diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema')
42 files changed, 21979 insertions, 9842 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp index babb8af..a8e6791 100644 --- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -63,7 +63,7 @@ namespace { } /// CheckUnreachable - Check for unreachable code. -static void CheckUnreachable(Sema &S, AnalysisContext &AC) { +static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) { UnreachableCodeHandler UC(S); reachable_code::FindUnreachableCode(AC, UC); } @@ -89,7 +89,7 @@ enum ControlFlowKind { /// return. We assume NeverFallThrough iff we never fall off the end of the /// statement but we may return. We assume that functions not marked noreturn /// will return. -static ControlFlowKind CheckFallThrough(AnalysisContext &AC) { +static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { CFG *cfg = AC.getCFG(); if (cfg == 0) return UnknownFallThrough; @@ -218,7 +218,7 @@ struct CheckFallThroughDiagnostics { unsigned diag_AlwaysFallThrough_HasNoReturn; unsigned diag_AlwaysFallThrough_ReturnsNonVoid; unsigned diag_NeverFallThroughOrReturn; - bool funMode; + enum { Function, Block, Lambda } funMode; SourceLocation FuncLoc; static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) { @@ -241,19 +241,8 @@ struct CheckFallThroughDiagnostics { // Don't suggest that template instantiations be marked "noreturn" bool isTemplateInstantiation = false; - if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func)) { - switch (Function->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - break; - - case TSK_ImplicitInstantiation: - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - isTemplateInstantiation = true; - break; - } - } + if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func)) + isTemplateInstantiation = Function->isTemplateInstantiation(); if (!isVirtualMethod && !isTemplateInstantiation) D.diag_NeverFallThroughOrReturn = @@ -261,7 +250,7 @@ struct CheckFallThroughDiagnostics { else D.diag_NeverFallThroughOrReturn = 0; - D.funMode = true; + D.funMode = Function; return D; } @@ -277,13 +266,28 @@ struct CheckFallThroughDiagnostics { diag::err_falloff_nonvoid_block; D.diag_NeverFallThroughOrReturn = diag::warn_suggest_noreturn_block; - D.funMode = false; + D.funMode = Block; + return D; + } + + static CheckFallThroughDiagnostics MakeForLambda() { + CheckFallThroughDiagnostics D; + D.diag_MaybeFallThrough_HasNoReturn = + diag::err_noreturn_lambda_has_return_expr; + D.diag_MaybeFallThrough_ReturnsNonVoid = + diag::warn_maybe_falloff_nonvoid_lambda; + D.diag_AlwaysFallThrough_HasNoReturn = + diag::err_noreturn_lambda_has_return_expr; + D.diag_AlwaysFallThrough_ReturnsNonVoid = + diag::warn_falloff_nonvoid_lambda; + D.diag_NeverFallThroughOrReturn = 0; + D.funMode = Lambda; return D; } bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid, bool HasNoReturn) const { - if (funMode) { + if (funMode == Function) { return (ReturnsVoid || D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function, FuncLoc) == DiagnosticsEngine::Ignored) @@ -295,9 +299,9 @@ struct CheckFallThroughDiagnostics { == DiagnosticsEngine::Ignored); } - // For blocks. - return ReturnsVoid && !HasNoReturn - && (!ReturnsVoid || + // For blocks / lambdas. + return ReturnsVoid && !HasNoReturn + && ((funMode == Lambda) || D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) == DiagnosticsEngine::Ignored); } @@ -312,7 +316,7 @@ struct CheckFallThroughDiagnostics { static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, const BlockExpr *blkExpr, const CheckFallThroughDiagnostics& CD, - AnalysisContext &AC) { + AnalysisDeclContext &AC) { bool ReturnsVoid = false; bool HasNoReturn = false; @@ -421,47 +425,27 @@ public: } 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 "); + return true; + } + // Don't issue a fixit if there is already an initializer. if (VD->getInit()) return false; - + // Suggest possible initialization (if any). - const char *initialization = 0; - QualType VariableTy = VD->getType().getCanonicalType(); - - if (VariableTy->isObjCObjectPointerType() || - VariableTy->isBlockPointerType()) { - // Check if 'nil' is defined. - if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil"))) - initialization = " = nil"; - else - initialization = " = 0"; - } - else if (VariableTy->isRealFloatingType()) - initialization = " = 0.0"; - else if (VariableTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus) - initialization = " = false"; - else if (VariableTy->isEnumeralType()) + const char *Init = S.getFixItZeroInitializerForType(VariableTy); + if (!Init) return false; - else if (VariableTy->isPointerType() || VariableTy->isMemberPointerType()) { - if (S.Context.getLangOptions().CPlusPlus0x) - initialization = " = nullptr"; - // Check if 'NULL' is defined. - else if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("NULL"))) - initialization = " = NULL"; - else - initialization = " = 0"; - } - else if (VariableTy->isScalarType()) - initialization = " = 0"; - - if (initialization) { - SourceLocation loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); - S.Diag(loc, diag::note_var_fixit_add_initialization) << VD->getDeclName() - << FixItHint::CreateInsertion(loc, initialization); - return true; - } - return false; + SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); + + S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName() + << FixItHint::CreateInsertion(Loc, Init); + return true; } /// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an @@ -512,10 +496,15 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, } } else { const BlockExpr *BE = cast<BlockExpr>(E); - S.Diag(BE->getLocStart(), - isAlwaysUninit ? diag::warn_uninit_var_captured_by_block - : diag::warn_maybe_uninit_var_captured_by_block) - << VD->getDeclName(); + if (VD->getType()->isBlockPointerType() && + !VD->hasAttr<BlocksAttr>()) + S.Diag(BE->getLocStart(), diag::warn_uninit_byref_blockvar_captured_by_block) + << VD->getDeclName(); + else + S.Diag(BE->getLocStart(), + isAlwaysUninit ? diag::warn_uninit_var_captured_by_block + : diag::warn_maybe_uninit_var_captured_by_block) + << VD->getDeclName(); } // Report where the variable was declared when the use wasn't within @@ -586,9 +575,10 @@ public: // Specially handle the case where we have uses of an uninitialized // variable, but the root cause is an idiomatic self-init. We want // to report the diagnostic at the self-init since that is the root cause. - if (!vec->empty() && hasSelfInit) + if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec)) DiagnoseUninitializedUse(S, vd, vd->getInit()->IgnoreParenCasts(), - true, /* alwaysReportSelfInit */ true); + /* isAlwaysUninit */ true, + /* alwaysReportSelfInit */ true); else { // Sort the uses by their SourceLocations. While not strictly // guaranteed to produce them in line/column order, this will provide @@ -610,6 +600,16 @@ public: } delete uses; } + +private: + static bool hasAlwaysUninitializedUse(const UsesVec* vec) { + for (UsesVec::const_iterator i = vec->begin(), e = vec->end(); i != e; ++i) { + if (i->second) { + return true; + } + } + return false; +} }; } @@ -619,49 +619,60 @@ public: //===----------------------------------------------------------------------===// namespace clang { namespace thread_safety { -typedef std::pair<SourceLocation, PartialDiagnostic> DelayedDiag; -typedef llvm::SmallVector<DelayedDiag, 4> DiagList; +typedef llvm::SmallVector<PartialDiagnosticAt, 1> OptionalNotes; +typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag; +typedef std::list<DelayedDiag> DiagList; struct SortDiagBySourceLocation { - Sema &S; - SortDiagBySourceLocation(Sema &S) : S(S) {} + SourceManager &SM; + SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {} bool operator()(const DelayedDiag &left, const DelayedDiag &right) { // Although this call will be slow, this is only called when outputting // multiple warnings. - return S.getSourceManager().isBeforeInTranslationUnit(left.first, - right.first); + return SM.isBeforeInTranslationUnit(left.first.first, right.first.first); } }; +namespace { class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler { Sema &S; DiagList Warnings; + SourceLocation FunLocation, FunEndLocation; // Helper functions void warnLockMismatch(unsigned DiagID, Name LockName, SourceLocation Loc) { - PartialDiagnostic Warning = S.PDiag(DiagID) << LockName; - Warnings.push_back(DelayedDiag(Loc, Warning)); + // 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); + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); } public: - ThreadSafetyReporter(Sema &S) : S(S) {} + ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL) + : S(S), FunLocation(FL), FunEndLocation(FEL) {} /// \brief Emit all buffered diagnostics in order of sourcelocation. /// We need to output diagnostics produced while iterating through /// the lockset in deterministic order, so this function orders diagnostics /// and outputs them. void emitDiagnostics() { - SortDiagBySourceLocation SortDiagBySL(S); - sort(Warnings.begin(), Warnings.end(), SortDiagBySL); + Warnings.sort(SortDiagBySourceLocation(S.getSourceManager())); for (DiagList::iterator I = Warnings.begin(), E = Warnings.end(); - I != E; ++I) - S.Diag(I->first, I->second); + 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); + } } void handleInvalidLockExp(SourceLocation Loc) { - PartialDiagnostic Warning = S.PDiag(diag::warn_cannot_resolve_lock) << Loc; - Warnings.push_back(DelayedDiag(Loc, Warning)); + 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); @@ -671,12 +682,13 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler { warnLockMismatch(diag::warn_double_lock, LockName, Loc); } - void handleMutexHeldEndOfScope(Name LockName, SourceLocation Loc, + void handleMutexHeldEndOfScope(Name LockName, SourceLocation LocLocked, + SourceLocation LocEndOfScope, LockErrorKind LEK){ unsigned DiagID = 0; switch (LEK) { case LEK_LockedSomePredecessors: - DiagID = diag::warn_lock_at_end_of_scope; + DiagID = diag::warn_lock_some_predecessors; break; case LEK_LockedSomeLoopIterations: DiagID = diag::warn_expecting_lock_held_on_loop; @@ -685,18 +697,22 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler { DiagID = diag::warn_no_unlock; break; } - warnLockMismatch(DiagID, LockName, Loc); + if (LocEndOfScope.isInvalid()) + LocEndOfScope = FunEndLocation; + + PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << LockName); + PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here)); + Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note))); } void handleExclusiveAndShared(Name LockName, SourceLocation Loc1, SourceLocation Loc2) { - PartialDiagnostic Warning = - S.PDiag(diag::warn_lock_exclusive_and_shared) << LockName; - PartialDiagnostic Note = - S.PDiag(diag::note_lock_exclusive_and_shared) << LockName; - Warnings.push_back(DelayedDiag(Loc1, Warning)); - Warnings.push_back(DelayedDiag(Loc2, Note)); + PartialDiagnosticAt Warning( + Loc1, S.PDiag(diag::warn_lock_exclusive_and_shared) << LockName); + PartialDiagnosticAt Note( + Loc2, S.PDiag(diag::note_lock_exclusive_and_shared) << LockName); + Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note))); } void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK, @@ -706,9 +722,9 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler { unsigned DiagID = POK == POK_VarAccess? diag::warn_variable_requires_any_lock: diag::warn_var_deref_requires_any_lock; - PartialDiagnostic Warning = S.PDiag(DiagID) - << D->getName() << getLockKindFromAccessKind(AK); - Warnings.push_back(DelayedDiag(Loc, Warning)); + PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) + << D->getName() << getLockKindFromAccessKind(AK)); + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); } void handleMutexNotHeld(const NamedDecl *D, ProtectedOperationKind POK, @@ -725,19 +741,20 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler { DiagID = diag::warn_fun_requires_lock; break; } - PartialDiagnostic Warning = S.PDiag(DiagID) - << D->getName() << LockName << LK; - Warnings.push_back(DelayedDiag(Loc, Warning)); + PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) + << D->getName() << LockName << LK); + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); } void handleFunExcludesLock(Name FunName, Name LockName, SourceLocation Loc) { - PartialDiagnostic Warning = - S.PDiag(diag::warn_fun_excludes_mutex) << FunName << LockName; - Warnings.push_back(DelayedDiag(Loc, Warning)); + PartialDiagnosticAt Warning(Loc, + S.PDiag(diag::warn_fun_excludes_mutex) << FunName << LockName); + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); } }; } } +} //===----------------------------------------------------------------------===// // AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based @@ -813,7 +830,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, const Stmt *Body = D->getBody(); assert(Body); - AnalysisContext AC(D, 0); + AnalysisDeclContext AC(/* AnalysisDeclContextManager */ 0, D, 0); // Don't generate EH edges for CallExprs as we'd like to avoid the n^2 // explosion for destrutors that can result and the compile time hit. @@ -828,8 +845,8 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, // prototyping, but we need a way for analyses to say what expressions they // expect to always be CFGElements and then fill in the BuildOptions // appropriately. This is essentially a layering violation. - if (P.enableCheckUnreachable) { - // Unreachable code analysis requires a linearized CFG. + if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis) { + // Unreachable code analysis and thread safety require a linearized CFG. AC.getCFGBuildOptions().setAllAlwaysAdd(); } else { @@ -868,8 +885,12 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, bool processed = false; if (const Stmt *stmt = i->stmt) { const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt); - assert(block); - if (CFGReverseBlockReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis()) { + CFGReverseBlockReachabilityAnalysis *cra = + AC.getCFGReachablityAnalysis(); + // FIXME: We should be able to assert that block is non-null, but + // the CFG analysis can skip potentially-evaluated expressions in + // edge cases; see test/Sema/vla-2.c. + if (block && cra) { // Can this block be reached from the entrance? if (cra->isReachable(&AC.getCFG()->getEntry(), block)) S.Diag(D.Loc, D.PD); @@ -892,17 +913,32 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, if (P.enableCheckFallThrough) { const CheckFallThroughDiagnostics &CD = (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock() - : CheckFallThroughDiagnostics::MakeForFunction(D)); + : (isa<CXXMethodDecl>(D) && + cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call && + cast<CXXMethodDecl>(D)->getParent()->isLambda()) + ? CheckFallThroughDiagnostics::MakeForLambda() + : CheckFallThroughDiagnostics::MakeForFunction(D)); CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC); } // Warning: check for unreachable code - if (P.enableCheckUnreachable) - CheckUnreachable(S, AC); + if (P.enableCheckUnreachable) { + // Only check for unreachable code on non-template instantiations. + // Different template instantiations can effectively change the control-flow + // and it is very difficult to prove that a snippet of code in a template + // is unreachable for all instantiations. + bool isTemplateInstantiation = false; + if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) + isTemplateInstantiation = Function->isTemplateInstantiation(); + if (!isTemplateInstantiation) + CheckUnreachable(S, AC); + } // Check for thread safety violations if (P.enableThreadSafetyAnalysis) { - thread_safety::ThreadSafetyReporter Reporter(S); + SourceLocation FL = AC.getDecl()->getLocation(); + SourceLocation FEL = AC.getDecl()->getLocEnd(); + thread_safety::ThreadSafetyReporter Reporter(S, FL, FEL); thread_safety::runThreadSafetyAnalysis(AC, Reporter); Reporter.emitDiagnostics(); } diff --git a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp index 13a0ede..f142ab4 100644 --- a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp @@ -101,135 +101,26 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { StringRef AttrName = Name->getName(); // Normalize the attribute name, __foo__ becomes foo. - if (AttrName.startswith("__") && AttrName.endswith("__")) + if (AttrName.startswith("__") && AttrName.endswith("__") && + AttrName.size() >= 4) AttrName = AttrName.substr(2, AttrName.size() - 4); return llvm::StringSwitch<AttributeList::Kind>(AttrName) - .Case("weak", AT_weak) - .Case("weakref", AT_weakref) - .Case("objc_arc_weak_reference_unavailable", AT_arc_weakref_unavailable) - .Case("pure", AT_pure) - .Case("mode", AT_mode) - .Case("used", AT_used) - .Case("alias", AT_alias) - .Case("align", AT_aligned) - .Case("cdecl", AT_cdecl) - .Case("const", AT_const) - .Case("__const", AT_const) // some GCC headers do contain this spelling - .Case("blocks", AT_blocks) - .Case("format", AT_format) - .Case("malloc", AT_malloc) - .Case("packed", AT_packed) - .Case("unused", AT_unused) - .Case("aligned", AT_aligned) - .Case("cleanup", AT_cleanup) - .Case("naked", AT_naked) - .Case("nodebug", AT_nodebug) - .Case("nonnull", AT_nonnull) - .Case("nothrow", AT_nothrow) - .Case("objc_gc", AT_objc_gc) - .Case("regparm", AT_regparm) - .Case("section", AT_section) - .Case("stdcall", AT_stdcall) - .Case("annotate", AT_annotate) - .Case("fastcall", AT_fastcall) - .Case("ibaction", AT_IBAction) - .Case("iboutlet", AT_IBOutlet) - .Case("iboutletcollection", AT_IBOutletCollection) - .Case("noreturn", AT_noreturn) - .Case("noinline", AT_noinline) - .Case("sentinel", AT_sentinel) - .Case("NSObject", AT_nsobject) - .Case("dllimport", AT_dllimport) - .Case("dllexport", AT_dllexport) - .Case("may_alias", AT_may_alias) - .Case("base_check", AT_base_check) - .Case("deprecated", AT_deprecated) - .Case("availability", AT_availability) - .Case("visibility", AT_visibility) - .Case("destructor", AT_destructor) - .Case("format_arg", AT_format_arg) - .Case("gnu_inline", AT_gnu_inline) - .Case("weak_import", AT_weak_import) - .Case("vecreturn", AT_vecreturn) - .Case("vector_size", AT_vector_size) - .Case("constructor", AT_constructor) - .Case("unavailable", AT_unavailable) - .Case("overloadable", AT_overloadable) + #include "clang/Sema/AttrParsedAttrKinds.inc" .Case("address_space", AT_address_space) - .Case("opencl_image_access", AT_opencl_image_access) - .Case("always_inline", AT_always_inline) - .Case("returns_twice", AT_returns_twice) + .Case("align", AT_aligned) // FIXME - should it be "aligned"? + .Case("base_check", AT_base_check) + .Case("bounded", IgnoredAttribute) // OpenBSD + .Case("__const", AT_const) // some GCC headers do contain this spelling + .Case("cf_returns_autoreleased", AT_cf_returns_autoreleased) + .Case("mode", AT_mode) .Case("vec_type_hint", IgnoredAttribute) - .Case("objc_exception", AT_objc_exception) - .Case("objc_method_family", AT_objc_method_family) - .Case("objc_returns_inner_pointer", AT_objc_returns_inner_pointer) .Case("ext_vector_type", AT_ext_vector_type) .Case("neon_vector_type", AT_neon_vector_type) .Case("neon_polyvector_type", AT_neon_polyvector_type) - .Case("transparent_union", AT_transparent_union) - .Case("analyzer_noreturn", AT_analyzer_noreturn) - .Case("warn_unused_result", AT_warn_unused_result) - .Case("carries_dependency", AT_carries_dependency) - .Case("ns_bridged", AT_ns_bridged) - .Case("ns_consumed", AT_ns_consumed) - .Case("ns_consumes_self", AT_ns_consumes_self) - .Case("ns_returns_autoreleased", AT_ns_returns_autoreleased) - .Case("ns_returns_not_retained", AT_ns_returns_not_retained) - .Case("ns_returns_retained", AT_ns_returns_retained) - .Case("cf_audited_transfer", AT_cf_audited_transfer) - .Case("cf_consumed", AT_cf_consumed) - .Case("cf_returns_not_retained", AT_cf_returns_not_retained) - .Case("cf_returns_retained", AT_cf_returns_retained) - .Case("cf_returns_autoreleased", AT_cf_returns_autoreleased) - .Case("cf_unknown_transfer", AT_cf_unknown_transfer) - .Case("ns_consumes_self", AT_ns_consumes_self) - .Case("ns_consumed", AT_ns_consumed) + .Case("opencl_image_access", AT_opencl_image_access) + .Case("objc_gc", AT_objc_gc) .Case("objc_ownership", AT_objc_ownership) - .Case("objc_precise_lifetime", AT_objc_precise_lifetime) - .Case("ownership_returns", AT_ownership_returns) - .Case("ownership_holds", AT_ownership_holds) - .Case("ownership_takes", AT_ownership_takes) - .Case("reqd_work_group_size", AT_reqd_wg_size) - .Case("init_priority", AT_init_priority) - .Case("no_instrument_function", AT_no_instrument_function) - .Case("thiscall", AT_thiscall) - .Case("bounded", IgnoredAttribute) // OpenBSD - .Case("pascal", AT_pascal) - .Case("__cdecl", AT_cdecl) - .Case("__stdcall", AT_stdcall) - .Case("__fastcall", AT_fastcall) - .Case("__thiscall", AT_thiscall) - .Case("__pascal", AT_pascal) - .Case("constant", AT_constant) - .Case("device", AT_device) - .Case("global", AT_global) - .Case("host", AT_host) - .Case("shared", AT_shared) - .Case("launch_bounds", AT_launch_bounds) - .Case("common", AT_common) - .Case("nocommon", AT_nocommon) - .Case("opencl_kernel_function", AT_opencl_kernel_function) - .Case("uuid", AT_uuid) - .Case("pcs", AT_pcs) - .Case("ms_struct", AT_MsStruct) - .Case("guarded_var", AT_guarded_var) - .Case("pt_guarded_var", AT_pt_guarded_var) - .Case("scoped_lockable", AT_scoped_lockable) - .Case("lockable", AT_lockable) - .Case("no_thread_safety_analysis", AT_no_thread_safety_analysis) - .Case("guarded_by", AT_guarded_by) - .Case("pt_guarded_by", AT_pt_guarded_by) - .Case("acquired_after", AT_acquired_after) - .Case("acquired_before", AT_acquired_before) - .Case("exclusive_lock_function", AT_exclusive_lock_function) - .Case("exclusive_locks_required", AT_exclusive_locks_required) - .Case("exclusive_trylock_function", AT_exclusive_trylock_function) - .Case("lock_returned", AT_lock_returned) - .Case("locks_excluded", AT_locks_excluded) - .Case("shared_lock_function", AT_shared_lock_function) - .Case("shared_locks_required", AT_shared_locks_required) - .Case("shared_trylock_function", AT_shared_trylock_function) - .Case("unlock_function", AT_unlock_function) + .Case("vector_size", AT_vector_size) .Default(UnknownAttribute); } diff --git a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp index da98603..ce9bbb9 100644 --- a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp @@ -18,6 +18,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/Lex/Preprocessor.h" #include "clang-c/Index.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/raw_ostream.h" @@ -71,8 +72,8 @@ bool CodeCompletionContext::wantConstructorResults() const { case CCC_ObjCCategoryName: return false; } - - return false; + + llvm_unreachable("Invalid CodeCompletionContext::Kind!"); } //===----------------------------------------------------------------------===// @@ -93,7 +94,6 @@ CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text) case CK_Optional: llvm_unreachable("Optional strings cannot be created from text"); - break; case CK_LeftParen: this->Text = "("; @@ -192,9 +192,12 @@ CodeCompletionString::CodeCompletionString(const Chunk *Chunks, unsigned Priority, CXAvailabilityKind Availability, const char **Annotations, - unsigned NumAnnotations) - : NumChunks(NumChunks), NumAnnotations(NumAnnotations) - , Priority(Priority), Availability(Availability) + unsigned NumAnnotations, + CXCursorKind ParentKind, + StringRef ParentName) + : NumChunks(NumChunks), NumAnnotations(NumAnnotations), + Priority(Priority), Availability(Availability), ParentKind(ParentKind), + ParentName(ParentName) { assert(NumChunks <= 0xffff); assert(NumAnnotations <= 0xffff); @@ -260,23 +263,137 @@ const char *CodeCompletionAllocator::CopyString(Twine String) { // FIXME: It would be more efficient to teach Twine to tell us its size and // then add a routine there to fill in an allocated char* with the contents // of the string. - llvm::SmallString<128> Data; + SmallString<128> Data; return CopyString(String.toStringRef(Data)); } +StringRef CodeCompletionTUInfo::getParentName(DeclContext *DC) { + NamedDecl *ND = dyn_cast<NamedDecl>(DC); + if (!ND) + return StringRef(); + + // Check whether we've already cached the parent name. + StringRef &CachedParentName = ParentNames[DC]; + if (!CachedParentName.empty()) + return CachedParentName; + + // If we already processed this DeclContext and assigned empty to it, the + // data pointer will be non-null. + if (CachedParentName.data() != 0) + return StringRef(); + + // Find the interesting names. + llvm::SmallVector<DeclContext *, 2> Contexts; + while (DC && !DC->isFunctionOrMethod()) { + if (NamedDecl *ND = dyn_cast<NamedDecl>(DC)) { + if (ND->getIdentifier()) + Contexts.push_back(DC); + } + + DC = DC->getParent(); + } + + { + llvm::SmallString<128> S; + llvm::raw_svector_ostream OS(S); + bool First = true; + for (unsigned I = Contexts.size(); I != 0; --I) { + if (First) + First = false; + else { + OS << "::"; + } + + DeclContext *CurDC = Contexts[I-1]; + if (ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC)) + CurDC = CatImpl->getCategoryDecl(); + + if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) { + ObjCInterfaceDecl *Interface = Cat->getClassInterface(); + if (!Interface) { + // Assign an empty StringRef but with non-null data to distinguish + // between empty because we didn't process the DeclContext yet. + CachedParentName = StringRef((const char *)~0U, 0); + return StringRef(); + } + + OS << Interface->getName() << '(' << Cat->getName() << ')'; + } else { + OS << cast<NamedDecl>(CurDC)->getName(); + } + } + + CachedParentName = AllocatorRef->CopyString(OS.str()); + } + + return CachedParentName; +} + CodeCompletionString *CodeCompletionBuilder::TakeString() { - void *Mem = Allocator.Allocate( + void *Mem = getAllocator().Allocate( sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size() + sizeof(const char *) * Annotations.size(), llvm::alignOf<CodeCompletionString>()); CodeCompletionString *Result = new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(), Priority, Availability, - Annotations.data(), Annotations.size()); + Annotations.data(), Annotations.size(), + ParentKind, ParentName); Chunks.clear(); return Result; } +void CodeCompletionBuilder::AddTypedTextChunk(const char *Text) { + Chunks.push_back(Chunk(CodeCompletionString::CK_TypedText, Text)); +} + +void CodeCompletionBuilder::AddTextChunk(const char *Text) { + Chunks.push_back(Chunk::CreateText(Text)); +} + +void CodeCompletionBuilder::AddOptionalChunk(CodeCompletionString *Optional) { + Chunks.push_back(Chunk::CreateOptional(Optional)); +} + +void CodeCompletionBuilder::AddPlaceholderChunk(const char *Placeholder) { + Chunks.push_back(Chunk::CreatePlaceholder(Placeholder)); +} + +void CodeCompletionBuilder::AddInformativeChunk(const char *Text) { + Chunks.push_back(Chunk::CreateInformative(Text)); +} + +void CodeCompletionBuilder::AddResultTypeChunk(const char *ResultType) { + Chunks.push_back(Chunk::CreateResultType(ResultType)); +} + +void +CodeCompletionBuilder::AddCurrentParameterChunk(const char *CurrentParameter) { + Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter)); +} + +void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK, + const char *Text) { + Chunks.push_back(Chunk(CK, Text)); +} + +void CodeCompletionBuilder::addParentContext(DeclContext *DC) { + if (DC->isTranslationUnit()) { + ParentKind = CXCursor_TranslationUnit; + return; + } + + if (DC->isFunctionOrMethod()) + return; + + NamedDecl *ND = dyn_cast<NamedDecl>(DC); + if (!ND) + return; + + ParentKind = getCursorKindForDecl(ND); + ParentName = getCodeCompletionTUInfo().getParentName(DC); +} + unsigned CodeCompletionResult::getPriorityFromDecl(NamedDecl *ND) { if (!ND) return CCP_Unlikely; @@ -330,8 +447,8 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { case CK_FunctionType: return Type; } - - return 0; + + llvm_unreachable("Invalid CandidateKind!"); } //===----------------------------------------------------------------------===// @@ -356,7 +473,8 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, if (Results[I].Hidden) OS << " (Hidden)"; if (CodeCompletionString *CCS - = Results[I].CreateCodeCompletionString(SemaRef, Allocator)) { + = Results[I].CreateCodeCompletionString(SemaRef, getAllocator(), + CCTUInfo)) { OS << " : " << CCS->getAsString(); } @@ -370,7 +488,8 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, case CodeCompletionResult::RK_Macro: { OS << Results[I].Macro->getName(); if (CodeCompletionString *CCS - = Results[I].CreateCodeCompletionString(SemaRef, Allocator)) { + = Results[I].CreateCodeCompletionString(SemaRef, getAllocator(), + CCTUInfo)) { OS << " : " << CCS->getAsString(); } OS << '\n'; @@ -394,17 +513,32 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, for (unsigned I = 0; I != NumCandidates; ++I) { if (CodeCompletionString *CCS = Candidates[I].CreateSignatureString(CurrentArg, SemaRef, - Allocator)) { + getAllocator(), CCTUInfo)) { OS << "OVERLOAD: " << CCS->getAsString() << "\n"; } } } +/// \brief Retrieve the effective availability of the given declaration. +static AvailabilityResult getDeclAvailability(Decl *D) { + AvailabilityResult AR = D->getAvailability(); + if (isa<EnumConstantDecl>(D)) + AR = std::max(AR, cast<Decl>(D->getDeclContext())->getAvailability()); + return AR; +} + void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) { switch (Kind) { - case RK_Declaration: + case RK_Pattern: + if (!Declaration) { + // Do nothing: Patterns can come with cursor kinds! + break; + } + // Fall through + + case RK_Declaration: { // Set the availability based on attributes. - switch (Declaration->getAvailability()) { + switch (getDeclAvailability(Declaration)) { case AR_Available: case AR_NotYetIntroduced: Availability = CXAvailability_Available; @@ -424,9 +558,19 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) { Availability = CXAvailability_NotAvailable; CursorKind = getCursorKindForDecl(Declaration); - if (CursorKind == CXCursor_UnexposedDecl) - CursorKind = CXCursor_NotImplemented; + if (CursorKind == CXCursor_UnexposedDecl) { + // FIXME: Forward declarations of Objective-C classes and protocols + // are not directly exposed, but we want code completion to treat them + // like a definition. + if (isa<ObjCInterfaceDecl>(Declaration)) + CursorKind = CXCursor_ObjCInterfaceDecl; + else if (isa<ObjCProtocolDecl>(Declaration)) + CursorKind = CXCursor_ObjCProtocolDecl; + else + CursorKind = CXCursor_NotImplemented; + } break; + } case RK_Macro: Availability = CXAvailability_Available; @@ -436,11 +580,7 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) { case RK_Keyword: Availability = CXAvailability_Available; CursorKind = CXCursor_NotImplemented; - break; - - case RK_Pattern: - // Do nothing: Patterns can come with cursor kinds! - break; + break; } if (!Accessible) diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp index f0a763e..b531acc 100644 --- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp @@ -15,6 +15,7 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/LocInfoType.h" #include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/SemaDiagnostic.h" #include "clang/Sema/Sema.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" @@ -150,6 +151,9 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, unsigned TypeQuals, bool RefQualifierIsLvalueRef, SourceLocation RefQualifierLoc, + SourceLocation ConstQualifierLoc, + SourceLocation + VolatileQualifierLoc, SourceLocation MutableLoc, ExceptionSpecificationType ESpecType, @@ -176,6 +180,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, I.Fun.ArgInfo = 0; I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef; I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding(); + I.Fun.ConstQualifierLoc = ConstQualifierLoc.getRawEncoding(); + I.Fun.VolatileQualifierLoc = VolatileQualifierLoc.getRawEncoding(); I.Fun.MutableLoc = MutableLoc.getRawEncoding(); I.Fun.ExceptionSpecType = ESpecType; I.Fun.ExceptionSpecLoc = ESpecLoc.getRawEncoding(); @@ -239,7 +245,6 @@ bool Declarator::isDeclarationOfFunction() const { return false; } llvm_unreachable("Invalid type chunk"); - return false; } switch (DS.getTypeSpecType()) { @@ -259,6 +264,7 @@ bool Declarator::isDeclarationOfFunction() const { case TST_float: case TST_half: case TST_int: + case TST_int128: case TST_struct: case TST_union: case TST_unknown_anytype: @@ -289,8 +295,8 @@ bool Declarator::isDeclarationOfFunction() const { return QT->isFunctionType(); } } - - return false; + + llvm_unreachable("Invalid TypeSpecType!"); } /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this @@ -374,6 +380,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) { case DeclSpec::TST_char16: return "char16_t"; case DeclSpec::TST_char32: return "char32_t"; case DeclSpec::TST_int: return "int"; + case DeclSpec::TST_int128: return "__int128"; case DeclSpec::TST_half: return "half"; case DeclSpec::TST_float: return "float"; case DeclSpec::TST_double: return "double"; @@ -416,7 +423,7 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc, // It seems sensible to prohibit private_extern too // The cl_clang_storage_class_specifiers extension enables support for // these storage-class specifiers. - if (S.getLangOptions().OpenCL && + if (S.getLangOpts().OpenCL && !S.getOpenCLOptions().cl_clang_storage_class_specifiers) { switch (SC) { case SCS_extern: @@ -435,7 +442,7 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc, if (StorageClassSpec != SCS_unspecified) { // Maybe this is an attempt to use C++0x 'auto' outside of C++0x mode. bool isInvalid = true; - if (TypeSpecType == TST_unspecified && S.getLangOptions().CPlusPlus) { + if (TypeSpecType == TST_unspecified && S.getLangOpts().CPlusPlus) { if (SC == SCS_auto) return SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID); if (StorageClassSpec == SCS_auto) { @@ -813,7 +820,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) { if (TypeSpecSign != TSS_unspecified) { if (TypeSpecType == TST_unspecified) TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int. - else if (TypeSpecType != TST_int && + 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); @@ -861,7 +868,8 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) { TypeSpecType = TST_double; // _Complex -> _Complex double. } else if (TypeSpecType == TST_int || TypeSpecType == TST_char) { // Note that this intentionally doesn't include _Complex _Bool. - Diag(D, TSTLoc, diag::ext_integer_complex); + if (!PP.getLangOpts().CPlusPlus) + 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); @@ -874,7 +882,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) { // class specifier, then assume this is an attempt to use C++0x's 'auto' // type specifier. // FIXME: Does Microsoft really support implicit int in C++? - if (PP.getLangOptions().CPlusPlus && !PP.getLangOptions().MicrosoftExt && + if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().MicrosoftExt && TypeSpecType == TST_unspecified && StorageClassSpec == SCS_auto) { TypeSpecType = TST_auto; StorageClassSpec = StorageClassSpecAsWritten = SCS_unspecified; @@ -883,12 +891,17 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) { } // Diagnose if we've recovered from an ill-formed 'auto' storage class // specifier in a pre-C++0x dialect of C++. - if (!PP.getLangOptions().CPlusPlus0x && TypeSpecType == TST_auto) + if (!PP.getLangOpts().CPlusPlus0x && TypeSpecType == TST_auto) Diag(D, TSTLoc, diag::ext_auto_type_specifier); - if (PP.getLangOptions().CPlusPlus && !PP.getLangOptions().CPlusPlus0x && + if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().CPlusPlus0x && StorageClassSpec == SCS_auto) Diag(D, StorageClassSpecLoc, diag::warn_auto_storage_class) << FixItHint::CreateRemoval(StorageClassSpecLoc); + if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32) + Diag(D, TSTLoc, diag::warn_cxx98_compat_unicode_type) + << (TypeSpecType == TST_char16 ? "char16_t" : "char32_t"); + if (Constexpr_specified) + Diag(D, ConstexprLoc, diag::warn_cxx98_compat_constexpr); // C++ [class.friend]p6: // No storage-class-specifier shall appear in the decl-specifier-seq diff --git a/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp index d6c1ad1..876f9d7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp @@ -20,13 +20,15 @@ using namespace clang; using namespace sema; DelayedDiagnostic DelayedDiagnostic::makeDeprecation(SourceLocation Loc, - const NamedDecl *D, - StringRef Msg) { + const NamedDecl *D, + const ObjCInterfaceDecl *UnknownObjCClass, + StringRef Msg) { DelayedDiagnostic DD; DD.Kind = Deprecation; DD.Triggered = false; DD.Loc = Loc; DD.DeprecationData.Decl = D; + DD.DeprecationData.UnknownObjCClass = UnknownObjCClass; char *MessageData = 0; if (Msg.size()) { MessageData = new char [Msg.size()]; diff --git a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp index a643267..4d62cab 100644 --- a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp @@ -15,7 +15,10 @@ #include "clang/Sema/IdentifierResolver.h" #include "clang/Sema/Scope.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" #include "clang/Basic/LangOptions.h" +#include "clang/Lex/ExternalPreprocessorSource.h" +#include "clang/Lex/Preprocessor.h" using namespace clang; @@ -93,9 +96,11 @@ IdentifierResolver::IdDeclInfo::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { // IdentifierResolver Implementation //===----------------------------------------------------------------------===// -IdentifierResolver::IdentifierResolver(const LangOptions &langOpt) - : LangOpt(langOpt), IdDeclInfos(new IdDeclInfoMap) { +IdentifierResolver::IdentifierResolver(Preprocessor &PP) + : LangOpt(PP.getLangOpts()), PP(PP), + IdDeclInfos(new IdDeclInfoMap) { } + IdentifierResolver::~IdentifierResolver() { delete IdDeclInfos; } @@ -108,7 +113,7 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, bool ExplicitInstantiationOrSpecialization) const { Ctx = Ctx->getRedeclContext(); - if (Ctx->isFunctionOrMethod()) { + if (Ctx->isFunctionOrMethod() || S->isFunctionPrototypeScope()) { // Ignore the scopes associated within transparent declaration contexts. while (S->getEntity() && ((DeclContext *)S->getEntity())->isTransparentContext()) @@ -146,7 +151,7 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, void IdentifierResolver::AddDecl(NamedDecl *D) { DeclarationName Name = D->getDeclName(); if (IdentifierInfo *II = Name.getAsIdentifierInfo()) - II->setIsFromAST(false); + updatingIdentifier(*II); void *Ptr = Name.getFETokenInfo<void>(); @@ -170,6 +175,9 @@ void IdentifierResolver::AddDecl(NamedDecl *D) { void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) { DeclarationName Name = D->getDeclName(); + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + updatingIdentifier(*II); + void *Ptr = Name.getFETokenInfo<void>(); if (!Ptr) { @@ -194,9 +202,6 @@ void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) { return; } - if (IdentifierInfo *II = Name.getAsIdentifierInfo()) - II->setIsFromAST(false); - // General case: insert the declaration at the appropriate point in the // list, which already has at least two elements. IdDeclInfo *IDI = toIdDeclInfo(Ptr); @@ -212,7 +217,7 @@ void IdentifierResolver::RemoveDecl(NamedDecl *D) { assert(D && "null param passed"); DeclarationName Name = D->getDeclName(); if (IdentifierInfo *II = Name.getAsIdentifierInfo()) - II->setIsFromAST(false); + updatingIdentifier(*II); void *Ptr = Name.getFETokenInfo<void>(); @@ -233,7 +238,7 @@ bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { DeclarationName Name = Old->getDeclName(); if (IdentifierInfo *II = Name.getAsIdentifierInfo()) - II->setIsFromAST(false); + updatingIdentifier(*II); void *Ptr = Name.getFETokenInfo<void>(); @@ -254,6 +259,9 @@ bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { /// begin - Returns an iterator for decls with name 'Name'. IdentifierResolver::iterator IdentifierResolver::begin(DeclarationName Name) { + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + readingIdentifier(*II); + void *Ptr = Name.getFETokenInfo<void>(); if (!Ptr) return end(); @@ -269,27 +277,133 @@ IdentifierResolver::begin(DeclarationName Name) { return end(); } -void IdentifierResolver::AddDeclToIdentifierChain(IdentifierInfo *II, - NamedDecl *D) { - II->setIsFromAST(false); - void *Ptr = II->getFETokenInfo<void>(); +namespace { + enum DeclMatchKind { + DMK_Different, + DMK_Replace, + DMK_Ignore + }; +} - if (!Ptr) { - II->setFETokenInfo(D); - return; +/// \brief Compare two declarations to see whether they are different or, +/// if they are the same, whether the new declaration should replace the +/// existing declaration. +static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) { + // If the declarations are identical, ignore the new one. + if (Existing == New) + return DMK_Ignore; + + // If the declarations have different kinds, they're obviously different. + if (Existing->getKind() != New->getKind()) + return DMK_Different; + + // If the declarations are redeclarations of each other, keep the newest one. + if (Existing->getCanonicalDecl() == New->getCanonicalDecl()) { + // 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) + return DMK_Replace; + + if (RD->isCanonicalDecl()) + break; + } + + return DMK_Ignore; } + + return DMK_Different; +} +bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){ + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + readingIdentifier(*II); + + void *Ptr = Name.getFETokenInfo<void>(); + + if (!Ptr) { + Name.setFETokenInfo(D); + return true; + } + IdDeclInfo *IDI; - + if (isDeclPtr(Ptr)) { - II->setFETokenInfo(NULL); - IDI = &(*IdDeclInfos)[II]; NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr); - IDI->AddDecl(PrevD); - } else - IDI = toIdDeclInfo(Ptr); + + switch (compareDeclarations(PrevD, D)) { + case DMK_Different: + break; + + case DMK_Ignore: + return false; + + case DMK_Replace: + Name.setFETokenInfo(D); + return true; + } + + Name.setFETokenInfo(NULL); + IDI = &(*IdDeclInfos)[Name]; + + // If the existing declaration is not visible in translation unit scope, + // then add the new top-level declaration first. + if (!PrevD->getDeclContext()->getRedeclContext()->isTranslationUnit()) { + IDI->AddDecl(D); + IDI->AddDecl(PrevD); + } else { + IDI->AddDecl(PrevD); + IDI->AddDecl(D); + } + return true; + } + + IDI = toIdDeclInfo(Ptr); + // See whether this declaration is identical to any existing declarations. + // If not, find the right place to insert it. + for (IdDeclInfo::DeclsTy::iterator I = IDI->decls_begin(), + IEnd = IDI->decls_end(); + I != IEnd; ++I) { + + switch (compareDeclarations(*I, D)) { + case DMK_Different: + break; + + case DMK_Ignore: + return false; + + case DMK_Replace: + *I = D; + return true; + } + + if (!(*I)->getDeclContext()->getRedeclContext()->isTranslationUnit()) { + // We've found a declaration that is not visible from the translation + // unit (it's in an inner scope). Insert our declaration here. + IDI->InsertDecl(I, D); + return true; + } + } + + // Add the declaration to the end. IDI->AddDecl(D); + return true; +} + +void IdentifierResolver::readingIdentifier(IdentifierInfo &II) { + if (II.isOutOfDate()) + PP.getExternalSource()->updateOutOfDateIdentifier(II); +} + +void IdentifierResolver::updatingIdentifier(IdentifierInfo &II) { + if (II.isOutOfDate()) + PP.getExternalSource()->updateOutOfDateIdentifier(II); + + if (II.isFromAST()) + II.setChangedSinceDeserialization(); } //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp index 3e74dfc..ab786c6 100644 --- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp @@ -42,10 +42,10 @@ class JumpScopeChecker { /// the parent scope is the function body. unsigned ParentScope; - /// InDiag - The diagnostic to emit if there is a jump into this scope. + /// InDiag - The note to emit if there is a jump into this scope. unsigned InDiag; - /// OutDiag - The diagnostic to emit if there is an indirect jump out + /// OutDiag - The note to emit if there is an indirect jump out /// of this scope. Direct jumps always clean up their current scope /// in an orderly way. unsigned OutDiag; @@ -74,10 +74,12 @@ private: void VerifyJumps(); void VerifyIndirectJumps(); + void NoteJumpIntoScopes(ArrayRef<unsigned> ToScopes); void DiagnoseIndirectJump(IndirectGotoStmt *IG, unsigned IGScope, LabelDecl *Target, unsigned TargetScope); void CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc, - unsigned JumpDiag, unsigned JumpDiagWarning); + unsigned JumpDiag, unsigned JumpDiagWarning, + unsigned JumpDiagCXX98Compat); unsigned GetDeepestCommonScope(unsigned A, unsigned B); }; @@ -133,7 +135,7 @@ static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) { return ScopePair(diag::note_protected_by_cleanup, diag::note_exits_cleanup); - if (Context.getLangOptions().ObjCAutoRefCount && VD->hasLocalStorage()) { + if (Context.getLangOpts().ObjCAutoRefCount && VD->hasLocalStorage()) { switch (VD->getType().getObjCLifetime()) { case Qualifiers::OCL_None: case Qualifiers::OCL_ExplicitNone: @@ -147,8 +149,8 @@ static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) { } } - if (Context.getLangOptions().CPlusPlus && VD->hasLocalStorage()) { - // C++0x [stmt.dcl]p3: + if (Context.getLangOpts().CPlusPlus && VD->hasLocalStorage()) { + // 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 // is ill-formed unless the variable has scalar type, class type with @@ -177,13 +179,12 @@ static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) { record = ctor->getParent(); if (ctor->isTrivial() && ctor->isDefaultConstructor()) { - if (Context.getLangOptions().CPlusPlus0x) { - inDiagToUse = (record->hasTrivialDestructor() ? 0 : - diag::note_protected_by_variable_nontriv_destructor); - } else { - if (record->isPOD()) - inDiagToUse = 0; - } + if (!record->hasTrivialDestructor()) + inDiagToUse = diag::note_protected_by_variable_nontriv_destructor; + else if (!record->isPOD()) + inDiagToUse = diag::note_protected_by_variable_non_pod; + else + inDiagToUse = 0; } } else if (VD->getType()->isArrayType()) { record = VD->getType()->getBaseElementTypeUnsafe() @@ -258,7 +259,7 @@ void JumpScopeChecker::BuildScopeInformation(VarDecl *D, diag::note_exits_block_captures_weak); break; case QualType::DK_none: - llvm_unreachable("no-liftime captured variable"); + llvm_unreachable("non-lifetime captured variable"); } SourceLocation Loc = D->getLocation(); if (Loc.isInvalid()) @@ -477,7 +478,8 @@ 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::warn_goto_into_protected_scope, + diag::warn_cxx98_compat_goto_into_protected_scope); continue; } @@ -486,7 +488,8 @@ 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::warn_goto_into_protected_scope, + diag::warn_cxx98_compat_goto_into_protected_scope); continue; } @@ -495,7 +498,8 @@ void JumpScopeChecker::VerifyJumps() { SC = SC->getNextSwitchCase()) { assert(LabelAndGotoScopes.count(SC) && "Case not visited?"); CheckJump(SS, SC, SC->getLocStart(), - diag::err_switch_into_protected_scope, 0); + diag::err_switch_into_protected_scope, 0, + diag::warn_cxx98_compat_switch_into_protected_scope); } } } @@ -639,6 +643,39 @@ void JumpScopeChecker::VerifyIndirectJumps() { } } +/// Return true if a particular error+note combination must be downgraded to a +/// warning in Microsoft mode. +static bool IsMicrosoftJumpWarning(unsigned JumpDiag, unsigned InDiagNote) { + return (JumpDiag == diag::err_goto_into_protected_scope && + (InDiagNote == diag::note_protected_by_variable_init || + InDiagNote == diag::note_protected_by_variable_nontriv_destructor)); +} + +/// Return true if a particular note should be downgraded to a compatibility +/// warning in C++11 mode. +static bool IsCXX98CompatWarning(Sema &S, unsigned InDiagNote) { + return S.getLangOpts().CPlusPlus0x && + InDiagNote == diag::note_protected_by_variable_non_pod; +} + +/// Produce primary diagnostic for an indirect jump statement. +static void DiagnoseIndirectJumpStmt(Sema &S, IndirectGotoStmt *Jump, + LabelDecl *Target, bool &Diagnosed) { + if (Diagnosed) + return; + S.Diag(Jump->getGotoLoc(), diag::err_indirect_goto_in_protected_scope); + S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target); + Diagnosed = true; +} + +/// Produce note diagnostics for a jump into a protected scope. +void JumpScopeChecker::NoteJumpIntoScopes(ArrayRef<unsigned> ToScopes) { + assert(!ToScopes.empty()); + 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); +} + /// Diagnose an indirect jump which is known to cross scopes. void JumpScopeChecker::DiagnoseIndirectJump(IndirectGotoStmt *Jump, unsigned JumpScope, @@ -646,36 +683,41 @@ void JumpScopeChecker::DiagnoseIndirectJump(IndirectGotoStmt *Jump, unsigned TargetScope) { assert(JumpScope != TargetScope); - S.Diag(Jump->getGotoLoc(), diag::err_indirect_goto_in_protected_scope); - S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target); - unsigned Common = GetDeepestCommonScope(JumpScope, TargetScope); + bool Diagnosed = false; // Walk out the scope chain until we reach the common ancestor. for (unsigned I = JumpScope; I != Common; I = Scopes[I].ParentScope) - if (Scopes[I].OutDiag) + if (Scopes[I].OutDiag) { + DiagnoseIndirectJumpStmt(S, Jump, Target, Diagnosed); S.Diag(Scopes[I].Loc, Scopes[I].OutDiag); + } + + SmallVector<unsigned, 10> ToScopesCXX98Compat; // Now walk into the scopes containing the label whose address was taken. for (unsigned I = TargetScope; I != Common; I = Scopes[I].ParentScope) - if (Scopes[I].InDiag) + if (IsCXX98CompatWarning(S, Scopes[I].InDiag)) + ToScopesCXX98Compat.push_back(I); + else if (Scopes[I].InDiag) { + DiagnoseIndirectJumpStmt(S, Jump, Target, Diagnosed); S.Diag(Scopes[I].Loc, Scopes[I].InDiag); -} + } -/// Return true if a particular error+note combination must be downgraded -/// to a warning in Microsoft mode. -static bool IsMicrosoftJumpWarning(unsigned JumpDiag, unsigned InDiagNote) -{ - return (JumpDiag == diag::err_goto_into_protected_scope && - (InDiagNote == diag::note_protected_by_variable_init || - InDiagNote == diag::note_protected_by_variable_nontriv_destructor)); + // Diagnose this jump if it would be ill-formed in C++98. + if (!Diagnosed && !ToScopesCXX98Compat.empty()) { + S.Diag(Jump->getGotoLoc(), + diag::warn_cxx98_compat_indirect_goto_in_protected_scope); + S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target); + NoteJumpIntoScopes(ToScopesCXX98Compat); + } } - /// CheckJump - Validate that the specified jump statement is valid: that it is /// jumping within or out of its current scope, not into a deeper one. void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc, - unsigned JumpDiagError, unsigned JumpDiagWarning) { + unsigned JumpDiagError, unsigned JumpDiagWarning, + unsigned JumpDiagCXX98Compat) { assert(LabelAndGotoScopes.count(From) && "Jump didn't get added to scopes?"); unsigned FromScope = LabelAndGotoScopes[From]; @@ -691,12 +733,15 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc, if (CommonScope == ToScope) return; // Pull out (and reverse) any scopes we might need to diagnose skipping. + SmallVector<unsigned, 10> ToScopesCXX98Compat; SmallVector<unsigned, 10> ToScopesError; SmallVector<unsigned, 10> ToScopesWarning; for (unsigned I = ToScope; I != CommonScope; I = Scopes[I].ParentScope) { - if (S.getLangOptions().MicrosoftMode && JumpDiagWarning != 0 && + if (S.getLangOpts().MicrosoftMode && JumpDiagWarning != 0 && IsMicrosoftJumpWarning(JumpDiagError, Scopes[I].InDiag)) ToScopesWarning.push_back(I); + else if (IsCXX98CompatWarning(S, Scopes[I].InDiag)) + ToScopesCXX98Compat.push_back(I); else if (Scopes[I].InDiag) ToScopesError.push_back(I); } @@ -704,16 +749,19 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc, // Handle warnings. if (!ToScopesWarning.empty()) { S.Diag(DiagLoc, JumpDiagWarning); - for (unsigned i = 0, e = ToScopesWarning.size(); i != e; ++i) - S.Diag(Scopes[ToScopesWarning[i]].Loc, Scopes[ToScopesWarning[i]].InDiag); + NoteJumpIntoScopes(ToScopesWarning); } // Handle errors. if (!ToScopesError.empty()) { S.Diag(DiagLoc, JumpDiagError); - // Emit diagnostics note for whatever is left in ToScopesError. - for (unsigned i = 0, e = ToScopesError.size(); i != e; ++i) - S.Diag(Scopes[ToScopesError[i]].Loc, Scopes[ToScopesError[i]].InDiag); + NoteJumpIntoScopes(ToScopesError); + } + + // Handle -Wc++98-compat warnings if the jump is well-formed. + if (ToScopesError.empty() && !ToScopesCXX98Compat.empty()) { + S.Diag(DiagLoc, JumpDiagCXX98Compat); + NoteJumpIntoScopes(ToScopesCXX98Compat); } } diff --git a/contrib/llvm/tools/clang/lib/Sema/MultiInitializer.cpp b/contrib/llvm/tools/clang/lib/Sema/MultiInitializer.cpp deleted file mode 100644 index 8bd2213..0000000 --- a/contrib/llvm/tools/clang/lib/Sema/MultiInitializer.cpp +++ /dev/null @@ -1,92 +0,0 @@ -//===--- MultiInitializer.cpp - Initializer expression group ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the MultiInitializer class, which can represent a list -// initializer or a parentheses-wrapped group of expressions in a C++ member -// initializer. -// -//===----------------------------------------------------------------------===// - -#include "clang/Sema/MultiInitializer.h" -#include "clang/Sema/Initialization.h" -#include "clang/Sema/Sema.h" -#include "clang/AST/Expr.h" - -using namespace clang; - -InitListExpr *MultiInitializer::getInitList() const { - return cast<InitListExpr>(InitListOrExpressions.get<Expr*>()); -} - -SourceLocation MultiInitializer::getStartLoc() const { - return isInitializerList() ? getInitList()->getLBraceLoc() : LParenLoc; -} - -SourceLocation MultiInitializer::getEndLoc() const { - return isInitializerList() ? getInitList()->getRBraceLoc() : RParenLoc; -} - -MultiInitializer::iterator MultiInitializer::begin() const { - return isInitializerList() ? getInitList()->getInits() : getExpressions(); -} - -MultiInitializer::iterator MultiInitializer::end() const { - if (isInitializerList()) { - InitListExpr *ILE = getInitList(); - return ILE->getInits() + ILE->getNumInits(); - } - return getExpressions() + NumInitializers; -} - -bool MultiInitializer::isTypeDependent() const { - if (isInitializerList()) - return getInitList()->isTypeDependent(); - for (iterator I = begin(), E = end(); I != E; ++I) { - if ((*I)->isTypeDependent()) - return true; - } - return false; -} - -bool MultiInitializer::DiagnoseUnexpandedParameterPack(Sema &SemaRef) const { - if (isInitializerList()) - return SemaRef.DiagnoseUnexpandedParameterPack(getInitList()); - for (iterator I = begin(), E = end(); I != E; ++I) { - if (SemaRef.DiagnoseUnexpandedParameterPack(*I)) - return true; - } - return false; -} - -Expr *MultiInitializer::CreateInitExpr(ASTContext &Ctx, QualType T) const { - if (isInitializerList()) - return InitListOrExpressions.get<Expr*>(); - - return new (Ctx) ParenListExpr(Ctx, LParenLoc, getExpressions(), - NumInitializers, RParenLoc, T); -} - -ExprResult MultiInitializer::PerformInit(Sema &SemaRef, - InitializedEntity Entity, - InitializationKind Kind) const { - Expr *Single; - Expr **Args; - unsigned NumArgs; - if (isInitializerList()) { - Single = InitListOrExpressions.get<Expr*>(); - Args = &Single; - NumArgs = 1; - } else { - Args = getExpressions(); - NumArgs = NumInitializers; - } - InitializationSequence InitSeq(SemaRef, Entity, Kind, Args, NumArgs); - return InitSeq.Perform(SemaRef, Entity, Kind, - MultiExprArg(SemaRef, Args, NumArgs), 0); -} diff --git a/contrib/llvm/tools/clang/lib/Sema/Scope.cpp b/contrib/llvm/tools/clang/lib/Sema/Scope.cpp index 833a59f..10f12ce 100644 --- a/contrib/llvm/tools/clang/lib/Sema/Scope.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/Scope.cpp @@ -19,23 +19,28 @@ using namespace clang; void Scope::Init(Scope *parent, unsigned flags) { AnyParent = parent; Flags = flags; - + + if (parent && !(flags & FnScope)) { + BreakParent = parent->BreakParent; + ContinueParent = parent->ContinueParent; + } else { + // Control scopes do not contain the contents of nested function scopes for + // control flow purposes. + BreakParent = ContinueParent = 0; + } + if (parent) { Depth = parent->Depth + 1; PrototypeDepth = parent->PrototypeDepth; PrototypeIndex = 0; FnParent = parent->FnParent; - BreakParent = parent->BreakParent; - ContinueParent = parent->ContinueParent; - ControlParent = parent->ControlParent; BlockParent = parent->BlockParent; TemplateParamParent = parent->TemplateParamParent; } else { Depth = 0; PrototypeDepth = 0; PrototypeIndex = 0; - FnParent = BreakParent = ContinueParent = BlockParent = 0; - ControlParent = 0; + FnParent = BlockParent = 0; TemplateParamParent = 0; } @@ -43,7 +48,6 @@ void Scope::Init(Scope *parent, unsigned flags) { if (flags & FnScope) FnParent = this; if (flags & BreakScope) BreakParent = this; if (flags & ContinueScope) ContinueParent = this; - if (flags & ControlScope) ControlParent = this; if (flags & BlockScope) BlockParent = this; if (flags & TemplateParamScope) TemplateParamParent = this; @@ -55,3 +59,13 @@ void Scope::Init(Scope *parent, unsigned flags) { Entity = 0; ErrorTrap.reset(); } + +bool Scope::containedInPrototypeScope() const { + const Scope *S = this; + while (S) { + if (S->isFunctionPrototypeScope()) + return true; + S = S->getParent(); + } + return false; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp index 533b21c..fcdfcac 100644 --- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp @@ -33,6 +33,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" +#include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/PartialDiagnostic.h" @@ -54,10 +55,12 @@ void FunctionScopeInfo::Clear() { } BlockScopeInfo::~BlockScopeInfo() { } +LambdaScopeInfo::~LambdaScopeInfo() { } -PrintingPolicy Sema::getPrintingPolicy() const { +PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context, + const Preprocessor &PP) { PrintingPolicy Policy = Context.getPrintingPolicy(); - Policy.Bool = getLangOptions().Bool; + Policy.Bool = Context.getLangOpts().Bool; if (!Policy.Bool) { if (MacroInfo *BoolMacro = PP.getMacroInfo(&Context.Idents.get("bool"))) { Policy.Bool = BoolMacro->isObjectLike() && @@ -74,36 +77,26 @@ void Sema::ActOnTranslationUnitScope(Scope *S) { PushDeclContext(S, Context.getTranslationUnitDecl()); VAListTagName = PP.getIdentifierInfo("__va_list_tag"); - - if (PP.getLangOptions().ObjC1) { - // Synthesize "@class Protocol; - if (Context.getObjCProtoType().isNull()) { - ObjCInterfaceDecl *ProtocolDecl = - ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(), - &Context.Idents.get("Protocol"), - SourceLocation(), true); - Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl)); - PushOnScopeChains(ProtocolDecl, TUScope, false); - } - } } Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter) - : TheTargetAttributesSema(0), FPFeatures(pp.getLangOptions()), - LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer), + : TheTargetAttributesSema(0), FPFeatures(pp.getLangOpts()), + LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), CollectStats(false), ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), OriginalLexicalContext(0), PackContext(0), MSStructPragmaOn(false), VisContext(0), - ExprNeedsCleanups(0), LateTemplateParser(0), OpaqueParser(0), - IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0), + ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0), + IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0), + NSNumberDecl(0), NSArrayDecl(0), ArrayWithObjectsMethod(0), + NSDictionaryDecl(0), DictionaryWithObjectsMethod(0), GlobalNewDeleteDeclared(false), ObjCShouldCallSuperDealloc(false), ObjCShouldCallSuperFinalize(false), TUKind(TUKind), - NumSFINAEErrors(0), SuppressAccessChecking(false), + NumSFINAEErrors(0), InFunctionDeclarator(0), SuppressAccessChecking(false), AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1), CurrentInstantiationScope(0), TyposCorrected(0), @@ -111,8 +104,13 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, { TUScope = 0; LoadedExternalKnownNamespaces = false; - - if (getLangOptions().CPlusPlus) + for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I) + NSNumberLiteralMethods[I] = 0; + + if (getLangOpts().ObjC1) + NSAPIObj.reset(new NSAPI(Context)); + + if (getLangOpts().CPlusPlus) FieldCollector.reset(new CXXFieldCollector()); // Tell diagnostics how to render things from the AST library. @@ -120,7 +118,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, &Context); ExprEvalContexts.push_back( - ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0, false)); + ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0, + false, 0, false)); FunctionScopes.push_back(new FunctionScopeInfo(Diags)); } @@ -143,33 +142,38 @@ void Sema::Initialize() { // If either of the 128-bit integer types are unavailable to name lookup, // define them now. DeclarationName Int128 = &Context.Idents.get("__int128_t"); - if (IdentifierResolver::begin(Int128) == IdentifierResolver::end()) + if (IdResolver.begin(Int128) == IdResolver.end()) PushOnScopeChains(Context.getInt128Decl(), TUScope); DeclarationName UInt128 = &Context.Idents.get("__uint128_t"); - if (IdentifierResolver::begin(UInt128) == IdentifierResolver::end()) + if (IdResolver.begin(UInt128) == IdResolver.end()) PushOnScopeChains(Context.getUInt128Decl(), TUScope); } // Initialize predefined Objective-C types: - if (PP.getLangOptions().ObjC1) { + if (PP.getLangOpts().ObjC1) { // If 'SEL' does not yet refer to any declarations, make it refer to the // predefined 'SEL'. DeclarationName SEL = &Context.Idents.get("SEL"); - if (IdentifierResolver::begin(SEL) == IdentifierResolver::end()) + if (IdResolver.begin(SEL) == IdResolver.end()) PushOnScopeChains(Context.getObjCSelDecl(), TUScope); // If 'id' does not yet refer to any declarations, make it refer to the // predefined 'id'. DeclarationName Id = &Context.Idents.get("id"); - if (IdentifierResolver::begin(Id) == IdentifierResolver::end()) + if (IdResolver.begin(Id) == IdResolver.end()) PushOnScopeChains(Context.getObjCIdDecl(), TUScope); // Create the built-in typedef for 'Class'. DeclarationName Class = &Context.Idents.get("Class"); - if (IdentifierResolver::begin(Class) == IdentifierResolver::end()) + if (IdResolver.begin(Class) == IdResolver.end()) PushOnScopeChains(Context.getObjCClassDecl(), TUScope); + + // Create the built-in forward declaratino for 'Protocol'. + DeclarationName Protocol = &Context.Idents.get("Protocol"); + if (IdResolver.begin(Protocol) == IdResolver.end()) + PushOnScopeChains(Context.getObjCProtocolDecl(), TUScope); } } @@ -240,13 +244,28 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, CastKind Kind, ExprValueKind VK, const CXXCastPath *BasePath, CheckedConversionKind CCK) { +#ifndef NDEBUG + if (VK == VK_RValue && !E->isRValue()) { + switch (Kind) { + default: + assert(0 && "can't implicitly cast lvalue to rvalue with this cast kind"); + case CK_LValueToRValue: + case CK_ArrayToPointerDecay: + case CK_FunctionToPointerDecay: + case CK_ToVoid: + break; + } + } + assert((VK == VK_RValue || !E->isRValue()) && "can't cast rvalue to lvalue"); +#endif + QualType ExprTy = Context.getCanonicalType(E->getType()); QualType TypeTy = Context.getCanonicalType(Ty); if (ExprTy == TypeTy) return Owned(E); - if (getLangOptions().ObjCAutoRefCount) + if (getLangOpts().ObjCAutoRefCount) CheckObjCARCConversion(SourceRange(), Ty, E, CCK); // If this is a derived-to-base cast to a through a virtual base, we @@ -303,7 +322,7 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { // Later redecls may add new information resulting in not having to warn, // so check again. - DeclToCheck = FD->getMostRecentDeclaration(); + DeclToCheck = FD->getMostRecentDecl(); if (DeclToCheck != FD) return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck); } @@ -317,7 +336,7 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { // Later redecls may add new information resulting in not having to warn, // so check again. - DeclToCheck = VD->getMostRecentDeclaration(); + DeclToCheck = VD->getMostRecentDecl(); if (DeclToCheck != VD) return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck); } @@ -407,6 +426,8 @@ void Sema::ActOnEndOfTranslationUnit() { // Only complete translation units define vtables and perform implicit // instantiations. if (TUKind == TU_Complete) { + DiagnoseUseOfUnimplementedSelectors(); + // If any dynamic classes have their key function defined within // this translation unit, then those vtables are considered "used" and must // be emitted. @@ -468,34 +489,32 @@ void Sema::ActOnEndOfTranslationUnit() { } if (TUKind == TU_Module) { - // Mark any macros from system headers (in /usr/include) as exported, along - // with our own Clang headers. - // FIXME: This is a gross hack to deal with the fact that system headers - // are #include'd in many places within module headers, but are not - // themselves modularized. This doesn't actually work, but it lets us - // focus on other issues for the moment. - for (Preprocessor::macro_iterator M = PP.macro_begin(false), - MEnd = PP.macro_end(false); - M != MEnd; ++M) { - if (M->second && - !M->second->isExported() && - !M->second->isBuiltinMacro()) { - SourceLocation Loc = M->second->getDefinitionLoc(); - if (SourceMgr.isInSystemHeader(Loc)) { - const FileEntry *File - = SourceMgr.getFileEntryForID(SourceMgr.getFileID(Loc)); - if (File && - ((StringRef(File->getName()).find("lib/clang") - != StringRef::npos) || - (StringRef(File->getName()).find("usr/include") - != StringRef::npos) || - (StringRef(File->getName()).find("usr/local/include") - != StringRef::npos))) - M->second->setExportLocation(Loc); + // If we are building a module, resolve all of the exported declarations + // now. + if (Module *CurrentModule = PP.getCurrentModule()) { + ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap(); + + llvm::SmallVector<Module *, 2> Stack; + Stack.push_back(CurrentModule); + while (!Stack.empty()) { + Module *Mod = Stack.back(); + Stack.pop_back(); + + // Resolve the exported declarations. + // FIXME: Actually complain, once we figure out how to teach the + // diagnostic client to deal with complains in the module map at this + // point. + ModMap.resolveExports(Mod, /*Complain=*/false); + + // Queue the submodules, so their exports will also be resolved. + for (Module::submodule_iterator Sub = Mod->submodule_begin(), + SubEnd = Mod->submodule_end(); + Sub != SubEnd; ++Sub) { + Stack.push_back(*Sub); } } } - + // Modules don't need any of the checking below. TUScope = 0; return; @@ -620,8 +639,16 @@ void Sema::ActOnEndOfTranslationUnit() { DeclContext *Sema::getFunctionLevelDeclContext() { DeclContext *DC = CurContext; - while (isa<BlockDecl>(DC) || isa<EnumDecl>(DC)) - DC = DC->getParent(); + while (true) { + if (isa<BlockDecl>(DC) || isa<EnumDecl>(DC)) { + DC = DC->getParent(); + } else if (isa<CXXMethodDecl>(DC) && + cast<CXXMethodDecl>(DC)->getOverloadedOperator() == OO_Call && + cast<CXXRecordDecl>(DC->getParent())->isLambda()) { + DC = DC->getParent()->getParent(); + } + else break; + } return DC; } @@ -646,58 +673,75 @@ NamedDecl *Sema::getCurFunctionOrMethodDecl() { return 0; } -Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() { - if (!isActive()) - return; - - if (llvm::Optional<TemplateDeductionInfo*> Info = SemaRef.isSFINAEContext()) { - switch (DiagnosticIDs::getDiagnosticSFINAEResponse(getDiagID())) { +void Sema::EmitCurrentDiagnostic(unsigned DiagID) { + // FIXME: It doesn't make sense to me that DiagID is an incoming argument here + // and yet we also use the current diag ID on the DiagnosticsEngine. This has + // been made more painfully obvious by the refactor that introduced this + // function, but it is possible that the incoming argument can be + // eliminnated. If it truly cannot be (for example, there is some reentrancy + // issue I am not seeing yet), then there should at least be a clarifying + // comment somewhere. + if (llvm::Optional<TemplateDeductionInfo*> Info = isSFINAEContext()) { + switch (DiagnosticIDs::getDiagnosticSFINAEResponse( + Diags.getCurrentDiagID())) { case DiagnosticIDs::SFINAE_Report: - // Fall through; we'll report the diagnostic below. + // We'll report the diagnostic below. break; - case DiagnosticIDs::SFINAE_AccessControl: - // Per C++ Core Issue 1170, access control is part of SFINAE. - // Additionally, the AccessCheckingSFINAE flag can be used to temporary - // make access control a part of SFINAE for the purposes of checking - // type traits. - if (!SemaRef.AccessCheckingSFINAE && - !SemaRef.getLangOptions().CPlusPlus0x) - break; - case DiagnosticIDs::SFINAE_SubstitutionFailure: // Count this failure so that we know that template argument deduction // has failed. - ++SemaRef.NumSFINAEErrors; - SemaRef.Diags.setLastDiagnosticIgnored(); - SemaRef.Diags.Clear(); - Clear(); + ++NumSFINAEErrors; + Diags.setLastDiagnosticIgnored(); + Diags.Clear(); return; + case DiagnosticIDs::SFINAE_AccessControl: { + // Per C++ Core Issue 1170, access control is part of SFINAE. + // Additionally, the AccessCheckingSFINAE flag can be used to temporarily + // make access control a part of SFINAE for the purposes of checking + // type traits. + if (!AccessCheckingSFINAE && !getLangOpts().CPlusPlus0x) + break; + + SourceLocation Loc = Diags.getCurrentDiagLoc(); + + // Suppress this diagnostic. + ++NumSFINAEErrors; + Diags.setLastDiagnosticIgnored(); + Diags.Clear(); + + // Now the diagnostic state is clear, produce a C++98 compatibility + // warning. + Diag(Loc, diag::warn_cxx98_compat_sfinae_access_control); + + // The last diagnostic which Sema produced was ignored. Suppress any + // notes attached to it. + Diags.setLastDiagnosticIgnored(); + return; + } + case DiagnosticIDs::SFINAE_Suppress: // Make a copy of this suppressed diagnostic and store it with the // template-deduction information; - FlushCounts(); - Diagnostic DiagInfo(&SemaRef.Diags); + Diagnostic DiagInfo(&Diags); if (*Info) (*Info)->addSuppressedDiagnostic(DiagInfo.getLocation(), - PartialDiagnostic(DiagInfo, - SemaRef.Context.getDiagAllocator())); + PartialDiagnostic(DiagInfo,Context.getDiagAllocator())); // Suppress this diagnostic. - SemaRef.Diags.setLastDiagnosticIgnored(); - SemaRef.Diags.Clear(); - Clear(); + Diags.setLastDiagnosticIgnored(); + Diags.Clear(); return; } } // Set up the context's printing policy based on our current state. - SemaRef.Context.setPrintingPolicy(SemaRef.getPrintingPolicy()); + Context.setPrintingPolicy(getPrintingPolicy()); // Emit the diagnostic. - if (!this->Emit()) + if (!Diags.EmitCurrentDiagnostic()) return; // If this is not a note, and we're in a template instantiation @@ -705,20 +749,14 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() { // we emitted an error, print a template instantiation // backtrace. if (!DiagnosticIDs::isBuiltinNote(DiagID) && - !SemaRef.ActiveTemplateInstantiations.empty() && - SemaRef.ActiveTemplateInstantiations.back() - != SemaRef.LastTemplateInstantiationErrorContext) { - SemaRef.PrintInstantiationStack(); - SemaRef.LastTemplateInstantiationErrorContext - = SemaRef.ActiveTemplateInstantiations.back(); + !ActiveTemplateInstantiations.empty() && + ActiveTemplateInstantiations.back() + != LastTemplateInstantiationErrorContext) { + PrintInstantiationStack(); + LastTemplateInstantiationErrorContext = ActiveTemplateInstantiations.back(); } } -Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID) { - DiagnosticBuilder DB = Diags.Report(Loc, DiagID); - return SemaDiagnosticBuilder(DB, *this, DiagID); -} - Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) { SemaDiagnosticBuilder Builder(Diag(Loc, PD.getDiagID())); @@ -795,8 +833,14 @@ void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) { BlockScope, Block)); } -void Sema::PopFunctionOrBlockScope(const AnalysisBasedWarnings::Policy *WP, - const Decl *D, const BlockExpr *blkExpr) { +void Sema::PushLambdaScope(CXXRecordDecl *Lambda, + CXXMethodDecl *CallOperator) { + FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda, + CallOperator)); +} + +void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP, + const Decl *D, const BlockExpr *blkExpr) { FunctionScopeInfo *Scope = FunctionScopes.pop_back_val(); assert(!FunctionScopes.empty() && "mismatched push/pop!"); @@ -818,6 +862,17 @@ void Sema::PopFunctionOrBlockScope(const AnalysisBasedWarnings::Policy *WP, } } +void Sema::PushCompoundScope() { + getCurFunction()->CompoundScopes.push_back(CompoundScopeInfo()); +} + +void Sema::PopCompoundScope() { + FunctionScopeInfo *CurFunction = getCurFunction(); + assert(!CurFunction->CompoundScopes.empty() && "mismatched push/pop"); + + CurFunction->CompoundScopes.pop_back(); +} + /// \brief Determine whether any errors occurred within this function/method/ /// block. bool Sema::hasAnyUnrecoverableErrorsInThisFunction() const { @@ -831,13 +886,17 @@ BlockScopeInfo *Sema::getCurBlock() { return dyn_cast<BlockScopeInfo>(FunctionScopes.back()); } +LambdaScopeInfo *Sema::getCurLambda() { + if (FunctionScopes.empty()) + return 0; + + return dyn_cast<LambdaScopeInfo>(FunctionScopes.back()); +} + // Pin this vtable to this file. ExternalSemaSource::~ExternalSemaSource() {} -std::pair<ObjCMethodList, ObjCMethodList> -ExternalSemaSource::ReadMethodPool(Selector Sel) { - return std::pair<ObjCMethodList, ObjCMethodList>(); -} +void ExternalSemaSource::ReadMethodPool(Selector Sel) { } void ExternalSemaSource::ReadKnownNamespaces( SmallVectorImpl<NamespaceDecl *> &Namespaces) { @@ -963,7 +1022,7 @@ static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads, } NamedDecl *Fn = (*It)->getUnderlyingDecl(); - S.Diag(Fn->getLocStart(), diag::note_possible_target_of_call); + S.Diag(Fn->getLocation(), diag::note_possible_target_of_call); ++ShownOverloads; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp index 6cd9230..dea5e76 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp @@ -19,6 +19,7 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/DependentDiagnostic.h" #include "clang/AST/ExprCXX.h" @@ -164,6 +165,10 @@ struct AccessTarget : public AccessedEntity { initialize(); } + bool isInstanceMember() const { + return (isMemberAccess() && getTargetDecl()->isCXXInstanceMember()); + } + bool hasInstanceContext() const { return HasInstanceContext; } @@ -264,6 +269,9 @@ static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived, SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack while (true) { + 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) { @@ -667,18 +675,25 @@ struct ProtectedFriendContext { } /// Search for a class P that EC is a friend of, under the constraint -/// InstanceContext <= P <= NamingClass +/// InstanceContext <= P +/// if InstanceContext exists, or else +/// NamingClass <= P /// and with the additional restriction that a protected member of -/// NamingClass would have some natural access in P. +/// NamingClass would have some natural access in P, which implicitly +/// imposes the constraint that P <= NamingClass. /// -/// That second condition isn't actually quite right: the condition in -/// the standard is whether the target would have some natural access -/// in P. The difference is that the target might be more accessible -/// along some path not passing through NamingClass. Allowing that +/// This isn't quite the condition laid out in the standard. +/// Instead of saying that a notional protected member of NamingClass +/// would have to have some natural access in P, it says the actual +/// target has to have some natural access in P, which opens up the +/// possibility that the target (which is not necessarily a member +/// of NamingClass) might be more accessible along some path not +/// passing through it. That's really a bad idea, though, because it /// introduces two problems: -/// - It breaks encapsulation because you can suddenly access a -/// forbidden base class's members by subclassing it elsewhere. -/// - It makes access substantially harder to compute because it +/// - Most importantly, it breaks encapsulation because you can +/// access a forbidden base class's members by directly subclassing +/// it elsewhere. +/// - It also makes access substantially harder to compute because it /// breaks the hill-climbing algorithm: knowing that the target is /// accessible in some base class would no longer let you change /// the question solely to whether the base class is accessible, @@ -688,9 +703,15 @@ struct ProtectedFriendContext { static AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC, const CXXRecordDecl *InstanceContext, const CXXRecordDecl *NamingClass) { - assert(InstanceContext->getCanonicalDecl() == InstanceContext); + assert(InstanceContext == 0 || + InstanceContext->getCanonicalDecl() == InstanceContext); assert(NamingClass->getCanonicalDecl() == NamingClass); + // If we don't have an instance context, our constraints give us + // that NamingClass <= P <= NamingClass, i.e. P == NamingClass. + // This is just the usual friendship check. + if (!InstanceContext) return GetFriendKind(S, EC, NamingClass); + ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass); if (PRC.findFriendship(InstanceContext)) return AR_accessible; if (PRC.EverDependent) return AR_dependent; @@ -733,15 +754,6 @@ static AccessResult HasAccess(Sema &S, case AR_dependent: OnFailure = AR_dependent; continue; } - if (!Target.hasInstanceContext()) - return AR_accessible; - - const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); - if (!InstanceContext) { - OnFailure = AR_dependent; - continue; - } - // C++ [class.protected]p1: // An additional access check beyond those described earlier in // [class.access] is applied when a non-static data member or @@ -754,8 +766,49 @@ static AccessResult HasAccess(Sema &S, // expression. In this case, the class of the object expression // shall be C or a class derived from C. // - // We interpret this as a restriction on [M3]. Most of the - // conditions are encoded by not having any instance context. + // We interpret this as a restriction on [M3]. + + // In this part of the code, 'C' is just our context class ECRecord. + + // These rules are different if we don't have an instance context. + if (!Target.hasInstanceContext()) { + // If it's not an instance member, these restrictions don't apply. + if (!Target.isInstanceMember()) return AR_accessible; + + // If it's an instance member, use the pointer-to-member rule + // that the naming class has to be derived from the effective + // context. + + // Despite the standard's confident wording, there is a case + // where you can have an instance member that's neither in a + // pointer-to-member expression nor in a member access: when + // it names a field in an unevaluated context that can't be an + // implicit member. Pending clarification, we just apply the + // same naming-class restriction here. + // FIXME: we're probably not correctly adding the + // protected-member restriction when we retroactively convert + // an expression to being evaluated. + + // We know that ECRecord derives from NamingClass. The + // restriction says to check whether NamingClass derives from + // ECRecord, but that's not really necessary: two distinct + // classes can't be recursively derived from each other. So + // along this path, we just need to check whether the classes + // are equal. + if (NamingClass == ECRecord) return AR_accessible; + + // Otherwise, this context class tells us nothing; on to the next. + continue; + } + + assert(Target.isInstanceMember()); + + const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); + if (!InstanceContext) { + OnFailure = AR_dependent; + continue; + } + switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { case AR_accessible: return AR_accessible; case AR_inaccessible: continue; @@ -774,9 +827,14 @@ static AccessResult HasAccess(Sema &S, // *unless* the [class.protected] restriction applies. If it does, // however, we should ignore whether the naming class is a friend, // and instead rely on whether any potential P is a friend. - if (Access == AS_protected && Target.hasInstanceContext()) { - const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); - if (!InstanceContext) return AR_dependent; + if (Access == AS_protected && Target.isInstanceMember()) { + // Compute the instance context if possible. + const CXXRecordDecl *InstanceContext = 0; + if (Target.hasInstanceContext()) { + InstanceContext = Target.resolveInstanceContext(S); + if (!InstanceContext) return AR_dependent; + } + switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) { case AR_accessible: return AR_accessible; case AR_inaccessible: return OnFailure; @@ -793,7 +851,6 @@ static AccessResult HasAccess(Sema &S, // Silence bogus warnings llvm_unreachable("impossible friendship kind"); - return OnFailure; } /// Finds the best path from the naming class to the declaring class, @@ -947,31 +1004,46 @@ static CXXBasePath *FindBestPath(Sema &S, static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC, AccessTarget &Target) { // Only applies to instance accesses. - if (!Target.hasInstanceContext()) + if (!Target.isInstanceMember()) return false; + assert(Target.isMemberAccess()); - NamedDecl *D = Target.getTargetDecl(); - const CXXRecordDecl *DeclaringClass = Target.getDeclaringClass(); - DeclaringClass = DeclaringClass->getCanonicalDecl(); + const CXXRecordDecl *NamingClass = Target.getNamingClass(); + NamingClass = NamingClass->getCanonicalDecl(); for (EffectiveContext::record_iterator I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { const CXXRecordDecl *ECRecord = *I; - switch (IsDerivedFromInclusive(ECRecord, DeclaringClass)) { + switch (IsDerivedFromInclusive(ECRecord, NamingClass)) { case AR_accessible: break; case AR_inaccessible: continue; case AR_dependent: continue; } // The effective context is a subclass of the declaring class. - // If that class isn't a superclass of the instance context, - // then the [class.protected] restriction applies. + // Check whether the [class.protected] restriction is limiting + // access. // To get this exactly right, this might need to be checked more // holistically; it's not necessarily the case that gaining // access here would grant us access overall. + NamedDecl *D = Target.getTargetDecl(); + + // If we don't have an instance context, [class.protected] says the + // naming class has to equal the context class. + if (!Target.hasInstanceContext()) { + // If it does, the restriction doesn't apply. + if (NamingClass == ECRecord) continue; + + // TODO: it would be great to have a fixit here, since this is + // such an obvious error. + S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject) + << S.Context.getTypeDeclType(ECRecord); + return true; + } + const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); assert(InstanceContext && "diagnosing dependent access"); @@ -979,12 +1051,25 @@ static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC, case AR_accessible: continue; case AR_dependent: continue; case AR_inaccessible: - S.Diag(D->getLocation(), diag::note_access_protected_restricted) - << (InstanceContext != Target.getNamingClass()->getCanonicalDecl()) - << S.Context.getTypeDeclType(InstanceContext) - << S.Context.getTypeDeclType(ECRecord); + break; + } + + // Okay, the restriction seems to be what's limiting us. + + // Use a special diagnostic for constructors and destructors. + if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D) || + (isa<FunctionTemplateDecl>(D) && + isa<CXXConstructorDecl>( + cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) { + S.Diag(D->getLocation(), diag::note_access_protected_restricted_ctordtor) + << isa<CXXDestructorDecl>(D); return true; } + + // Otherwise, use the generic diagnostic. + S.Diag(D->getLocation(), diag::note_access_protected_restricted_object) + << S.Context.getTypeDeclType(ECRecord); + return true; } return false; @@ -996,8 +1081,6 @@ static void DiagnoseAccessPath(Sema &S, const EffectiveContext &EC, AccessTarget &Entity) { AccessSpecifier Access = Entity.getAccess(); - const CXXRecordDecl *NamingClass = Entity.getNamingClass(); - NamingClass = NamingClass->getCanonicalDecl(); NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0); const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); @@ -1016,15 +1099,15 @@ static void DiagnoseAccessPath(Sema &S, while (D->isOutOfLine()) { NamedDecl *PrevDecl = 0; if (VarDecl *VD = dyn_cast<VarDecl>(D)) - PrevDecl = VD->getPreviousDeclaration(); + PrevDecl = VD->getPreviousDecl(); else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) - PrevDecl = FD->getPreviousDeclaration(); + PrevDecl = FD->getPreviousDecl(); else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D)) - PrevDecl = TND->getPreviousDeclaration(); + PrevDecl = TND->getPreviousDecl(); else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName()) break; - PrevDecl = TD->getPreviousDeclaration(); + PrevDecl = TD->getPreviousDecl(); } if (!PrevDecl) break; D = PrevDecl; @@ -1064,7 +1147,6 @@ static void DiagnoseAccessPath(Sema &S, case AR_dependent: llvm_unreachable("can't diagnose dependent access failures"); - return; } } @@ -1162,7 +1244,7 @@ static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S, if (Entity.getTargetDecl()->getAccess() == AS_private && (OrigDecl->getAccess() == AS_public || OrigDecl->getAccess() == AS_protected)) { - S.Diag(AccessLoc, diag::war_ms_using_declaration_inaccessible) + S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible) << Shadow->getUsingDecl()->getQualifiedNameAsString() << OrigDecl->getQualifiedNameAsString(); return true; @@ -1274,7 +1356,7 @@ static AccessResult CheckEffectiveAccess(Sema &S, AccessTarget &Entity) { assert(Entity.getAccess() != AS_public && "called for public access!"); - if (S.getLangOptions().MicrosoftMode && + if (S.getLangOpts().MicrosoftMode && IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity)) return AR_accessible; @@ -1294,7 +1376,6 @@ static AccessResult CheckEffectiveAccess(Sema &S, // silence unnecessary warning llvm_unreachable("invalid access result"); - return AR_accessible; } static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, @@ -1329,7 +1410,6 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, case AR_dependent: return Sema::AR_dependent; } llvm_unreachable("falling off end"); - return Sema::AR_accessible; } void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *decl) { @@ -1396,7 +1476,7 @@ void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD, Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, DeclAccessPair Found) { - if (!getLangOptions().AccessControl || + if (!getLangOpts().AccessControl || !E->getNamingClass() || Found.getAccess() == AS_public) return AR_accessible; @@ -1412,7 +1492,7 @@ Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, /// access which has now been resolved to a member. Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, DeclAccessPair Found) { - if (!getLangOptions().AccessControl || + if (!getLangOpts().AccessControl || Found.getAccess() == AS_public) return AR_accessible; @@ -1427,10 +1507,34 @@ Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, return CheckAccess(*this, E->getMemberLoc(), Entity); } +/// Is the given special member function accessible for the purposes of +/// deciding whether to define a special member function as deleted? +bool Sema::isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl, + AccessSpecifier access, + QualType objectType) { + // Fast path. + if (access == AS_public || !getLangOpts().AccessControl) return true; + + AccessTarget entity(Context, AccessTarget::Member, decl->getParent(), + DeclAccessPair::make(decl, access), objectType); + + // Suppress diagnostics. + entity.setDiag(PDiag()); + + switch (CheckAccess(*this, SourceLocation(), entity)) { + case AR_accessible: return true; + case AR_inaccessible: return false; + case AR_dependent: llvm_unreachable("dependent for =delete computation"); + case AR_delayed: llvm_unreachable("cannot delay =delete computation"); + } + llvm_unreachable("bad access result"); +} + Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, CXXDestructorDecl *Dtor, - const PartialDiagnostic &PDiag) { - if (!getLangOptions().AccessControl) + const PartialDiagnostic &PDiag, + QualType ObjectTy) { + if (!getLangOpts().AccessControl) return AR_accessible; // There's never a path involved when checking implicit destructor access. @@ -1439,9 +1543,11 @@ Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, return AR_accessible; CXXRecordDecl *NamingClass = Dtor->getParent(); + if (ObjectTy.isNull()) ObjectTy = Context.getTypeDeclType(NamingClass); + AccessTarget Entity(Context, AccessTarget::Member, NamingClass, DeclAccessPair::make(Dtor, Access), - QualType()); + ObjectTy); Entity.setDiag(PDiag); // TODO: avoid copy return CheckAccess(*this, Loc, Entity); @@ -1453,14 +1559,9 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, const InitializedEntity &Entity, AccessSpecifier Access, bool IsCopyBindingRefToTemp) { - if (!getLangOptions().AccessControl || - Access == AS_public) + if (!getLangOpts().AccessControl || Access == AS_public) return AR_accessible; - CXXRecordDecl *NamingClass = Constructor->getParent(); - AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass, - DeclAccessPair::make(Constructor, Access), - QualType()); PartialDiagnostic PD(PDiag()); switch (Entity.getKind()) { default: @@ -1483,28 +1584,47 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, break; } + case InitializedEntity::EK_LambdaCapture: { + const VarDecl *Var = Entity.getCapturedVar(); + PD = PDiag(diag::err_access_lambda_capture); + PD << Var->getName() << Entity.getType() << getSpecialMember(Constructor); + break; + } + } - return CheckConstructorAccess(UseLoc, Constructor, Access, PD); + return CheckConstructorAccess(UseLoc, Constructor, Entity, Access, PD); } /// Checks access to a constructor. Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, CXXConstructorDecl *Constructor, + const InitializedEntity &Entity, AccessSpecifier Access, - PartialDiagnostic PD) { - if (!getLangOptions().AccessControl || + const PartialDiagnostic &PD) { + if (!getLangOpts().AccessControl || Access == AS_public) return AR_accessible; CXXRecordDecl *NamingClass = Constructor->getParent(); + + // Initializing a base sub-object is an instance method call on an + // object of the derived class. Otherwise, we have an instance method + // call on an object of the constructed type. + CXXRecordDecl *ObjectClass; + if (Entity.getKind() == InitializedEntity::EK_Base) { + ObjectClass = cast<CXXConstructorDecl>(CurContext)->getParent(); + } else { + ObjectClass = NamingClass; + } + AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass, DeclAccessPair::make(Constructor, Access), - QualType()); + Context.getTypeDeclType(ObjectClass)); AccessEntity.setDiag(PD); return CheckAccess(*this, UseLoc, AccessEntity); -} +} /// Checks direct (i.e. non-inherited) access to an arbitrary class /// member. @@ -1512,7 +1632,7 @@ Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc, NamedDecl *Target, const PartialDiagnostic &Diag) { AccessSpecifier Access = Target->getAccess(); - if (!getLangOptions().AccessControl || + if (!getLangOpts().AccessControl || Access == AS_public) return AR_accessible; @@ -1531,7 +1651,7 @@ Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, CXXRecordDecl *NamingClass, DeclAccessPair Found, bool Diagnose) { - if (!getLangOptions().AccessControl || + if (!getLangOpts().AccessControl || !NamingClass || Found.getAccess() == AS_public) return AR_accessible; @@ -1551,7 +1671,7 @@ Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, Expr *ObjectExpr, Expr *ArgExpr, DeclAccessPair Found) { - if (!getLangOptions().AccessControl || + if (!getLangOpts().AccessControl || Found.getAccess() == AS_public) return AR_accessible; @@ -1569,7 +1689,7 @@ Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, DeclAccessPair Found) { - if (!getLangOptions().AccessControl || + if (!getLangOpts().AccessControl || Found.getAccess() == AS_none || Found.getAccess() == AS_public) return AR_accessible; @@ -1578,7 +1698,7 @@ Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, CXXRecordDecl *NamingClass = Ovl->getNamingClass(); AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, - Context.getTypeDeclType(NamingClass)); + /*no instance context*/ QualType()); Entity.setDiag(diag::err_access) << Ovl->getSourceRange(); @@ -1601,7 +1721,7 @@ Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, unsigned DiagID, bool ForceCheck, bool ForceUnprivileged) { - if (!ForceCheck && !getLangOptions().AccessControl) + if (!ForceCheck && !getLangOpts().AccessControl) return AR_accessible; if (Path.Access == AS_public) @@ -1630,7 +1750,7 @@ Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, /// Checks access to all the declarations in the given result set. void Sema::CheckLookupAccess(const LookupResult &R) { - assert(getLangOptions().AccessControl + assert(getLangOpts().AccessControl && "performing access check without access control"); assert(R.getNamingClass() && "performing access check without naming class"); @@ -1651,19 +1771,63 @@ void Sema::CheckLookupAccess(const LookupResult &R) { /// \param Decl the declaration to check if it can be accessed /// \param Class the class/context from which to start the search /// \return true if the Decl is accessible from the Class, false otherwise. -bool Sema::IsSimplyAccessible(NamedDecl *Decl, CXXRecordDecl *Class) { - if (!Class || !Decl->isCXXClassMember()) - return true; +bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) { + if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) { + if (!Decl->isCXXClassMember()) + return true; - QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal(); - AccessTarget Entity(Context, AccessedEntity::Member, Class, - DeclAccessPair::make(Decl, Decl->getAccess()), - qType); - if (Entity.getAccess() == AS_public) - return true; + QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal(); + AccessTarget Entity(Context, AccessedEntity::Member, Class, + DeclAccessPair::make(Decl, Decl->getAccess()), + qType); + if (Entity.getAccess() == AS_public) + return true; - EffectiveContext EC(CurContext); - return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible; + EffectiveContext EC(CurContext); + return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible; + } + + if (ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(Decl)) { + // @public and @package ivars are always accessible. + if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Public || + Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Package) + return true; + + + + // If we are inside a class or category implementation, determine the + // interface we're in. + ObjCInterfaceDecl *ClassOfMethodDecl = 0; + if (ObjCMethodDecl *MD = getCurMethodDecl()) + ClassOfMethodDecl = MD->getClassInterface(); + else if (FunctionDecl *FD = getCurFunctionDecl()) { + if (ObjCImplDecl *Impl + = dyn_cast<ObjCImplDecl>(FD->getLexicalDeclContext())) { + if (ObjCImplementationDecl *IMPD + = dyn_cast<ObjCImplementationDecl>(Impl)) + ClassOfMethodDecl = IMPD->getClassInterface(); + else if (ObjCCategoryImplDecl* CatImplClass + = dyn_cast<ObjCCategoryImplDecl>(Impl)) + ClassOfMethodDecl = CatImplClass->getClassInterface(); + } + } + + // If we're not in an interface, this ivar is inaccessible. + if (!ClassOfMethodDecl) + return false; + + // If we're inside the same interface that owns the ivar, we're fine. + if (declaresSameEntity(ClassOfMethodDecl, Ivar->getContainingInterface())) + return true; + + // If the ivar is private, it's inaccessible. + if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Private) + return false; + + return Ivar->getContainingInterface()->isSuperClassOf(ClassOfMethodDecl); + } + + return true; } void Sema::ActOnStartSuppressingAccessChecks() { diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp index 77410db..e935fc7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp @@ -263,9 +263,6 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, Context->setAlignment(AlignmentVal); } break; - - default: - llvm_unreachable("Invalid #pragma pack kind."); } } @@ -348,9 +345,9 @@ static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) { Stack->push_back(std::make_pair(type, loc)); } -void Sema::ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType, +void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType, SourceLocation PragmaLoc) { - if (IsPush) { + if (VisType) { // Compute visibility to use. VisibilityAttr::VisibilityType type; if (VisType->isStr("default")) @@ -368,7 +365,7 @@ void Sema::ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType, } PushPragmaVisibility(*this, type, PragmaLoc); } else { - PopPragmaVisibility(); + PopPragmaVisibility(false, PragmaLoc); } } @@ -381,28 +378,49 @@ void Sema::ActOnPragmaFPContract(tok::OnOffSwitch OOS) { FPFeatures.fp_contract = 0; break; case tok::OOS_DEFAULT: - FPFeatures.fp_contract = getLangOptions().DefaultFPContract; + FPFeatures.fp_contract = getLangOpts().DefaultFPContract; break; } } -void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr) { +void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr, + SourceLocation Loc) { // Visibility calculations will consider the namespace's visibility. // Here we just want to note that we're in a visibility context // which overrides any enclosing #pragma context, but doesn't itself // contribute visibility. - PushPragmaVisibility(*this, NoVisibility, SourceLocation()); + PushPragmaVisibility(*this, NoVisibility, Loc); } -void Sema::PopPragmaVisibility() { - // Pop visibility from stack, if there is one on the stack. - if (VisContext) { - VisStack *Stack = static_cast<VisStack*>(VisContext); +void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) { + if (!VisContext) { + Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch); + return; + } + + // Pop visibility from stack + VisStack *Stack = static_cast<VisStack*>(VisContext); - Stack->pop_back(); - // To simplify the implementation, never keep around an empty stack. - if (Stack->empty()) - FreeVisContext(); + const std::pair<unsigned, SourceLocation> *Back = &Stack->back(); + bool StartsWithPragma = Back->first != NoVisibility; + if (StartsWithPragma && IsNamespaceEnd) { + Diag(Back->second, diag::err_pragma_push_visibility_mismatch); + Diag(EndLoc, diag::note_surrounding_namespace_ends_here); + + // For better error recovery, eat all pushes inside the namespace. + do { + Stack->pop_back(); + Back = &Stack->back(); + StartsWithPragma = Back->first != NoVisibility; + } while (StartsWithPragma); + } else if (!StartsWithPragma && !IsNamespaceEnd) { + Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch); + Diag(Back->second, diag::note_surrounding_namespace_starts_here); + return; } - // FIXME: Add diag for pop without push. + + Stack->pop_back(); + // To simplify the implementation, never keep around an empty stack. + if (Stack->empty()) + FreeVisContext(); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp index 360a040..5a0fcec 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -13,6 +13,7 @@ #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/Template.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" @@ -150,14 +151,13 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, const TagType *Tag = NNS->getAsType()->getAs<TagType>(); assert(Tag && "Non-tag type in nested-name-specifier"); return Tag->getDecl(); - } break; + } case NestedNameSpecifier::Global: return Context.getTranslationUnitDecl(); } - // Required to silence a GCC warning. - return 0; + llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); } bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) { @@ -187,7 +187,7 @@ bool Sema::isUnknownSpecialization(const CXXScopeSpec &SS) { /// /// \param NNS a dependent nested name specifier. CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) { - assert(getLangOptions().CPlusPlus && "Only callable in C++"); + assert(getLangOpts().CPlusPlus && "Only callable in C++"); assert(NNS->isDependent() && "Only dependent nested-name-specifier allowed"); if (!NNS->getAsType()) @@ -210,43 +210,56 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC) { assert(DC != 0 && "given null context"); - if (TagDecl *tag = dyn_cast<TagDecl>(DC)) { - // If this is a dependent type, then we consider it complete. - if (tag->isDependentContext()) - return false; + TagDecl *tag = dyn_cast<TagDecl>(DC); - // If we're currently defining this type, then lookup into the - // type is okay: don't complain that it isn't complete yet. - QualType type = Context.getTypeDeclType(tag); - const TagType *tagType = type->getAs<TagType>(); - if (tagType && tagType->isBeingDefined()) - return false; + // If this is a dependent type, then we consider it complete. + if (!tag || tag->isDependentContext()) + return false; - SourceLocation loc = SS.getLastQualifierNameLoc(); - if (loc.isInvalid()) loc = SS.getRange().getBegin(); + // If we're currently defining this type, then lookup into the + // type is okay: don't complain that it isn't complete yet. + QualType type = Context.getTypeDeclType(tag); + const TagType *tagType = type->getAs<TagType>(); + if (tagType && tagType->isBeingDefined()) + return false; - // The type must be complete. - if (RequireCompleteType(loc, type, - PDiag(diag::err_incomplete_nested_name_spec) - << SS.getRange())) { - SS.SetInvalid(SS.getRange()); - return true; - } + SourceLocation loc = SS.getLastQualifierNameLoc(); + if (loc.isInvalid()) loc = SS.getRange().getBegin(); + + // The type must be complete. + if (RequireCompleteType(loc, type, + PDiag(diag::err_incomplete_nested_name_spec) + << SS.getRange())) { + SS.SetInvalid(SS.getRange()); + return true; + } - // Fixed enum types are complete, but they aren't valid as scopes - // until we see a definition, so awkwardly pull out this special - // case. - if (const EnumType *enumType = dyn_cast_or_null<EnumType>(tagType)) { - if (!enumType->getDecl()->isCompleteDefinition()) { - Diag(loc, diag::err_incomplete_nested_name_spec) - << type << SS.getRange(); + // Fixed enum types are complete, but they aren't valid as scopes + // until we see a definition, so awkwardly pull out this special + // case. + const EnumType *enumType = dyn_cast_or_null<EnumType>(tagType); + if (!enumType || enumType->getDecl()->isCompleteDefinition()) + return false; + + // Try to instantiate the definition, if this is a specialization of an + // enumeration temploid. + EnumDecl *ED = enumType->getDecl(); + if (EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) { + MemberSpecializationInfo *MSI = ED->getMemberSpecializationInfo(); + if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) { + if (InstantiateEnum(loc, ED, Pattern, getTemplateInstantiationArgs(ED), + TSK_ImplicitInstantiation)) { SS.SetInvalid(SS.getRange()); return true; } + return false; } } - return false; + Diag(loc, diag::err_incomplete_nested_name_spec) + << type << SS.getRange(); + SS.SetInvalid(SS.getRange()); + return true; } bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc, @@ -268,18 +281,18 @@ bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) { if (!isa<TypeDecl>(SD)) return false; - // Determine whether we have a class (or, in C++0x, an enum) or + // Determine whether we have a class (or, in C++11, an enum) or // a typedef thereof. If so, build the nested-name-specifier. QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD)); if (T->isDependentType()) return true; else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) { if (TD->getUnderlyingType()->isRecordType() || - (Context.getLangOptions().CPlusPlus0x && + (Context.getLangOpts().CPlusPlus0x && TD->getUnderlyingType()->isEnumeralType())) return true; } else if (isa<RecordDecl>(SD) || - (Context.getLangOptions().CPlusPlus0x && isa<EnumDecl>(SD))) + (Context.getLangOpts().CPlusPlus0x && isa<EnumDecl>(SD))) return true; return false; @@ -363,6 +376,25 @@ bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, return false; } +namespace { + +// Callback to only accept typo corrections that can be a valid C++ member +// intializer: either a non-static field member or a base class. +class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback { + public: + explicit NestedNameSpecifierValidatorCCC(Sema &SRef) + : SRef(SRef) {} + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + return SRef.isAcceptableNestedNameSpecifier(candidate.getCorrectionDecl()); + } + + private: + Sema &SRef; +}; + +} + /// \brief Build a new nested-name-specifier for "identifier::", as described /// by ActOnCXXNestedNameSpecifier. /// @@ -478,14 +510,14 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, // We haven't found anything, and we're not recovering from a // different kind of error, so look for typos. DeclarationName Name = Found.getLookupName(); + NestedNameSpecifierValidatorCCC Validator(*this); TypoCorrection Corrected; Found.clear(); if ((Corrected = CorrectTypo(Found.getLookupNameInfo(), - Found.getLookupKind(), S, &SS, LookupCtx, - EnteringContext, CTC_NoKeywords)) && - isAcceptableNestedNameSpecifier(Corrected.getCorrectionDecl())) { - std::string CorrectedStr(Corrected.getAsString(getLangOptions())); - std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions())); + Found.getLookupKind(), S, &SS, Validator, + LookupCtx, EnteringContext))) { + std::string CorrectedStr(Corrected.getAsString(getLangOpts())); + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); if (LookupCtx) Diag(Found.getNameLoc(), diag::err_no_member_suggest) << Name << LookupCtx << CorrectedQuotedStr << SS.getRange() @@ -596,6 +628,9 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, llvm_unreachable("Unhandled TypeDecl node in nested-name-specifier"); } + if (T->isEnumeralType()) + Diag(IdentifierLoc, diag::warn_cxx98_compat_enum_nested_name_spec); + SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T), CCLoc); return false; @@ -631,7 +666,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, // public: // void foo() { D::foo2(); } // }; - if (getLangOptions().MicrosoftExt) { + if (getLangOpts().MicrosoftExt) { DeclContext *DC = LookupCtx ? LookupCtx : CurContext; if (DC->isDependentContext() && DC->isFunctionOrMethod()) { SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc); @@ -673,6 +708,29 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, /*ScopeLookupResult=*/0, false); } +bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS, + const DeclSpec &DS, + SourceLocation ColonColonLoc) { + if (SS.isInvalid() || DS.getTypeSpecType() == DeclSpec::TST_error) + return true; + + assert(DS.getTypeSpecType() == DeclSpec::TST_decltype); + + QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); + if (!T->isDependentType() && !T->getAs<TagType>()) { + Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class) + << T << getLangOpts().CPlusPlus; + return true; + } + + TypeLocBuilder TLB; + DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T); + DecltypeTL.setNameLoc(DS.getTypeSpecTypeLoc()); + SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T), + ColonColonLoc); + return false; +} + /// IsInvalidUnlessNestedName - This method is used for error recovery /// purposes to determine whether the specified identifier is only valid as /// a nested name specifier, for example a namespace name. It is @@ -695,8 +753,8 @@ bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, } bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, - SourceLocation TemplateLoc, - CXXScopeSpec &SS, + CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, TemplateTy Template, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, @@ -723,17 +781,18 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, // Create source-location information for this type. TypeLocBuilder Builder; - DependentTemplateSpecializationTypeLoc SpecTL + DependentTemplateSpecializationTypeLoc SpecTL = Builder.push<DependentTemplateSpecializationTypeLoc>(T); + SpecTL.setElaboratedKeywordLoc(SourceLocation()); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + SpecTL.setTemplateKeywordLoc(TemplateKWLoc); + SpecTL.setTemplateNameLoc(TemplateNameLoc); SpecTL.setLAngleLoc(LAngleLoc); SpecTL.setRAngleLoc(RAngleLoc); - SpecTL.setKeywordLoc(SourceLocation()); - SpecTL.setNameLoc(TemplateNameLoc); - SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); - SS.Extend(Context, TemplateLoc, Builder.getTypeLocInContext(Context, T), + SS.Extend(Context, TemplateKWLoc, Builder.getTypeLocInContext(Context, T), CCLoc); return false; } @@ -766,20 +825,19 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, return true; } - // Provide source-location information for the template specialization - // type. + // Provide source-location information for the template specialization type. TypeLocBuilder Builder; - TemplateSpecializationTypeLoc SpecTL + TemplateSpecializationTypeLoc SpecTL = Builder.push<TemplateSpecializationTypeLoc>(T); - + SpecTL.setTemplateKeywordLoc(TemplateKWLoc); + SpecTL.setTemplateNameLoc(TemplateNameLoc); SpecTL.setLAngleLoc(LAngleLoc); SpecTL.setRAngleLoc(RAngleLoc); - SpecTL.setTemplateNameLoc(TemplateNameLoc); for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); - SS.Extend(Context, TemplateLoc, Builder.getTypeLocInContext(Context, T), + SS.Extend(Context, TemplateKWLoc, Builder.getTypeLocInContext(Context, T), CCLoc); return false; } @@ -854,8 +912,7 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { return true; } - // Silence bogus warning. - return false; + llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); } /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp index 8bd9351..54683e1 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp @@ -49,7 +49,7 @@ namespace { : Self(S), SrcExpr(src), DestType(destType), ResultType(destType.getNonLValueExprType(S.Context)), ValueKind(Expr::getValueKindForType(destType)), - Kind(CK_Dependent) { + Kind(CK_Dependent), IsARCUnbridgedCast(false) { if (const BuiltinType *placeholder = src.get()->getType()->getAsPlaceholderType()) { @@ -67,6 +67,7 @@ namespace { CastKind Kind; BuiltinType::Kind PlaceholderKind; CXXCastPath BasePath; + bool IsARCUnbridgedCast; SourceRange OpRange; SourceRange DestRange; @@ -76,9 +77,23 @@ namespace { void CheckReinterpretCast(); void CheckStaticCast(); void CheckDynamicCast(); - void CheckCXXCStyleCast(bool FunctionalCast); + void CheckCXXCStyleCast(bool FunctionalCast, bool ListInitialization); void CheckCStyleCast(); + /// Complete an apparently-successful cast operation that yields + /// the given expression. + ExprResult complete(CastExpr *castExpr) { + // If this is an unbridged cast, wrap the result in an implicit + // cast that yields the unbridged-cast placeholder type. + if (IsARCUnbridgedCast) { + castExpr = ImplicitCastExpr::Create(Self.Context, + Self.Context.ARCUnbridgedCastTy, + CK_Dependent, castExpr, 0, + castExpr->getValueKind()); + } + return Self.Owned(castExpr); + } + // Internal convenience methods. /// Try to handle the given placeholder expression kind. Return @@ -103,8 +118,12 @@ namespace { } void checkObjCARCConversion(Sema::CheckedConversionKind CCK) { + assert(Self.getLangOpts().ObjCAutoRefCount); + Expr *src = SrcExpr.get(); - Self.CheckObjCARCConversion(OpRange, DestType, src, CCK); + if (Self.CheckObjCARCConversion(OpRange, DestType, src, CCK) == + Sema::ACR_unbridged) + IsARCUnbridgedCast = true; SrcExpr = src; } @@ -171,15 +190,15 @@ static TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, Sema::CheckedConversionKind CCK, const SourceRange &OpRange, - unsigned &msg, - CastKind &Kind); + unsigned &msg, CastKind &Kind, + bool ListInitialization); static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, Sema::CheckedConversionKind CCK, const SourceRange &OpRange, - unsigned &msg, - CastKind &Kind, - CXXCastPath &BasePath); + unsigned &msg, CastKind &Kind, + CXXCastPath &BasePath, + bool ListInitialization); static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, unsigned &msg); static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, @@ -203,7 +222,7 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, if (D.isInvalidType()) return ExprError(); - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { // Check that there are no default arguments (C++ only). CheckExtraCXXDefaultArguments(D); } @@ -237,9 +256,9 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, if (Op.SrcExpr.isInvalid()) return ExprError(); } - return Owned(CXXConstCastExpr::Create(Context, Op.ResultType, Op.ValueKind, - Op.SrcExpr.take(), DestTInfo, OpLoc, - Parens.getEnd())); + return Op.complete(CXXConstCastExpr::Create(Context, Op.ResultType, + Op.ValueKind, Op.SrcExpr.take(), DestTInfo, + OpLoc, Parens.getEnd())); case tok::kw_dynamic_cast: { if (!TypeDependent) { @@ -247,10 +266,10 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, if (Op.SrcExpr.isInvalid()) return ExprError(); } - return Owned(CXXDynamicCastExpr::Create(Context, Op.ResultType, - Op.ValueKind, Op.Kind, - Op.SrcExpr.take(), &Op.BasePath, - DestTInfo, OpLoc, Parens.getEnd())); + return Op.complete(CXXDynamicCastExpr::Create(Context, Op.ResultType, + Op.ValueKind, Op.Kind, Op.SrcExpr.take(), + &Op.BasePath, DestTInfo, + OpLoc, Parens.getEnd())); } case tok::kw_reinterpret_cast: { if (!TypeDependent) { @@ -258,11 +277,10 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, if (Op.SrcExpr.isInvalid()) return ExprError(); } - return Owned(CXXReinterpretCastExpr::Create(Context, Op.ResultType, - Op.ValueKind, Op.Kind, - Op.SrcExpr.take(), 0, - DestTInfo, OpLoc, - Parens.getEnd())); + return Op.complete(CXXReinterpretCastExpr::Create(Context, Op.ResultType, + Op.ValueKind, Op.Kind, Op.SrcExpr.take(), + 0, DestTInfo, OpLoc, + Parens.getEnd())); } case tok::kw_static_cast: { if (!TypeDependent) { @@ -271,21 +289,20 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, return ExprError(); } - return Owned(CXXStaticCastExpr::Create(Context, Op.ResultType, Op.ValueKind, - Op.Kind, Op.SrcExpr.take(), - &Op.BasePath, DestTInfo, OpLoc, - Parens.getEnd())); + return Op.complete(CXXStaticCastExpr::Create(Context, Op.ResultType, + Op.ValueKind, Op.Kind, Op.SrcExpr.take(), + &Op.BasePath, DestTInfo, + OpLoc, Parens.getEnd())); } } - - return ExprError(); } /// Try to diagnose a failed overloaded cast. Returns true if /// diagnostics were emitted. static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT, SourceRange range, Expr *src, - QualType destType) { + QualType destType, + bool listInitialization) { switch (CT) { // These cast kinds don't consider user-defined conversions. case CT_Const: @@ -307,8 +324,9 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT, InitializedEntity entity = InitializedEntity::InitializeTemporary(destType); InitializationKind initKind = (CT == CT_CStyle)? InitializationKind::CreateCStyleCast(range.getBegin(), - range) - : (CT == CT_Functional)? InitializationKind::CreateFunctionalCast(range) + range, listInitialization) + : (CT == CT_Functional)? InitializationKind::CreateFunctionalCast(range, + listInitialization) : InitializationKind::CreateCast(/*type range?*/ range); InitializationSequence sequence(S, entity, initKind, &src, 1); @@ -328,7 +346,6 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT, switch (sequence.getFailedOverloadResult()) { case OR_Success: llvm_unreachable("successful failed overload"); - return false; case OR_No_Viable_Function: if (candidates.empty()) msg = diag::err_ovl_no_conversion_in_cast; @@ -352,21 +369,23 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT, << CT << srcType << destType << range << src->getSourceRange(); - candidates.NoteCandidates(S, howManyCandidates, &src, 1); + candidates.NoteCandidates(S, howManyCandidates, src); return true; } /// Diagnose a failed cast. static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType, - SourceRange opRange, Expr *src, QualType destType) { + SourceRange opRange, Expr *src, QualType destType, + bool listInitialization) { if (src->getType() == S.Context.BoundMemberTy) { (void) S.CheckPlaceholderExpr(src); // will always fail return; } if (msg == diag::err_bad_cxx_cast_generic && - tryDiagnoseOverloadedCast(S, castType, opRange, src, destType)) + tryDiagnoseOverloadedCast(S, castType, opRange, src, destType, + listInitialization)) return; S.Diag(opRange.getBegin(), msg) << castType @@ -443,7 +462,7 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType, // If the only checking we care about is for Objective-C lifetime qualifiers, // and we're not in ARC mode, there's nothing to check. if (!CheckCVR && CheckObjCLifetime && - !Self.Context.getLangOptions().ObjCAutoRefCount) + !Self.Context.getLangOpts().ObjCAutoRefCount) return false; // Casting away constness is defined in C++ 5.2.11p8 with reference to @@ -511,6 +530,13 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType, /// Refer to C++ 5.2.7 for details. Dynamic casts are used mostly for runtime- /// checked downcasts in class hierarchies. void CastOperation::CheckDynamicCast() { + if (ValueKind == VK_RValue) + SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); + else if (isPlaceholder()) + SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take()); + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + QualType OrigSrcType = SrcExpr.get()->getType(); QualType DestType = Self.Context.getCanonicalType(this->DestType); @@ -638,11 +664,12 @@ void CastOperation::CheckDynamicCast() { /// const char *str = "literal"; /// legacy_function(const_cast\<char*\>(str)); void CastOperation::CheckConstCast() { - if (ValueKind == VK_RValue && !isPlaceholder(BuiltinType::Overload)) { + if (ValueKind == VK_RValue) SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); - if (SrcExpr.isInvalid()) // if conversion failed, don't report another error - return; - } + else if (isPlaceholder()) + SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take()); + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; unsigned msg = diag::err_bad_cxx_cast_generic; if (TryConstCast(Self, SrcExpr.get(), DestType, /*CStyle*/false, msg) != TC_Success @@ -657,11 +684,12 @@ void CastOperation::CheckConstCast() { /// like this: /// char *bytes = reinterpret_cast\<char*\>(int_ptr); void CastOperation::CheckReinterpretCast() { - if (ValueKind == VK_RValue && !isPlaceholder(BuiltinType::Overload)) { + if (ValueKind == VK_RValue && !isPlaceholder(BuiltinType::Overload)) SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); - if (SrcExpr.isInvalid()) // if conversion failed, don't report another error - return; - } + else + checkNonOverloadPlaceholders(); + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; unsigned msg = diag::err_bad_cxx_cast_generic; TryCastResult tcr = @@ -679,9 +707,10 @@ void CastOperation::CheckReinterpretCast() { Self.NoteAllOverloadCandidates(SrcExpr.get()); } else { - diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(), DestType); + diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(), + DestType, /*listInitialization=*/false); } - } else if (tcr == TC_Success && Self.getLangOptions().ObjCAutoRefCount) { + } else if (tcr == TC_Success && Self.getLangOpts().ObjCAutoRefCount) { checkObjCARCConversion(Sema::CCK_OtherCast); } } @@ -726,7 +755,7 @@ void CastOperation::CheckStaticCast() { unsigned msg = diag::err_bad_cxx_cast_generic; TryCastResult tcr = TryStaticCast(Self, SrcExpr, DestType, Sema::CCK_OtherCast, OpRange, msg, - Kind, BasePath); + Kind, BasePath, /*ListInitialization=*/false); if (tcr != TC_Success && msg != 0) { if (SrcExpr.isInvalid()) return; @@ -737,12 +766,13 @@ void CastOperation::CheckStaticCast() { << oe->getQualifierLoc().getSourceRange(); Self.NoteAllOverloadCandidates(SrcExpr.get()); } else { - diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType); + diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType, + /*listInitialization=*/false); } } else if (tcr == TC_Success) { if (Kind == CK_BitCast) checkCastAlign(); - if (Self.getLangOptions().ObjCAutoRefCount) + if (Self.getLangOpts().ObjCAutoRefCount) checkObjCARCConversion(Sema::CCK_OtherCast); } else if (Kind == CK_BitCast) { checkCastAlign(); @@ -756,8 +786,8 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, Sema::CheckedConversionKind CCK, const SourceRange &OpRange, unsigned &msg, - CastKind &Kind, - CXXCastPath &BasePath) { + CastKind &Kind, CXXCastPath &BasePath, + bool ListInitialization) { // Determine whether we have the semantics of a C-style cast. bool CStyle = (CCK == Sema::CCK_CStyleCast || CCK == Sema::CCK_FunctionalCast); @@ -782,23 +812,23 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, // C++ 5.2.9p5, reference downcast. // See the function for details. // DR 427 specifies that this is to be applied before paragraph 2. - tcr = TryStaticReferenceDowncast(Self, SrcExpr.get(), DestType, CStyle, OpRange, - msg, Kind, BasePath); + tcr = TryStaticReferenceDowncast(Self, SrcExpr.get(), DestType, CStyle, + OpRange, msg, Kind, BasePath); if (tcr != TC_NotApplicable) return tcr; // C++0x [expr.static.cast]p3: // A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2 // T2" if "cv2 T2" is reference-compatible with "cv1 T1". - tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind, BasePath, - msg); + tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind, + BasePath, msg); if (tcr != TC_NotApplicable) return tcr; // C++ 5.2.9p2: An expression e can be explicitly converted to a type T // [...] if the declaration "T t(e);" is well-formed, [...]. tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CCK, OpRange, msg, - Kind); + Kind, ListInitialization); if (SrcExpr.isInvalid()) return TC_Failed; if (tcr != TC_NotApplicable) @@ -1269,7 +1299,7 @@ TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, Sema::CheckedConversionKind CCK, const SourceRange &OpRange, unsigned &msg, - CastKind &Kind) { + CastKind &Kind, bool ListInitialization) { if (DestType->isRecordType()) { if (Self.RequireCompleteType(OpRange.getBegin(), DestType, diag::err_bad_dynamic_cast_incomplete)) { @@ -1277,13 +1307,14 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, return TC_Failed; } } - + InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType); InitializationKind InitKind = (CCK == Sema::CCK_CStyleCast) - ? InitializationKind::CreateCStyleCast(OpRange.getBegin(), OpRange) + ? InitializationKind::CreateCStyleCast(OpRange.getBegin(), OpRange, + ListInitialization) : (CCK == Sema::CCK_FunctionalCast) - ? InitializationKind::CreateFunctionalCast(OpRange) + ? InitializationKind::CreateFunctionalCast(OpRange, ListInitialization) : InitializationKind::CreateCast(OpRange); Expr *SrcExprRaw = SrcExpr.get(); InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExprRaw, 1); @@ -1497,6 +1528,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, case OK_BitField: inappropriate = "bit-field"; break; case OK_VectorComponent: inappropriate = "vector element"; break; case OK_ObjCProperty: inappropriate = "property expression"; break; + case OK_ObjCSubscript: inappropriate = "container subscripting expression"; + break; } if (inappropriate) { Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_reference) @@ -1545,7 +1578,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, } // A valid member pointer cast. - Kind = IsLValueCast? CK_LValueBitCast : CK_BitCast; + assert(!IsLValueCast); + Kind = CK_ReinterpretMemberPointer; return TC_Success; } @@ -1592,7 +1626,27 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, return TC_Failed; } - + + if (SrcType == DestType) { + // C++ 5.2.10p2 has a note that mentions that, subject to all other + // restrictions, a cast to the same type is allowed so long as it does not + // cast away constness. In C++98, the intent was not entirely clear here, + // since all other paragraphs explicitly forbid casts to the same type. + // C++11 clarifies this case with p2. + // + // The only allowed types are: integral, enumeration, pointer, or + // pointer-to-member types. We also won't restrict Obj-C pointers either. + Kind = CK_NoOp; + TryCastResult Result = TC_NotApplicable; + if (SrcType->isIntegralOrEnumerationType() || + SrcType->isAnyPointerType() || + SrcType->isMemberPointerType() || + SrcType->isBlockPointerType()) { + Result = TC_Success; + } + return Result; + } + bool destIsPtr = DestType->isAnyPointerType() || DestType->isBlockPointerType(); bool srcIsPtr = SrcType->isAnyPointerType() || @@ -1603,17 +1657,6 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, return TC_NotApplicable; } - if (SrcType == DestType) { - // C++ 5.2.10p2 has a note that mentions that, subject to all other - // restrictions, a cast to the same type is allowed. The intent is not - // entirely clear here, since all other paragraphs explicitly forbid casts - // to the same type. However, the behavior of compilers is pretty consistent - // on this point: allow same-type conversion if the involved types are - // pointers, disallow otherwise. - Kind = CK_NoOp; - return TC_Success; - } - if (DestType->isIntegralType(Self.Context)) { assert(srcIsPtr && "One type must be a pointer"); // C++ 5.2.10p4: A pointer can be explicitly converted to any integral @@ -1621,7 +1664,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, // integral type size doesn't matter. if ((Self.Context.getTypeSize(SrcType) > Self.Context.getTypeSize(DestType)) && - !Self.getLangOptions().MicrosoftExt) { + !Self.getLangOpts().MicrosoftExt) { msg = diag::err_bad_reinterpret_cast_small_int; return TC_Failed; } @@ -1694,15 +1737,19 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, // casting the return value of dlsym() and GetProcAddress(). // FIXME: Conditionally-supported behavior should be configurable in the // TargetInfo or similar. - if (!Self.getLangOptions().CPlusPlus0x) - Self.Diag(OpRange.getBegin(), diag::ext_cast_fn_obj) << OpRange; + Self.Diag(OpRange.getBegin(), + Self.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj) + << OpRange; return TC_Success; } if (DestType->isFunctionPointerType()) { // See above. - if (!Self.getLangOptions().CPlusPlus0x) - Self.Diag(OpRange.getBegin(), diag::ext_cast_fn_obj) << OpRange; + Self.Diag(OpRange.getBegin(), + Self.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj) + << OpRange; return TC_Success; } @@ -1714,7 +1761,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, return TC_Success; } -void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle) { +void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, + bool ListInitialization) { // Handle placeholders. if (isPlaceholder()) { // C-style casts can resolve __unknown_any types. @@ -1728,7 +1776,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle) { checkNonOverloadPlaceholders(); if (SrcExpr.isInvalid()) return; - } + } // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". // This test is outside everything else because it's the only case where @@ -1797,7 +1845,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle) { if (tcr == TC_NotApplicable) { // ... or if that is not possible, a static_cast, ignoring const, ... tcr = TryStaticCast(Self, SrcExpr, DestType, CCK, OpRange, - msg, Kind, BasePath); + msg, Kind, BasePath, ListInitialization); if (SrcExpr.isInvalid()) return; @@ -1810,7 +1858,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle) { } } - if (Self.getLangOptions().ObjCAutoRefCount && tcr == TC_Success) + if (Self.getLangOpts().ObjCAutoRefCount && tcr == TC_Success) checkObjCARCConversion(CCK); if (tcr != TC_Success && msg != 0) { @@ -1826,7 +1874,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle) { } else { diagnoseBadCast(Self, msg, (FunctionalStyle ? CT_Functional : CT_CStyle), - OpRange, SrcExpr.get(), DestType); + OpRange, SrcExpr.get(), DestType, ListInitialization); } } else if (Kind == CK_BitCast) { checkCastAlign(); @@ -1839,26 +1887,15 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle) { /// Check the semantics of a C-style cast operation, in C. void CastOperation::CheckCStyleCast() { - assert(!Self.getLangOptions().CPlusPlus); + assert(!Self.getLangOpts().CPlusPlus); - // Handle placeholders. - if (isPlaceholder()) { - // C-style casts can resolve __unknown_any types. - if (claimPlaceholder(BuiltinType::UnknownAny)) { - SrcExpr = Self.checkUnknownAnyCast(DestRange, DestType, - SrcExpr.get(), Kind, - ValueKind, BasePath); - return; - } - - // We allow overloads in C, but we don't allow them to be resolved - // by anything except calls. - SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take()); - if (SrcExpr.isInvalid()) - return; - } - - assert(!isPlaceholder()); + // C-style casts can resolve __unknown_any types. + if (claimPlaceholder(BuiltinType::UnknownAny)) { + SrcExpr = Self.checkUnknownAnyCast(DestRange, DestType, + SrcExpr.get(), Kind, + ValueKind, BasePath); + return; + } // C99 6.5.4p2: the cast type needs to be void or scalar and the expression // type needs to be scalar. @@ -1878,6 +1915,12 @@ void CastOperation::CheckCStyleCast() { return; QualType SrcType = SrcExpr.get()->getType(); + // You can cast an _Atomic(T) to anything you can cast a T to. + if (const AtomicType *AtomicSrcType = SrcType->getAs<AtomicType>()) + SrcType = AtomicSrcType->getValueType(); + + assert(!SrcType->isPlaceholderType()); + if (Self.RequireCompleteType(OpRange.getBegin(), DestType, diag::err_typecheck_cast_to_incomplete)) { SrcExpr = ExprError(); @@ -1983,14 +2026,14 @@ void CastOperation::CheckCStyleCast() { DestType->isArithmeticType()) { Self.Diag(SrcExpr.get()->getLocStart(), diag::err_cast_pointer_to_non_pointer_int) - << SrcType << SrcExpr.get()->getSourceRange(); + << DestType << SrcExpr.get()->getSourceRange(); SrcExpr = ExprError(); return; } } // ARC imposes extra restrictions on casts. - if (Self.getLangOptions().ObjCAutoRefCount) { + if (Self.getLangOpts().ObjCAutoRefCount) { checkObjCARCConversion(Sema::CCK_CStyleCast); if (SrcExpr.isInvalid()) return; @@ -2035,8 +2078,9 @@ ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc, Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange(); Op.OpRange = SourceRange(LPLoc, CastExpr->getLocEnd()); - if (getLangOptions().CPlusPlus) { - Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ false); + if (getLangOpts().CPlusPlus) { + Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ false, + isa<InitListExpr>(CastExpr)); } else { Op.CheckCStyleCast(); } @@ -2044,26 +2088,25 @@ ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc, if (Op.SrcExpr.isInvalid()) return ExprError(); - return Owned(CStyleCastExpr::Create(Context, Op.ResultType, Op.ValueKind, - Op.Kind, Op.SrcExpr.take(), &Op.BasePath, - CastTypeInfo, LPLoc, RPLoc)); + return Op.complete(CStyleCastExpr::Create(Context, Op.ResultType, + Op.ValueKind, Op.Kind, Op.SrcExpr.take(), + &Op.BasePath, CastTypeInfo, LPLoc, RPLoc)); } ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo, SourceLocation LPLoc, Expr *CastExpr, SourceLocation RPLoc) { + assert(LPLoc.isValid() && "List-initialization shouldn't get here."); CastOperation Op(*this, CastTypeInfo->getType(), CastExpr); Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange(); Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getLocEnd()); - Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ true); + Op.CheckCXXCStyleCast(/*FunctionalStyle=*/true, /*ListInit=*/false); if (Op.SrcExpr.isInvalid()) return ExprError(); - return Owned(CXXFunctionalCastExpr::Create(Context, Op.ResultType, - Op.ValueKind, CastTypeInfo, - Op.DestRange.getBegin(), - Op.Kind, Op.SrcExpr.take(), - &Op.BasePath, RPLoc)); + return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType, + Op.ValueKind, CastTypeInfo, Op.DestRange.getBegin(), + Op.Kind, Op.SrcExpr.take(), &Op.BasePath, RPLoc)); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp index a6c49bb..fdc2349 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp @@ -30,6 +30,7 @@ #include "clang/AST/StmtObjC.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/raw_ostream.h" #include "clang/Basic/TargetBuiltins.h" @@ -42,31 +43,7 @@ using namespace sema; SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL, unsigned ByteNo) const { return SL->getLocationOfByte(ByteNo, PP.getSourceManager(), - PP.getLangOptions(), PP.getTargetInfo()); -} - - -/// CheckablePrintfAttr - does a function call have a "printf" attribute -/// and arguments that merit checking? -bool Sema::CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall) { - if (Format->getType() == "printf") return true; - if (Format->getType() == "printf0") { - // printf0 allows null "format" string; if so don't check format/args - unsigned format_idx = Format->getFormatIdx() - 1; - // Does the index refer to the implicit object argument? - if (isa<CXXMemberCallExpr>(TheCall)) { - if (format_idx == 0) - return false; - --format_idx; - } - if (format_idx < TheCall->getNumArgs()) { - Expr *Format = TheCall->getArg(format_idx)->IgnoreParenCasts(); - if (!Format->isNullPointerConstant(Context, - Expr::NPC_ValueDependentIsNull)) - return true; - } - } - return false; + PP.getLangOpts(), PP.getTargetInfo()); } /// Checks that a call expression's argument count is the desired number. @@ -183,43 +160,101 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { TheCall->setType(Context.IntTy); break; case Builtin::BI__sync_fetch_and_add: + case Builtin::BI__sync_fetch_and_add_1: + case Builtin::BI__sync_fetch_and_add_2: + case Builtin::BI__sync_fetch_and_add_4: + case Builtin::BI__sync_fetch_and_add_8: + case Builtin::BI__sync_fetch_and_add_16: case Builtin::BI__sync_fetch_and_sub: + case Builtin::BI__sync_fetch_and_sub_1: + case Builtin::BI__sync_fetch_and_sub_2: + case Builtin::BI__sync_fetch_and_sub_4: + case Builtin::BI__sync_fetch_and_sub_8: + case Builtin::BI__sync_fetch_and_sub_16: case Builtin::BI__sync_fetch_and_or: + case Builtin::BI__sync_fetch_and_or_1: + case Builtin::BI__sync_fetch_and_or_2: + case Builtin::BI__sync_fetch_and_or_4: + case Builtin::BI__sync_fetch_and_or_8: + case Builtin::BI__sync_fetch_and_or_16: case Builtin::BI__sync_fetch_and_and: + case Builtin::BI__sync_fetch_and_and_1: + case Builtin::BI__sync_fetch_and_and_2: + case Builtin::BI__sync_fetch_and_and_4: + case Builtin::BI__sync_fetch_and_and_8: + case Builtin::BI__sync_fetch_and_and_16: case Builtin::BI__sync_fetch_and_xor: + case Builtin::BI__sync_fetch_and_xor_1: + case Builtin::BI__sync_fetch_and_xor_2: + case Builtin::BI__sync_fetch_and_xor_4: + case Builtin::BI__sync_fetch_and_xor_8: + case Builtin::BI__sync_fetch_and_xor_16: case Builtin::BI__sync_add_and_fetch: + case Builtin::BI__sync_add_and_fetch_1: + case Builtin::BI__sync_add_and_fetch_2: + case Builtin::BI__sync_add_and_fetch_4: + case Builtin::BI__sync_add_and_fetch_8: + case Builtin::BI__sync_add_and_fetch_16: case Builtin::BI__sync_sub_and_fetch: + case Builtin::BI__sync_sub_and_fetch_1: + case Builtin::BI__sync_sub_and_fetch_2: + case Builtin::BI__sync_sub_and_fetch_4: + case Builtin::BI__sync_sub_and_fetch_8: + case Builtin::BI__sync_sub_and_fetch_16: case Builtin::BI__sync_and_and_fetch: + case Builtin::BI__sync_and_and_fetch_1: + case Builtin::BI__sync_and_and_fetch_2: + case Builtin::BI__sync_and_and_fetch_4: + case Builtin::BI__sync_and_and_fetch_8: + case Builtin::BI__sync_and_and_fetch_16: case Builtin::BI__sync_or_and_fetch: + case Builtin::BI__sync_or_and_fetch_1: + case Builtin::BI__sync_or_and_fetch_2: + case Builtin::BI__sync_or_and_fetch_4: + case Builtin::BI__sync_or_and_fetch_8: + case Builtin::BI__sync_or_and_fetch_16: case Builtin::BI__sync_xor_and_fetch: + case Builtin::BI__sync_xor_and_fetch_1: + case Builtin::BI__sync_xor_and_fetch_2: + case Builtin::BI__sync_xor_and_fetch_4: + case Builtin::BI__sync_xor_and_fetch_8: + case Builtin::BI__sync_xor_and_fetch_16: case Builtin::BI__sync_val_compare_and_swap: + case Builtin::BI__sync_val_compare_and_swap_1: + case Builtin::BI__sync_val_compare_and_swap_2: + case Builtin::BI__sync_val_compare_and_swap_4: + case Builtin::BI__sync_val_compare_and_swap_8: + case Builtin::BI__sync_val_compare_and_swap_16: case Builtin::BI__sync_bool_compare_and_swap: + case Builtin::BI__sync_bool_compare_and_swap_1: + case Builtin::BI__sync_bool_compare_and_swap_2: + case Builtin::BI__sync_bool_compare_and_swap_4: + case Builtin::BI__sync_bool_compare_and_swap_8: + case Builtin::BI__sync_bool_compare_and_swap_16: case Builtin::BI__sync_lock_test_and_set: + case Builtin::BI__sync_lock_test_and_set_1: + case Builtin::BI__sync_lock_test_and_set_2: + case Builtin::BI__sync_lock_test_and_set_4: + case Builtin::BI__sync_lock_test_and_set_8: + case Builtin::BI__sync_lock_test_and_set_16: case Builtin::BI__sync_lock_release: + case Builtin::BI__sync_lock_release_1: + case Builtin::BI__sync_lock_release_2: + case Builtin::BI__sync_lock_release_4: + case Builtin::BI__sync_lock_release_8: + case Builtin::BI__sync_lock_release_16: case Builtin::BI__sync_swap: + case Builtin::BI__sync_swap_1: + case Builtin::BI__sync_swap_2: + case Builtin::BI__sync_swap_4: + case Builtin::BI__sync_swap_8: + case Builtin::BI__sync_swap_16: return SemaBuiltinAtomicOverloaded(move(TheCallResult)); - case Builtin::BI__atomic_load: - return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Load); - case Builtin::BI__atomic_store: - return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Store); - case Builtin::BI__atomic_exchange: - return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Xchg); - case Builtin::BI__atomic_compare_exchange_strong: - return SemaAtomicOpsOverloaded(move(TheCallResult), - AtomicExpr::CmpXchgStrong); - case Builtin::BI__atomic_compare_exchange_weak: - return SemaAtomicOpsOverloaded(move(TheCallResult), - AtomicExpr::CmpXchgWeak); - case Builtin::BI__atomic_fetch_add: - return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Add); - case Builtin::BI__atomic_fetch_sub: - return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Sub); - case Builtin::BI__atomic_fetch_and: - return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::And); - case Builtin::BI__atomic_fetch_or: - return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Or); - case Builtin::BI__atomic_fetch_xor: - return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Xor); +#define BUILTIN(ID, TYPE, ATTRS) +#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ + case Builtin::BI##ID: \ + return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::AO##ID); +#include "clang/Basic/Builtins.def" case Builtin::BI__builtin_annotation: if (CheckBuiltinAnnotationString(*this, TheCall->getArg(1))) return ExprError(); @@ -245,29 +280,52 @@ 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) { - bool quad = t & 0x10; - - switch (t & 0x7) { - case 0: // i8 - return shift ? 7 : (8 << (int)quad) - 1; - case 1: // i16 - return shift ? 15 : (4 << (int)quad) - 1; - case 2: // i32 - return shift ? 31 : (2 << (int)quad) - 1; - case 3: // i64 - return shift ? 63 : (1 << (int)quad) - 1; - case 4: // f32 - assert(!shift && "cannot shift float types!"); - return (2 << (int)quad) - 1; - case 5: // poly8 - return shift ? 7 : (8 << (int)quad) - 1; - case 6: // poly16 - return shift ? 15 : (4 << (int)quad) - 1; - case 7: // float16 - assert(!shift && "cannot shift float types!"); - return (4 << (int)quad) - 1; - } - return 0; + NeonTypeFlags Type(t); + int IsQuad = Type.isQuad(); + switch (Type.getEltType()) { + case NeonTypeFlags::Int8: + case NeonTypeFlags::Poly8: + return shift ? 7 : (8 << IsQuad) - 1; + case NeonTypeFlags::Int16: + case NeonTypeFlags::Poly16: + return shift ? 15 : (4 << IsQuad) - 1; + case NeonTypeFlags::Int32: + return shift ? 31 : (2 << IsQuad) - 1; + case NeonTypeFlags::Int64: + return shift ? 63 : (1 << IsQuad) - 1; + case NeonTypeFlags::Float16: + assert(!shift && "cannot shift float types!"); + return (4 << IsQuad) - 1; + case NeonTypeFlags::Float32: + assert(!shift && "cannot shift float types!"); + return (2 << IsQuad) - 1; + } + llvm_unreachable("Invalid NeonTypeFlag!"); +} + +/// getNeonEltType - Return the QualType corresponding to the elements of +/// 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) { + switch (Flags.getEltType()) { + case NeonTypeFlags::Int8: + return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy; + case NeonTypeFlags::Int16: + return Flags.isUnsigned() ? Context.UnsignedShortTy : Context.ShortTy; + case NeonTypeFlags::Int32: + return Flags.isUnsigned() ? Context.UnsignedIntTy : Context.IntTy; + case NeonTypeFlags::Int64: + return Flags.isUnsigned() ? Context.UnsignedLongLongTy : Context.LongLongTy; + case NeonTypeFlags::Poly8: + return Context.SignedCharTy; + case NeonTypeFlags::Poly16: + return Context.ShortTy; + case NeonTypeFlags::Float16: + return Context.UnsignedShortTy; + case NeonTypeFlags::Float32: + return Context.FloatTy; + } + llvm_unreachable("Invalid NeonTypeFlag!"); } bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { @@ -275,6 +333,8 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { unsigned mask = 0; unsigned TV = 0; + int PtrArgNum = -1; + bool HasConstPtr = false; switch (BuiltinID) { #define GET_NEON_OVERLOAD_CHECK #include "clang/Basic/arm_neon.inc" @@ -283,15 +343,35 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { // 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) { - unsigned ArgNo = TheCall->getNumArgs()-1; - if (SemaBuiltinConstantArg(TheCall, ArgNo, Result)) + if (SemaBuiltinConstantArg(TheCall, ImmArg, Result)) return true; - TV = Result.getLimitedValue(32); - if ((TV > 31) || (mask & (1 << TV)) == 0) + TV = Result.getLimitedValue(64); + if ((TV > 63) || (mask & (1 << TV)) == 0) return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code) - << TheCall->getArg(ArgNo)->getSourceRange(); + << TheCall->getArg(ImmArg)->getSourceRange(); + } + + 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); + 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 @@ -341,16 +421,7 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { for (specific_attr_iterator<FormatAttr> i = FDecl->specific_attr_begin<FormatAttr>(), e = FDecl->specific_attr_end<FormatAttr>(); i != e ; ++i) { - - const FormatAttr *Format = *i; - const bool b = Format->getType() == "scanf"; - if (b || CheckablePrintfAttr(Format, TheCall)) { - bool HasVAListArg = Format->getFirstArg() == 0; - CheckPrintfScanfArguments(TheCall, HasVAListArg, - Format->getFormatIdx() - 1, - HasVAListArg ? 0 : Format->getFirstArg() - 1, - !b); - } + CheckFormatArguments(*i, TheCall); } for (specific_attr_iterator<NonNullAttr> @@ -360,98 +431,42 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { TheCall->getCallee()->getLocStart()); } - // Builtin handling - int CMF = -1; - switch (FDecl->getBuiltinID()) { - case Builtin::BI__builtin_memset: - case Builtin::BI__builtin___memset_chk: - case Builtin::BImemset: - CMF = CMF_Memset; - break; - - case Builtin::BI__builtin_memcpy: - case Builtin::BI__builtin___memcpy_chk: - case Builtin::BImemcpy: - CMF = CMF_Memcpy; - break; - - case Builtin::BI__builtin_memmove: - case Builtin::BI__builtin___memmove_chk: - case Builtin::BImemmove: - CMF = CMF_Memmove; - break; + unsigned CMId = FDecl->getMemoryFunctionKind(); + if (CMId == 0) + return false; - case Builtin::BIstrlcpy: - case Builtin::BIstrlcat: + // Handle memory setting and copying functions. + if (CMId == Builtin::BIstrlcpy || CMId == Builtin::BIstrlcat) CheckStrlcpycatArguments(TheCall, FnInfo); - break; - - case Builtin::BI__builtin_memcmp: - CMF = CMF_Memcmp; - break; - - case Builtin::BI__builtin_strncpy: - case Builtin::BI__builtin___strncpy_chk: - case Builtin::BIstrncpy: - CMF = CMF_Strncpy; - break; - - case Builtin::BI__builtin_strncmp: - CMF = CMF_Strncmp; - break; + else if (CMId == Builtin::BIstrncat) + CheckStrncatArguments(TheCall, FnInfo); + else + CheckMemaccessArguments(TheCall, CMId, FnInfo); - case Builtin::BI__builtin_strncasecmp: - CMF = CMF_Strncasecmp; - break; + return false; +} - case Builtin::BI__builtin_strncat: - case Builtin::BIstrncat: - CMF = CMF_Strncat; - break; +bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac, + Expr **Args, unsigned NumArgs) { + for (specific_attr_iterator<FormatAttr> + i = Method->specific_attr_begin<FormatAttr>(), + e = Method->specific_attr_end<FormatAttr>(); i != e ; ++i) { - case Builtin::BI__builtin_strndup: - case Builtin::BIstrndup: - CMF = CMF_Strndup; - break; + CheckFormatArguments(*i, Args, NumArgs, false, lbrac, + Method->getSourceRange()); + } - default: - if (FDecl->getLinkage() == ExternalLinkage && - (!getLangOptions().CPlusPlus || FDecl->isExternC())) { - if (FnInfo->isStr("memset")) - CMF = CMF_Memset; - else if (FnInfo->isStr("memcpy")) - CMF = CMF_Memcpy; - else if (FnInfo->isStr("memmove")) - CMF = CMF_Memmove; - else if (FnInfo->isStr("memcmp")) - CMF = CMF_Memcmp; - else if (FnInfo->isStr("strncpy")) - CMF = CMF_Strncpy; - else if (FnInfo->isStr("strncmp")) - CMF = CMF_Strncmp; - else if (FnInfo->isStr("strncasecmp")) - CMF = CMF_Strncasecmp; - else if (FnInfo->isStr("strncat")) - CMF = CMF_Strncat; - else if (FnInfo->isStr("strndup")) - CMF = CMF_Strndup; - } - break; + // diagnose nonnull arguments. + for (specific_attr_iterator<NonNullAttr> + i = Method->specific_attr_begin<NonNullAttr>(), + e = Method->specific_attr_end<NonNullAttr>(); i != e; ++i) { + CheckNonNullArguments(*i, Args, lbrac); } - - // Memset/memcpy/memmove handling - if (CMF != -1) - CheckMemaccessArguments(TheCall, CheckedMemoryFunction(CMF), FnInfo); return false; } bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) { - // Printf checking. - const FormatAttr *Format = NDecl->getAttr<FormatAttr>(); - if (!Format) - return false; - const VarDecl *V = dyn_cast<VarDecl>(NDecl); if (!V) return false; @@ -460,84 +475,187 @@ bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) { if (!Ty->isBlockPointerType()) return false; - const bool b = Format->getType() == "scanf"; - if (!b && !CheckablePrintfAttr(Format, TheCall)) - return false; - - bool HasVAListArg = Format->getFirstArg() == 0; - CheckPrintfScanfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1, - HasVAListArg ? 0 : Format->getFirstArg() - 1, !b); + // format string checking. + for (specific_attr_iterator<FormatAttr> + i = NDecl->specific_attr_begin<FormatAttr>(), + e = NDecl->specific_attr_end<FormatAttr>(); i != e ; ++i) { + CheckFormatArguments(*i, TheCall); + } return false; } -ExprResult -Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, AtomicExpr::AtomicOp Op) { +ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, + AtomicExpr::AtomicOp Op) { CallExpr *TheCall = cast<CallExpr>(TheCallResult.get()); DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts()); - // All these operations take one of the following four forms: - // T __atomic_load(_Atomic(T)*, int) (loads) - // T* __atomic_add(_Atomic(T*)*, ptrdiff_t, int) (pointer add/sub) - // int __atomic_compare_exchange_strong(_Atomic(T)*, T*, T, int, int) - // (cmpxchg) - // T __atomic_exchange(_Atomic(T)*, T, int) (everything else) - // where T is an appropriate type, and the int paremeterss are for orderings. - unsigned NumVals = 1; - unsigned NumOrders = 1; - if (Op == AtomicExpr::Load) { - NumVals = 0; - } else if (Op == AtomicExpr::CmpXchgWeak || Op == AtomicExpr::CmpXchgStrong) { - NumVals = 2; - NumOrders = 2; - } - - if (TheCall->getNumArgs() < NumVals+NumOrders+1) { + // All these operations take one of the following forms: + enum { + // C __c11_atomic_init(A *, C) + Init, + // C __c11_atomic_load(A *, int) + Load, + // void __atomic_load(A *, CP, int) + Copy, + // C __c11_atomic_add(A *, M, int) + Arithmetic, + // C __atomic_exchange_n(A *, CP, int) + Xchg, + // void __atomic_exchange(A *, C *, CP, int) + GNUXchg, + // bool __c11_atomic_compare_exchange_strong(A *, C *, CP, int, int) + C11CmpXchg, + // bool __atomic_compare_exchange(A *, C *, CP, bool, int, int) + GNUCmpXchg + } Form = Init; + const unsigned NumArgs[] = { 2, 2, 3, 3, 3, 4, 5, 6 }; + const unsigned NumVals[] = { 1, 0, 1, 1, 1, 2, 2, 3 }; + // where: + // C is an appropriate type, + // A is volatile _Atomic(C) for __c11 builtins and is C for GNU builtins, + // CP is C for __c11 builtins and GNU _n builtins and is C * otherwise, + // M is C if C is an integer, and ptrdiff_t if C is a pointer, and + // the int parameters are for orderings. + + assert(AtomicExpr::AO__c11_atomic_init == 0 && + AtomicExpr::AO__c11_atomic_fetch_xor + 1 == AtomicExpr::AO__atomic_load + && "need to update code for modified C11 atomics"); + bool IsC11 = Op >= AtomicExpr::AO__c11_atomic_init && + Op <= AtomicExpr::AO__c11_atomic_fetch_xor; + bool IsN = Op == AtomicExpr::AO__atomic_load_n || + Op == AtomicExpr::AO__atomic_store_n || + Op == AtomicExpr::AO__atomic_exchange_n || + Op == AtomicExpr::AO__atomic_compare_exchange_n; + bool IsAddSub = false; + + switch (Op) { + case AtomicExpr::AO__c11_atomic_init: + Form = Init; + break; + + case AtomicExpr::AO__c11_atomic_load: + case AtomicExpr::AO__atomic_load_n: + Form = Load; + break; + + case AtomicExpr::AO__c11_atomic_store: + case AtomicExpr::AO__atomic_load: + case AtomicExpr::AO__atomic_store: + case AtomicExpr::AO__atomic_store_n: + Form = Copy; + break; + + case AtomicExpr::AO__c11_atomic_fetch_add: + case AtomicExpr::AO__c11_atomic_fetch_sub: + case AtomicExpr::AO__atomic_fetch_add: + case AtomicExpr::AO__atomic_fetch_sub: + case AtomicExpr::AO__atomic_add_fetch: + case AtomicExpr::AO__atomic_sub_fetch: + IsAddSub = true; + // Fall through. + case AtomicExpr::AO__c11_atomic_fetch_and: + case AtomicExpr::AO__c11_atomic_fetch_or: + case AtomicExpr::AO__c11_atomic_fetch_xor: + case AtomicExpr::AO__atomic_fetch_and: + case AtomicExpr::AO__atomic_fetch_or: + case AtomicExpr::AO__atomic_fetch_xor: + case AtomicExpr::AO__atomic_fetch_nand: + case AtomicExpr::AO__atomic_and_fetch: + case AtomicExpr::AO__atomic_or_fetch: + case AtomicExpr::AO__atomic_xor_fetch: + case AtomicExpr::AO__atomic_nand_fetch: + Form = Arithmetic; + break; + + case AtomicExpr::AO__c11_atomic_exchange: + case AtomicExpr::AO__atomic_exchange_n: + Form = Xchg; + break; + + case AtomicExpr::AO__atomic_exchange: + Form = GNUXchg; + break; + + case AtomicExpr::AO__c11_atomic_compare_exchange_strong: + case AtomicExpr::AO__c11_atomic_compare_exchange_weak: + Form = C11CmpXchg; + break; + + case AtomicExpr::AO__atomic_compare_exchange: + case AtomicExpr::AO__atomic_compare_exchange_n: + Form = GNUCmpXchg; + break; + } + + // Check we have the right number of arguments. + if (TheCall->getNumArgs() < NumArgs[Form]) { Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) - << 0 << NumVals+NumOrders+1 << TheCall->getNumArgs() + << 0 << NumArgs[Form] << TheCall->getNumArgs() << TheCall->getCallee()->getSourceRange(); return ExprError(); - } else if (TheCall->getNumArgs() > NumVals+NumOrders+1) { - Diag(TheCall->getArg(NumVals+NumOrders+1)->getLocStart(), + } else if (TheCall->getNumArgs() > NumArgs[Form]) { + Diag(TheCall->getArg(NumArgs[Form])->getLocStart(), diag::err_typecheck_call_too_many_args) - << 0 << NumVals+NumOrders+1 << TheCall->getNumArgs() + << 0 << NumArgs[Form] << TheCall->getNumArgs() << TheCall->getCallee()->getSourceRange(); return ExprError(); } - // Inspect the first argument of the atomic operation. This should always be - // a pointer to an _Atomic type. + // Inspect the first argument of the atomic operation. Expr *Ptr = TheCall->getArg(0); Ptr = DefaultFunctionArrayLvalueConversion(Ptr).get(); const PointerType *pointerType = Ptr->getType()->getAs<PointerType>(); if (!pointerType) { - Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic) + Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer) << Ptr->getType() << Ptr->getSourceRange(); return ExprError(); } - QualType AtomTy = pointerType->getPointeeType(); - if (!AtomTy->isAtomicType()) { - Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic) - << Ptr->getType() << Ptr->getSourceRange(); - return ExprError(); + // For a __c11 builtin, this should be a pointer to an _Atomic type. + QualType AtomTy = pointerType->getPointeeType(); // 'A' + QualType ValType = AtomTy; // 'C' + if (IsC11) { + if (!AtomTy->isAtomicType()) { + Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic) + << Ptr->getType() << Ptr->getSourceRange(); + return ExprError(); + } + ValType = AtomTy->getAs<AtomicType>()->getValueType(); } - QualType ValType = AtomTy->getAs<AtomicType>()->getValueType(); - if ((Op == AtomicExpr::Add || Op == AtomicExpr::Sub) && - !ValType->isIntegerType() && !ValType->isPointerType()) { + // For an arithmetic operation, the implied arithmetic must be well-formed. + if (Form == Arithmetic) { + // gcc does not enforce these rules for GNU atomics, but we do so for sanity. + if (IsAddSub && !ValType->isIntegerType() && !ValType->isPointerType()) { + Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic_int_or_ptr) + << IsC11 << Ptr->getType() << Ptr->getSourceRange(); + return ExprError(); + } + if (!IsAddSub && !ValType->isIntegerType()) { + Diag(DRE->getLocStart(), diag::err_atomic_op_bitwise_needs_atomic_int) + << IsC11 << Ptr->getType() << Ptr->getSourceRange(); + return ExprError(); + } + } else if (IsN && !ValType->isIntegerType() && !ValType->isPointerType()) { + // For __atomic_*_n operations, the value type must be a scalar integral or + // pointer type which is 1, 2, 4, 8 or 16 bytes in length. Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic_int_or_ptr) - << Ptr->getType() << Ptr->getSourceRange(); + << IsC11 << Ptr->getType() << Ptr->getSourceRange(); return ExprError(); } - if (!ValType->isIntegerType() && - (Op == AtomicExpr::And || Op == AtomicExpr::Or || Op == AtomicExpr::Xor)){ - Diag(DRE->getLocStart(), diag::err_atomic_op_logical_needs_atomic_int) + if (!IsC11 && !AtomTy.isTriviallyCopyableType(Context)) { + // For GNU atomics, require a trivially-copyable type. This is not part of + // the GNU atomics specification, but we enforce it for sanity. + Diag(DRE->getLocStart(), diag::err_atomic_op_needs_trivial_copy) << Ptr->getType() << Ptr->getSourceRange(); return ExprError(); } + // FIXME: For any builtin other than a load, the ValType must not be + // const-qualified. + switch (ValType.getObjCLifetime()) { case Qualifiers::OCL_None: case Qualifiers::OCL_ExplicitNone: @@ -547,61 +665,107 @@ Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, AtomicExpr::AtomicOp Op) case Qualifiers::OCL_Weak: case Qualifiers::OCL_Strong: case Qualifiers::OCL_Autoreleasing: + // FIXME: Can this happen? By this point, ValType should be known + // to be trivially copyable. Diag(DRE->getLocStart(), diag::err_arc_atomic_ownership) << ValType << Ptr->getSourceRange(); return ExprError(); } QualType ResultType = ValType; - if (Op == AtomicExpr::Store) + if (Form == Copy || Form == GNUXchg || Form == Init) ResultType = Context.VoidTy; - else if (Op == AtomicExpr::CmpXchgWeak || Op == AtomicExpr::CmpXchgStrong) + else if (Form == C11CmpXchg || Form == GNUCmpXchg) ResultType = Context.BoolTy; + // The type of a parameter passed 'by value'. In the GNU atomics, such + // arguments are actually passed as pointers. + QualType ByValType = ValType; // 'CP' + if (!IsC11 && !IsN) + ByValType = Ptr->getType(); + // The first argument --- the pointer --- has a fixed type; we // deduce the types of the rest of the arguments accordingly. Walk // the remaining arguments, converting them to the deduced value type. - for (unsigned i = 1; i != NumVals+NumOrders+1; ++i) { - ExprResult Arg = TheCall->getArg(i); + for (unsigned i = 1; i != NumArgs[Form]; ++i) { QualType Ty; - if (i < NumVals+1) { - // The second argument to a cmpxchg is a pointer to the data which will - // be exchanged. The second argument to a pointer add/subtract is the - // amount to add/subtract, which must be a ptrdiff_t. The third - // argument to a cmpxchg and the second argument in all other cases - // is the type of the value. - if (i == 1 && (Op == AtomicExpr::CmpXchgWeak || - Op == AtomicExpr::CmpXchgStrong)) - Ty = Context.getPointerType(ValType.getUnqualifiedType()); - else if (!ValType->isIntegerType() && - (Op == AtomicExpr::Add || Op == AtomicExpr::Sub)) - Ty = Context.getPointerDiffType(); - else - Ty = ValType; + if (i < NumVals[Form] + 1) { + switch (i) { + case 1: + // The second argument is the non-atomic operand. For arithmetic, this + // is always passed by value, and for a compare_exchange it is always + // passed by address. For the rest, GNU uses by-address and C11 uses + // by-value. + assert(Form != Load); + if (Form == Init || (Form == Arithmetic && ValType->isIntegerType())) + Ty = ValType; + else if (Form == Copy || Form == Xchg) + Ty = ByValType; + else if (Form == Arithmetic) + Ty = Context.getPointerDiffType(); + else + Ty = Context.getPointerType(ValType.getUnqualifiedType()); + break; + case 2: + // The third argument to compare_exchange / GNU exchange is a + // (pointer to a) desired value. + Ty = ByValType; + break; + case 3: + // The fourth argument to GNU compare_exchange is a 'weak' flag. + Ty = Context.BoolTy; + break; + } } else { // The order(s) are always converted to int. Ty = Context.IntTy; } + InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, Ty, false); + ExprResult Arg = TheCall->getArg(i); Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg); if (Arg.isInvalid()) return true; TheCall->setArg(i, Arg.get()); } + // Permute the arguments into a 'consistent' order. SmallVector<Expr*, 5> SubExprs; SubExprs.push_back(Ptr); - if (Op == AtomicExpr::Load) { + switch (Form) { + case Init: + // Note, AtomicExpr::getVal1() has a special case for this atomic. + SubExprs.push_back(TheCall->getArg(1)); // Val1 + break; + case Load: SubExprs.push_back(TheCall->getArg(1)); // Order - } else if (Op != AtomicExpr::CmpXchgWeak && Op != AtomicExpr::CmpXchgStrong) { + break; + case Copy: + case Arithmetic: + case Xchg: SubExprs.push_back(TheCall->getArg(2)); // Order SubExprs.push_back(TheCall->getArg(1)); // Val1 - } else { + break; + case GNUXchg: + // Note, AtomicExpr::getVal2() has a special case for this atomic. SubExprs.push_back(TheCall->getArg(3)); // Order SubExprs.push_back(TheCall->getArg(1)); // Val1 SubExprs.push_back(TheCall->getArg(2)); // Val2 + break; + case C11CmpXchg: + SubExprs.push_back(TheCall->getArg(3)); // Order + SubExprs.push_back(TheCall->getArg(1)); // Val1 SubExprs.push_back(TheCall->getArg(4)); // OrderFail + SubExprs.push_back(TheCall->getArg(2)); // Val2 + break; + case GNUCmpXchg: + SubExprs.push_back(TheCall->getArg(4)); // Order + SubExprs.push_back(TheCall->getArg(1)); // Val1 + SubExprs.push_back(TheCall->getArg(5)); // OrderFail + SubExprs.push_back(TheCall->getArg(2)); // Val2 + SubExprs.push_back(TheCall->getArg(3)); // Weak + break; } return Owned(new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(), @@ -663,6 +827,12 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { // casts here. // FIXME: We don't allow floating point scalars as input. Expr *FirstArg = TheCall->getArg(0); + ExprResult FirstArgResult = DefaultFunctionArrayLvalueConversion(FirstArg); + if (FirstArgResult.isInvalid()) + return ExprError(); + FirstArg = FirstArgResult.take(); + TheCall->setArg(0, FirstArg); + const PointerType *pointerType = FirstArg->getType()->getAs<PointerType>(); if (!pointerType) { Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer) @@ -749,34 +919,145 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { unsigned BuiltinIndex, NumFixed = 1; switch (BuiltinID) { default: llvm_unreachable("Unknown overloaded atomic builtin!"); - case Builtin::BI__sync_fetch_and_add: BuiltinIndex = 0; break; - case Builtin::BI__sync_fetch_and_sub: BuiltinIndex = 1; break; - case Builtin::BI__sync_fetch_and_or: BuiltinIndex = 2; break; - case Builtin::BI__sync_fetch_and_and: BuiltinIndex = 3; break; - case Builtin::BI__sync_fetch_and_xor: BuiltinIndex = 4; break; - - case Builtin::BI__sync_add_and_fetch: BuiltinIndex = 5; break; - case Builtin::BI__sync_sub_and_fetch: BuiltinIndex = 6; break; - case Builtin::BI__sync_and_and_fetch: BuiltinIndex = 7; break; - case Builtin::BI__sync_or_and_fetch: BuiltinIndex = 8; break; - case Builtin::BI__sync_xor_and_fetch: BuiltinIndex = 9; break; + case Builtin::BI__sync_fetch_and_add: + case Builtin::BI__sync_fetch_and_add_1: + case Builtin::BI__sync_fetch_and_add_2: + case Builtin::BI__sync_fetch_and_add_4: + case Builtin::BI__sync_fetch_and_add_8: + case Builtin::BI__sync_fetch_and_add_16: + BuiltinIndex = 0; + break; + + case Builtin::BI__sync_fetch_and_sub: + case Builtin::BI__sync_fetch_and_sub_1: + case Builtin::BI__sync_fetch_and_sub_2: + case Builtin::BI__sync_fetch_and_sub_4: + case Builtin::BI__sync_fetch_and_sub_8: + case Builtin::BI__sync_fetch_and_sub_16: + BuiltinIndex = 1; + break; + + case Builtin::BI__sync_fetch_and_or: + case Builtin::BI__sync_fetch_and_or_1: + case Builtin::BI__sync_fetch_and_or_2: + case Builtin::BI__sync_fetch_and_or_4: + case Builtin::BI__sync_fetch_and_or_8: + case Builtin::BI__sync_fetch_and_or_16: + BuiltinIndex = 2; + break; + + case Builtin::BI__sync_fetch_and_and: + case Builtin::BI__sync_fetch_and_and_1: + case Builtin::BI__sync_fetch_and_and_2: + case Builtin::BI__sync_fetch_and_and_4: + case Builtin::BI__sync_fetch_and_and_8: + case Builtin::BI__sync_fetch_and_and_16: + BuiltinIndex = 3; + break; + + case Builtin::BI__sync_fetch_and_xor: + case Builtin::BI__sync_fetch_and_xor_1: + case Builtin::BI__sync_fetch_and_xor_2: + case Builtin::BI__sync_fetch_and_xor_4: + case Builtin::BI__sync_fetch_and_xor_8: + case Builtin::BI__sync_fetch_and_xor_16: + BuiltinIndex = 4; + break; + + case Builtin::BI__sync_add_and_fetch: + case Builtin::BI__sync_add_and_fetch_1: + case Builtin::BI__sync_add_and_fetch_2: + case Builtin::BI__sync_add_and_fetch_4: + case Builtin::BI__sync_add_and_fetch_8: + case Builtin::BI__sync_add_and_fetch_16: + BuiltinIndex = 5; + break; + + case Builtin::BI__sync_sub_and_fetch: + case Builtin::BI__sync_sub_and_fetch_1: + case Builtin::BI__sync_sub_and_fetch_2: + case Builtin::BI__sync_sub_and_fetch_4: + case Builtin::BI__sync_sub_and_fetch_8: + case Builtin::BI__sync_sub_and_fetch_16: + BuiltinIndex = 6; + break; + + case Builtin::BI__sync_and_and_fetch: + case Builtin::BI__sync_and_and_fetch_1: + case Builtin::BI__sync_and_and_fetch_2: + case Builtin::BI__sync_and_and_fetch_4: + case Builtin::BI__sync_and_and_fetch_8: + case Builtin::BI__sync_and_and_fetch_16: + BuiltinIndex = 7; + break; + + case Builtin::BI__sync_or_and_fetch: + case Builtin::BI__sync_or_and_fetch_1: + case Builtin::BI__sync_or_and_fetch_2: + case Builtin::BI__sync_or_and_fetch_4: + case Builtin::BI__sync_or_and_fetch_8: + case Builtin::BI__sync_or_and_fetch_16: + BuiltinIndex = 8; + break; + + case Builtin::BI__sync_xor_and_fetch: + case Builtin::BI__sync_xor_and_fetch_1: + case Builtin::BI__sync_xor_and_fetch_2: + case Builtin::BI__sync_xor_and_fetch_4: + case Builtin::BI__sync_xor_and_fetch_8: + case Builtin::BI__sync_xor_and_fetch_16: + BuiltinIndex = 9; + break; case Builtin::BI__sync_val_compare_and_swap: + case Builtin::BI__sync_val_compare_and_swap_1: + case Builtin::BI__sync_val_compare_and_swap_2: + case Builtin::BI__sync_val_compare_and_swap_4: + case Builtin::BI__sync_val_compare_and_swap_8: + case Builtin::BI__sync_val_compare_and_swap_16: BuiltinIndex = 10; NumFixed = 2; break; + case Builtin::BI__sync_bool_compare_and_swap: + case Builtin::BI__sync_bool_compare_and_swap_1: + case Builtin::BI__sync_bool_compare_and_swap_2: + case Builtin::BI__sync_bool_compare_and_swap_4: + case Builtin::BI__sync_bool_compare_and_swap_8: + case Builtin::BI__sync_bool_compare_and_swap_16: BuiltinIndex = 11; NumFixed = 2; ResultType = Context.BoolTy; break; - case Builtin::BI__sync_lock_test_and_set: BuiltinIndex = 12; break; + + case Builtin::BI__sync_lock_test_and_set: + case Builtin::BI__sync_lock_test_and_set_1: + case Builtin::BI__sync_lock_test_and_set_2: + case Builtin::BI__sync_lock_test_and_set_4: + case Builtin::BI__sync_lock_test_and_set_8: + case Builtin::BI__sync_lock_test_and_set_16: + BuiltinIndex = 12; + break; + case Builtin::BI__sync_lock_release: + case Builtin::BI__sync_lock_release_1: + case Builtin::BI__sync_lock_release_2: + case Builtin::BI__sync_lock_release_4: + case Builtin::BI__sync_lock_release_8: + case Builtin::BI__sync_lock_release_16: BuiltinIndex = 13; NumFixed = 0; ResultType = Context.VoidTy; break; - case Builtin::BI__sync_swap: BuiltinIndex = 14; break; + + case Builtin::BI__sync_swap: + case Builtin::BI__sync_swap_1: + case Builtin::BI__sync_swap_2: + case Builtin::BI__sync_swap_4: + case Builtin::BI__sync_swap_8: + case Builtin::BI__sync_swap_16: + BuiltinIndex = 14; + break; } // Now that we know how many fixed arguments we expect, first check that we @@ -827,7 +1108,9 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { DeclRefExpr* NewDRE = DeclRefExpr::Create( Context, DRE->getQualifierLoc(), + SourceLocation(), NewBuiltinDecl, + /*enclosing*/ false, DRE->getLocation(), NewBuiltinDecl->getType(), DRE->getValueKind()); @@ -1020,7 +1303,6 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { "promotion from float to double is the only expected cast here"); Cast->setSubExpr(0); TheCall->setArg(NumArgs-1, CastArg); - OrigArg = CastArg; } } @@ -1204,33 +1486,35 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) { } // Handle i > 1 ? "x" : "y", recursively. -bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, - bool HasVAListArg, +bool Sema::SemaCheckStringLiteral(const Expr *E, Expr **Args, + unsigned NumArgs, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, - bool isPrintf) { + FormatStringType Type, bool inFunctionCall) { tryAgain: if (E->isTypeDependent() || E->isValueDependent()) return false; - E = E->IgnoreParens(); + E = E->IgnoreParenCasts(); - switch (E->getStmtClass()) { - case Stmt::BinaryConditionalOperatorClass: - case Stmt::ConditionalOperatorClass: { - const AbstractConditionalOperator *C = cast<AbstractConditionalOperator>(E); - return SemaCheckStringLiteral(C->getTrueExpr(), TheCall, HasVAListArg, - format_idx, firstDataArg, isPrintf) - && SemaCheckStringLiteral(C->getFalseExpr(), TheCall, HasVAListArg, - format_idx, firstDataArg, isPrintf); - } - - case Stmt::IntegerLiteralClass: + if (E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) // Technically -Wformat-nonliteral does not warn about this case. // The behavior of printf and friends in this case is implementation // dependent. Ideally if the format string cannot be null then // it should have a 'nonnull' attribute in the function prototype. return true; + switch (E->getStmtClass()) { + case Stmt::BinaryConditionalOperatorClass: + case Stmt::ConditionalOperatorClass: { + const AbstractConditionalOperator *C = cast<AbstractConditionalOperator>(E); + return SemaCheckStringLiteral(C->getTrueExpr(), Args, NumArgs, HasVAListArg, + format_idx, firstDataArg, Type, + inFunctionCall) + && SemaCheckStringLiteral(C->getFalseExpr(), Args, NumArgs, HasVAListArg, + format_idx, firstDataArg, Type, + inFunctionCall); + } + case Stmt::ImplicitCastExprClass: { E = cast<ImplicitCastExpr>(E)->getSubExpr(); goto tryAgain; @@ -1263,13 +1547,17 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, } else if (const PointerType *PT = T->getAs<PointerType>()) { isConstant = T.isConstant(Context) && PT->getPointeeType().isConstant(Context); + } else if (T->isObjCObjectPointerType()) { + // In ObjC, there is usually no "const ObjectPointer" type, + // so don't check if the pointee type is constant. + isConstant = T.isConstant(Context); } if (isConstant) { if (const Expr *Init = VD->getAnyInitializer()) - return SemaCheckStringLiteral(Init, TheCall, + return SemaCheckStringLiteral(Init, Args, NumArgs, HasVAListArg, format_idx, firstDataArg, - isPrintf); + Type, /*inFunctionCall*/false); } // For vprintf* functions (i.e., HasVAListArg==true), we add a @@ -1286,32 +1574,46 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, // vprintf(fmt, ap); // Do NOT emit a warning about "fmt". // ... // - // - // FIXME: We don't have full attribute support yet, so just check to see - // if the argument is a DeclRefExpr that references a parameter. We'll - // add proper support for checking the attribute later. - if (HasVAListArg) - if (isa<ParmVarDecl>(VD)) - return true; + if (HasVAListArg) { + 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; + // adjust for implicit parameter + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND)) + if (MD->isInstance()) + ++PVIndex; + // We also check if the formats are compatible. + // We can't pass a 'scanf' string to a 'printf' function. + if (PVIndex == PVFormat->getFormatIdx() && + Type == GetFormatStringType(PVFormat)) + return true; + } + } + } + } } return false; } - case Stmt::CallExprClass: { + case Stmt::CallExprClass: + case Stmt::CXXMemberCallExprClass: { const CallExpr *CE = cast<CallExpr>(E); - if (const ImplicitCastExpr *ICE - = dyn_cast<ImplicitCastExpr>(CE->getCallee())) { - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr())) { - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) { - if (const FormatArgAttr *FA = FD->getAttr<FormatArgAttr>()) { - unsigned ArgIndex = FA->getFormatIdx(); - const Expr *Arg = CE->getArg(ArgIndex - 1); - - return SemaCheckStringLiteral(Arg, TheCall, HasVAListArg, - format_idx, firstDataArg, isPrintf); - } - } + if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) { + if (const FormatArgAttr *FA = ND->getAttr<FormatArgAttr>()) { + unsigned ArgIndex = FA->getFormatIdx(); + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND)) + if (MD->isInstance()) + --ArgIndex; + const Expr *Arg = CE->getArg(ArgIndex - 1); + + return SemaCheckStringLiteral(Arg, Args, NumArgs, HasVAListArg, + format_idx, firstDataArg, Type, + inFunctionCall); } } @@ -1327,8 +1629,8 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, StrE = cast<StringLiteral>(E); if (StrE) { - CheckFormatString(StrE, E, TheCall, HasVAListArg, format_idx, - firstDataArg, isPrintf); + CheckFormatString(StrE, E, Args, NumArgs, HasVAListArg, format_idx, + firstDataArg, Type, inFunctionCall); return true; } @@ -1354,39 +1656,58 @@ Sema::CheckNonNullArguments(const NonNullAttr *NonNull, } } +Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) { + return llvm::StringSwitch<FormatStringType>(Format->getType()) + .Case("scanf", FST_Scanf) + .Cases("printf", "printf0", FST_Printf) + .Cases("NSString", "CFString", FST_NSString) + .Case("strftime", FST_Strftime) + .Case("strfmon", FST_Strfmon) + .Cases("kprintf", "cmn_err", "vcmn_err", "zcmn_err", FST_Kprintf) + .Default(FST_Unknown); +} + /// CheckPrintfScanfArguments - Check calls to printf and scanf (and similar /// functions) for correct use of format strings. -void -Sema::CheckPrintfScanfArguments(const CallExpr *TheCall, bool HasVAListArg, - unsigned format_idx, unsigned firstDataArg, - bool isPrintf) { - - const Expr *Fn = TheCall->getCallee(); - +void Sema::CheckFormatArguments(const FormatAttr *Format, CallExpr *TheCall) { + bool IsCXXMember = false; // The way the format attribute works in GCC, the implicit this argument // of member functions is counted. However, it doesn't appear in our own // lists, so decrement format_idx in that case. - if (isa<CXXMemberCallExpr>(TheCall)) { - const CXXMethodDecl *method_decl = - dyn_cast<CXXMethodDecl>(TheCall->getCalleeDecl()); - if (method_decl && method_decl->isInstance()) { - // Catch a format attribute mistakenly referring to the object argument. - if (format_idx == 0) - return; - --format_idx; - if(firstDataArg != 0) - --firstDataArg; - } + IsCXXMember = isa<CXXMemberCallExpr>(TheCall); + CheckFormatArguments(Format, TheCall->getArgs(), TheCall->getNumArgs(), + IsCXXMember, TheCall->getRParenLoc(), + TheCall->getCallee()->getSourceRange()); +} + +void Sema::CheckFormatArguments(const FormatAttr *Format, Expr **Args, + unsigned NumArgs, bool IsCXXMember, + SourceLocation Loc, SourceRange Range) { + bool HasVAListArg = Format->getFirstArg() == 0; + unsigned format_idx = Format->getFormatIdx() - 1; + unsigned firstDataArg = HasVAListArg ? 0 : Format->getFirstArg() - 1; + if (IsCXXMember) { + if (format_idx == 0) + return; + --format_idx; + if(firstDataArg != 0) + --firstDataArg; } + CheckFormatArguments(Args, NumArgs, HasVAListArg, format_idx, + firstDataArg, GetFormatStringType(Format), Loc, Range); +} +void Sema::CheckFormatArguments(Expr **Args, unsigned NumArgs, + bool HasVAListArg, unsigned format_idx, + unsigned firstDataArg, FormatStringType Type, + SourceLocation Loc, SourceRange Range) { // CHECK: printf/scanf-like function is called with no format string. - if (format_idx >= TheCall->getNumArgs()) { - Diag(TheCall->getRParenLoc(), diag::warn_missing_format_string) - << Fn->getSourceRange(); + if (format_idx >= NumArgs) { + Diag(Loc, diag::warn_missing_format_string) << Range; return; } - const Expr *OrigFormatExpr = TheCall->getArg(format_idx)->IgnoreParenCasts(); + const Expr *OrigFormatExpr = Args[format_idx]->IgnoreParenCasts(); // CHECK: format string is not a string literal. // @@ -1400,18 +1721,30 @@ Sema::CheckPrintfScanfArguments(const CallExpr *TheCall, bool HasVAListArg, // C string (e.g. "%d") // ObjC string uses the same format specifiers as C string, so we can use // the same format string checking logic for both ObjC and C strings. - if (SemaCheckStringLiteral(OrigFormatExpr, TheCall, HasVAListArg, format_idx, - firstDataArg, isPrintf)) + if (SemaCheckStringLiteral(OrigFormatExpr, Args, NumArgs, HasVAListArg, + format_idx, firstDataArg, Type)) return; // Literal format string found, check done! + // Strftime is particular as it always uses a single 'time' argument, + // so it is safe to pass a non-literal string. + if (Type == FST_Strftime) + return; + + // Do not emit diag when the string param is a macro expansion and the + // format is either NSString or CFString. This is a hack to prevent + // diag when using the NSLocalizedString and CFCopyLocalizedString macros + // which are usually used in place of NS and CF string literals. + if (Type == FST_NSString && Args[format_idx]->getLocStart().isMacroID()) + return; + // If there are no arguments specified, warn with -Wformat-security, otherwise // warn only with -Wformat-nonliteral. - if (TheCall->getNumArgs() == format_idx+1) - Diag(TheCall->getArg(format_idx)->getLocStart(), + if (NumArgs == format_idx+1) + Diag(Args[format_idx]->getLocStart(), diag::warn_format_nonliteral_noargs) << OrigFormatExpr->getSourceRange(); else - Diag(TheCall->getArg(format_idx)->getLocStart(), + Diag(Args[format_idx]->getLocStart(), diag::warn_format_nonliteral) << OrigFormatExpr->getSourceRange(); } @@ -1427,24 +1760,28 @@ protected: const bool IsObjCLiteral; const char *Beg; // Start of format string. const bool HasVAListArg; - const CallExpr *TheCall; + const Expr * const *Args; + const unsigned NumArgs; unsigned FormatIdx; llvm::BitVector CoveredArgs; bool usesPositionalArgs; bool atFirstArg; + bool inFunctionCall; public: CheckFormatHandler(Sema &s, const StringLiteral *fexpr, const Expr *origFormatExpr, unsigned firstDataArg, unsigned numDataArgs, bool isObjCLiteral, const char *beg, bool hasVAListArg, - const CallExpr *theCall, unsigned formatIdx) + Expr **args, unsigned numArgs, + unsigned formatIdx, bool inFunctionCall) : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), FirstDataArg(firstDataArg), NumDataArgs(numDataArgs), IsObjCLiteral(isObjCLiteral), Beg(beg), HasVAListArg(hasVAListArg), - TheCall(theCall), FormatIdx(formatIdx), - usesPositionalArgs(false), atFirstArg(true) { + Args(args), NumArgs(numArgs), FormatIdx(formatIdx), + usesPositionalArgs(false), atFirstArg(true), + inFunctionCall(inFunctionCall) { CoveredArgs.resize(numDataArgs); CoveredArgs.reset(); } @@ -1453,7 +1790,22 @@ public: void HandleIncompleteSpecifier(const char *startSpecifier, unsigned specifierLen); - + + void HandleNonStandardLengthModifier( + const analyze_format_string::LengthModifier &LM, + const char *startSpecifier, unsigned specifierLen); + + void HandleNonStandardConversionSpecifier( + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen); + + void HandleNonStandardConversionSpecification( + const analyze_format_string::LengthModifier &LM, + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen); + + virtual void HandlePosition(const char *startPos, unsigned posLen); + virtual void HandleInvalidPosition(const char *startSpecifier, unsigned specifierLen, analyze_format_string::PositionContext p); @@ -1462,11 +1814,23 @@ public: void HandleNullChar(const char *nullCharacter); + template <typename Range> + static void EmitFormatDiagnostic(Sema &S, bool inFunctionCall, + const Expr *ArgumentExpr, + PartialDiagnostic PDiag, + SourceLocation StringLoc, + bool IsStringLocation, Range StringRange, + FixItHint Fixit = FixItHint()); + protected: bool HandleInvalidConversionSpecifier(unsigned argIndex, SourceLocation Loc, const char *startSpec, unsigned specifierLen, const char *csStart, unsigned csLen); + + void HandlePositionalNonpositionalArgs(SourceLocation Loc, + const char *startSpec, + unsigned specifierLen); SourceRange getFormatStringRange(); CharSourceRange getSpecifierRange(const char *startSpecifier, @@ -1479,6 +1843,14 @@ protected: const analyze_format_string::ConversionSpecifier &CS, const char *startSpecifier, unsigned specifierLen, unsigned argIndex); + + template <typename Range> + void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc, + bool IsStringLocation, Range StringRange, + FixItHint Fixit = FixItHint()); + + void CheckPositionalAndNonpositionalArgs( + const analyze_format_string::FormatSpecifier *FS); }; } @@ -1503,37 +1875,80 @@ SourceLocation CheckFormatHandler::getLocationOfByte(const char *x) { void CheckFormatHandler::HandleIncompleteSpecifier(const char *startSpecifier, unsigned specifierLen){ - SourceLocation Loc = getLocationOfByte(startSpecifier); - S.Diag(Loc, diag::warn_printf_incomplete_specifier) - << getSpecifierRange(startSpecifier, specifierLen); + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_incomplete_specifier), + getLocationOfByte(startSpecifier), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); +} + +void CheckFormatHandler::HandleNonStandardLengthModifier( + const analyze_format_string::LengthModifier &LM, + const char *startSpecifier, unsigned specifierLen) { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) << LM.toString() + << 0, + getLocationOfByte(LM.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); +} + +void CheckFormatHandler::HandleNonStandardConversionSpecifier( + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen) { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) << CS.toString() + << 1, + getLocationOfByte(CS.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); +} + +void CheckFormatHandler::HandleNonStandardConversionSpecification( + const analyze_format_string::LengthModifier &LM, + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen) { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard_conversion_spec) + << LM.toString() << CS.toString(), + getLocationOfByte(LM.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); +} + +void CheckFormatHandler::HandlePosition(const char *startPos, + unsigned posLen) { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard_positional_arg), + getLocationOfByte(startPos), + /*IsStringLocation*/true, + getSpecifierRange(startPos, posLen)); } void CheckFormatHandler::HandleInvalidPosition(const char *startPos, unsigned posLen, analyze_format_string::PositionContext p) { - SourceLocation Loc = getLocationOfByte(startPos); - S.Diag(Loc, diag::warn_format_invalid_positional_specifier) - << (unsigned) p << getSpecifierRange(startPos, posLen); + EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_positional_specifier) + << (unsigned) p, + getLocationOfByte(startPos), /*IsStringLocation*/true, + getSpecifierRange(startPos, posLen)); } void CheckFormatHandler::HandleZeroPosition(const char *startPos, unsigned posLen) { - SourceLocation Loc = getLocationOfByte(startPos); - S.Diag(Loc, diag::warn_format_zero_positional_specifier) - << getSpecifierRange(startPos, posLen); + EmitFormatDiagnostic(S.PDiag(diag::warn_format_zero_positional_specifier), + getLocationOfByte(startPos), + /*IsStringLocation*/true, + getSpecifierRange(startPos, posLen)); } void CheckFormatHandler::HandleNullChar(const char *nullCharacter) { if (!IsObjCLiteral) { // The presence of a null character is likely an error. - S.Diag(getLocationOfByte(nullCharacter), - diag::warn_printf_format_string_contains_null_char) - << getFormatStringRange(); + EmitFormatDiagnostic( + S.PDiag(diag::warn_printf_format_string_contains_null_char), + getLocationOfByte(nullCharacter), /*IsStringLocation*/true, + getFormatStringRange()); } } const Expr *CheckFormatHandler::getDataArg(unsigned i) const { - return TheCall->getArg(FirstDataArg + i); + return Args[FirstDataArg + i]; } void CheckFormatHandler::DoneProcessing() { @@ -1545,9 +1960,9 @@ void CheckFormatHandler::DoneProcessing() { signed notCoveredArg = CoveredArgs.find_first(); if (notCoveredArg >= 0) { assert((unsigned)notCoveredArg < NumDataArgs); - S.Diag(getDataArg((unsigned) notCoveredArg)->getLocStart(), - diag::warn_printf_data_arg_not_used) - << getFormatStringRange(); + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_data_arg_not_used), + getDataArg((unsigned) notCoveredArg)->getLocStart(), + /*IsStringLocation*/false, getFormatStringRange()); } } } @@ -1575,13 +1990,23 @@ CheckFormatHandler::HandleInvalidConversionSpecifier(unsigned argIndex, keepGoing = false; } - S.Diag(Loc, diag::warn_format_invalid_conversion) - << StringRef(csStart, csLen) - << getSpecifierRange(startSpec, specifierLen); + EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_conversion) + << StringRef(csStart, csLen), + Loc, /*IsStringLocation*/true, + getSpecifierRange(startSpec, specifierLen)); return keepGoing; } +void +CheckFormatHandler::HandlePositionalNonpositionalArgs(SourceLocation Loc, + const char *startSpec, + unsigned specifierLen) { + EmitFormatDiagnostic( + S.PDiag(diag::warn_format_mix_positional_nonpositional_args), + Loc, /*isStringLoc*/true, getSpecifierRange(startSpec, specifierLen)); +} + bool CheckFormatHandler::CheckNumArgs( const analyze_format_string::FormatSpecifier &FS, @@ -1589,23 +2014,74 @@ CheckFormatHandler::CheckNumArgs( const char *startSpecifier, unsigned specifierLen, unsigned argIndex) { if (argIndex >= NumDataArgs) { - if (FS.usesPositionalArg()) { - S.Diag(getLocationOfByte(CS.getStart()), - diag::warn_printf_positional_arg_exceeds_data_args) - << (argIndex+1) << NumDataArgs - << getSpecifierRange(startSpecifier, specifierLen); - } - else { - S.Diag(getLocationOfByte(CS.getStart()), - diag::warn_printf_insufficient_data_args) - << getSpecifierRange(startSpecifier, specifierLen); - } - + PartialDiagnostic PDiag = FS.usesPositionalArg() + ? (S.PDiag(diag::warn_printf_positional_arg_exceeds_data_args) + << (argIndex+1) << NumDataArgs) + : S.PDiag(diag::warn_printf_insufficient_data_args); + EmitFormatDiagnostic( + PDiag, getLocationOfByte(CS.getStart()), /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); return false; } return true; } +template<typename Range> +void CheckFormatHandler::EmitFormatDiagnostic(PartialDiagnostic PDiag, + SourceLocation Loc, + bool IsStringLocation, + Range StringRange, + FixItHint FixIt) { + EmitFormatDiagnostic(S, inFunctionCall, Args[FormatIdx], PDiag, + Loc, IsStringLocation, StringRange, FixIt); +} + +/// \brief If the format string is not within the funcion call, emit a note +/// so that the function call and string are in diagnostic messages. +/// +/// \param inFunctionCall if true, the format string is within the function +/// call and only one diagnostic message will be produced. Otherwise, an +/// extra note will be emitted pointing to location of the format string. +/// +/// \param ArgumentExpr the expression that is passed as the format string +/// argument in the function call. Used for getting locations when two +/// diagnostics are emitted. +/// +/// \param PDiag the callee should already have provided any strings for the +/// diagnostic message. This function only adds locations and fixits +/// to diagnostics. +/// +/// \param Loc primary location for diagnostic. If two diagnostics are +/// required, one will be at Loc and a new SourceLocation will be created for +/// the other one. +/// +/// \param IsStringLocation if true, Loc points to the format string should be +/// used for the note. Otherwise, Loc points to the argument list and will +/// be used with PDiag. +/// +/// \param StringRange some or all of the string to highlight. This is +/// templated so it can accept either a CharSourceRange or a SourceRange. +/// +/// \param Fixit optional fix it hint for the format string. +template<typename Range> +void CheckFormatHandler::EmitFormatDiagnostic(Sema &S, bool InFunctionCall, + const Expr *ArgumentExpr, + PartialDiagnostic PDiag, + SourceLocation Loc, + bool IsStringLocation, + Range StringRange, + FixItHint FixIt) { + if (InFunctionCall) + S.Diag(Loc, PDiag) << StringRange << FixIt; + else { + S.Diag(IsStringLocation ? ArgumentExpr->getExprLoc() : Loc, PDiag) + << ArgumentExpr->getSourceRange(); + S.Diag(IsStringLocation ? Loc : StringRange.getBegin(), + diag::note_format_string_defined) + << StringRange << FixIt; + } +} + //===--- CHECK: Printf format string checking ------------------------------===// namespace { @@ -1615,10 +2091,11 @@ public: const Expr *origFormatExpr, unsigned firstDataArg, unsigned numDataArgs, bool isObjCLiteral, const char *beg, bool hasVAListArg, - const CallExpr *theCall, unsigned formatIdx) + Expr **Args, unsigned NumArgs, + unsigned formatIdx, bool inFunctionCall) : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, numDataArgs, isObjCLiteral, beg, hasVAListArg, - theCall, formatIdx) {} + Args, NumArgs, formatIdx, inFunctionCall) {} bool HandleInvalidPrintfConversionSpecifier( @@ -1668,9 +2145,11 @@ bool CheckPrintfHandler::HandleAmount( if (!HasVAListArg) { unsigned argIndex = Amt.getArgIndex(); if (argIndex >= NumDataArgs) { - S.Diag(getLocationOfByte(Amt.getStart()), - diag::warn_printf_asterisk_missing_arg) - << k << getSpecifierRange(startSpecifier, specifierLen); + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_asterisk_missing_arg) + << k, + getLocationOfByte(Amt.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); // Don't do any more checking. We will just emit // spurious errors. return false; @@ -1688,12 +2167,12 @@ bool CheckPrintfHandler::HandleAmount( assert(ATR.isValid()); if (!ATR.matchesType(S.Context, T)) { - S.Diag(getLocationOfByte(Amt.getStart()), - diag::warn_printf_asterisk_wrong_type) - << k - << ATR.getRepresentativeType(S.Context) << T - << getSpecifierRange(startSpecifier, specifierLen) - << Arg->getSourceRange(); + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_asterisk_wrong_type) + << k << ATR.getRepresentativeTypeName(S.Context) + << T << Arg->getSourceRange(), + getLocationOfByte(Amt.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); // Don't do any more checking. We will just emit // spurious errors. return false; @@ -1711,25 +2190,19 @@ void CheckPrintfHandler::HandleInvalidAmount( unsigned specifierLen) { const analyze_printf::PrintfConversionSpecifier &CS = FS.getConversionSpecifier(); - switch (Amt.getHowSpecified()) { - case analyze_printf::OptionalAmount::Constant: - S.Diag(getLocationOfByte(Amt.getStart()), - diag::warn_printf_nonsensical_optional_amount) - << type - << CS.toString() - << getSpecifierRange(startSpecifier, specifierLen) - << FixItHint::CreateRemoval(getSpecifierRange(Amt.getStart(), - Amt.getConstantLength())); - break; - default: - S.Diag(getLocationOfByte(Amt.getStart()), - diag::warn_printf_nonsensical_optional_amount) - << type - << CS.toString() - << getSpecifierRange(startSpecifier, specifierLen); - break; - } + FixItHint fixit = + Amt.getHowSpecified() == analyze_printf::OptionalAmount::Constant + ? FixItHint::CreateRemoval(getSpecifierRange(Amt.getStart(), + Amt.getConstantLength())) + : FixItHint(); + + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_nonsensical_optional_amount) + << type << CS.toString(), + getLocationOfByte(Amt.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen), + fixit); } void CheckPrintfHandler::HandleFlag(const analyze_printf::PrintfSpecifier &FS, @@ -1739,11 +2212,13 @@ void CheckPrintfHandler::HandleFlag(const analyze_printf::PrintfSpecifier &FS, // Warn about pointless flag with a fixit removal. const analyze_printf::PrintfConversionSpecifier &CS = FS.getConversionSpecifier(); - S.Diag(getLocationOfByte(flag.getPosition()), - diag::warn_printf_nonsensical_flag) - << flag.toString() << CS.toString() - << getSpecifierRange(startSpecifier, specifierLen) - << FixItHint::CreateRemoval(getSpecifierRange(flag.getPosition(), 1)); + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_nonsensical_flag) + << flag.toString() << CS.toString(), + getLocationOfByte(flag.getPosition()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen), + FixItHint::CreateRemoval( + getSpecifierRange(flag.getPosition(), 1))); } void CheckPrintfHandler::HandleIgnoredFlag( @@ -1753,12 +2228,13 @@ void CheckPrintfHandler::HandleIgnoredFlag( const char *startSpecifier, unsigned specifierLen) { // Warn about ignored flag with a fixit removal. - S.Diag(getLocationOfByte(ignoredFlag.getPosition()), - diag::warn_printf_ignored_flag) - << ignoredFlag.toString() << flag.toString() - << getSpecifierRange(startSpecifier, specifierLen) - << FixItHint::CreateRemoval(getSpecifierRange( - ignoredFlag.getPosition(), 1)); + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_ignored_flag) + << ignoredFlag.toString() << flag.toString(), + getLocationOfByte(ignoredFlag.getPosition()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen), + FixItHint::CreateRemoval( + getSpecifierRange(ignoredFlag.getPosition(), 1))); } bool @@ -1777,10 +2253,8 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier usesPositionalArgs = FS.usesPositionalArg(); } else if (usesPositionalArgs != FS.usesPositionalArg()) { - // Cannot mix-and-match positional and non-positional arguments. - S.Diag(getLocationOfByte(CS.getStart()), - diag::warn_format_mix_positional_nonpositional_args) - << getSpecifierRange(startSpecifier, specifierLen); + HandlePositionalNonpositionalArgs(getLocationOfByte(CS.getStart()), + startSpecifier, specifierLen); return false; } } @@ -1889,18 +2363,29 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier // Check the length modifier is valid with the given conversion specifier. const LengthModifier &LM = FS.getLengthModifier(); if (!FS.hasValidLengthModifier()) - S.Diag(getLocationOfByte(LM.getStart()), - diag::warn_format_nonsensical_length) - << LM.toString() << CS.toString() - << getSpecifierRange(startSpecifier, specifierLen) - << FixItHint::CreateRemoval(getSpecifierRange(LM.getStart(), - LM.getLength())); + EmitFormatDiagnostic(S.PDiag(diag::warn_format_nonsensical_length) + << LM.toString() << CS.toString(), + getLocationOfByte(LM.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen), + FixItHint::CreateRemoval( + getSpecifierRange(LM.getStart(), + LM.getLength()))); + if (!FS.hasStandardLengthModifier()) + HandleNonStandardLengthModifier(LM, startSpecifier, specifierLen); + if (!FS.hasStandardConversionSpecifier(S.getLangOpts())) + HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen); + if (!FS.hasStandardLengthConversionCombination()) + HandleNonStandardConversionSpecification(LM, CS, startSpecifier, + specifierLen); // Are we using '%n'? if (CS.getKind() == ConversionSpecifier::nArg) { // Issue a warning about this being a possible security issue. - S.Diag(getLocationOfByte(CS.getStart()), diag::warn_printf_write_back) - << getSpecifierRange(startSpecifier, specifierLen); + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_write_back), + getLocationOfByte(CS.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); // Continue checking the other format specifiers. return true; } @@ -1915,7 +2400,8 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier // Now type check the data expression that matches the // format specifier. const Expr *Ex = getDataArg(argIndex); - const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context); + const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context, + IsObjCLiteral); if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) { // Check if we didn't match because of an implicit cast from a 'char' // or 'short' to an 'int'. This is done because printf is a varargs @@ -1930,32 +2416,35 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier // We may be able to offer a FixItHint if it is a supported type. PrintfSpecifier fixedFS = FS; - bool success = fixedFS.fixType(Ex->getType()); + bool success = fixedFS.fixType(Ex->getType(), S.getLangOpts(), + S.Context, IsObjCLiteral); if (success) { // Get the fix string from the fixed format specifier - llvm::SmallString<128> buf; + SmallString<128> buf; llvm::raw_svector_ostream os(buf); fixedFS.toString(os); - // FIXME: getRepresentativeType() perhaps should return a string - // instead of a QualType to better handle when the representative - // type is 'wint_t' (which is defined in the system headers). - S.Diag(getLocationOfByte(CS.getStart()), - diag::warn_printf_conversion_argument_type_mismatch) - << ATR.getRepresentativeType(S.Context) << Ex->getType() - << getSpecifierRange(startSpecifier, specifierLen) - << Ex->getSourceRange() - << FixItHint::CreateReplacement( - getSpecifierRange(startSpecifier, specifierLen), - os.str()); + EmitFormatDiagnostic( + S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) + << ATR.getRepresentativeTypeName(S.Context) << Ex->getType() + << Ex->getSourceRange(), + getLocationOfByte(CS.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen), + FixItHint::CreateReplacement( + getSpecifierRange(startSpecifier, specifierLen), + os.str())); } else { - S.Diag(getLocationOfByte(CS.getStart()), - diag::warn_printf_conversion_argument_type_mismatch) - << ATR.getRepresentativeType(S.Context) << Ex->getType() - << getSpecifierRange(startSpecifier, specifierLen) - << Ex->getSourceRange(); + EmitFormatDiagnostic( + S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) + << ATR.getRepresentativeTypeName(S.Context) << Ex->getType() + << getSpecifierRange(startSpecifier, specifierLen) + << Ex->getSourceRange(), + getLocationOfByte(CS.getStart()), + true, + getSpecifierRange(startSpecifier, specifierLen)); } } @@ -1971,10 +2460,11 @@ public: const Expr *origFormatExpr, unsigned firstDataArg, unsigned numDataArgs, bool isObjCLiteral, const char *beg, bool hasVAListArg, - const CallExpr *theCall, unsigned formatIdx) + Expr **Args, unsigned NumArgs, + unsigned formatIdx, bool inFunctionCall) : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, numDataArgs, isObjCLiteral, beg, hasVAListArg, - theCall, formatIdx) {} + Args, NumArgs, formatIdx, inFunctionCall) {} bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS, const char *startSpecifier, @@ -1991,8 +2481,9 @@ public: void CheckScanfHandler::HandleIncompleteScanList(const char *start, const char *end) { - S.Diag(getLocationOfByte(end), diag::warn_scanf_scanlist_incomplete) - << getSpecifierRange(start, end - start); + EmitFormatDiagnostic(S.PDiag(diag::warn_scanf_scanlist_incomplete), + getLocationOfByte(end), /*IsStringLocation*/true, + getSpecifierRange(start, end - start)); } bool CheckScanfHandler::HandleInvalidScanfConversionSpecifier( @@ -2027,10 +2518,8 @@ bool CheckScanfHandler::HandleScanfSpecifier( usesPositionalArgs = FS.usesPositionalArg(); } else if (usesPositionalArgs != FS.usesPositionalArg()) { - // Cannot mix-and-match positional and non-positional arguments. - S.Diag(getLocationOfByte(CS.getStart()), - diag::warn_format_mix_positional_nonpositional_args) - << getSpecifierRange(startSpecifier, specifierLen); + HandlePositionalNonpositionalArgs(getLocationOfByte(CS.getStart()), + startSpecifier, specifierLen); return false; } } @@ -2041,9 +2530,10 @@ bool CheckScanfHandler::HandleScanfSpecifier( if (Amt.getConstantAmount() == 0) { const CharSourceRange &R = getSpecifierRange(Amt.getStart(), Amt.getConstantLength()); - S.Diag(getLocationOfByte(Amt.getStart()), - diag::warn_scanf_nonzero_width) - << R << FixItHint::CreateRemoval(R); + EmitFormatDiagnostic(S.PDiag(diag::warn_scanf_nonzero_width), + getLocationOfByte(Amt.getStart()), + /*IsStringLocation*/true, R, + FixItHint::CreateRemoval(R)); } } @@ -2065,13 +2555,22 @@ bool CheckScanfHandler::HandleScanfSpecifier( // Check the length modifier is valid with the given conversion specifier. const LengthModifier &LM = FS.getLengthModifier(); if (!FS.hasValidLengthModifier()) { - S.Diag(getLocationOfByte(LM.getStart()), - diag::warn_format_nonsensical_length) - << LM.toString() << CS.toString() - << getSpecifierRange(startSpecifier, specifierLen) - << FixItHint::CreateRemoval(getSpecifierRange(LM.getStart(), - LM.getLength())); - } + const CharSourceRange &R = getSpecifierRange(LM.getStart(), LM.getLength()); + EmitFormatDiagnostic(S.PDiag(diag::warn_format_nonsensical_length) + << LM.toString() << CS.toString() + << getSpecifierRange(startSpecifier, specifierLen), + getLocationOfByte(LM.getStart()), + /*IsStringLocation*/true, R, + FixItHint::CreateRemoval(R)); + } + + if (!FS.hasStandardLengthModifier()) + HandleNonStandardLengthModifier(LM, startSpecifier, specifierLen); + if (!FS.hasStandardConversionSpecifier(S.getLangOpts())) + HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen); + if (!FS.hasStandardLengthConversionCombination()) + HandleNonStandardConversionSpecification(LM, CS, startSpecifier, + specifierLen); // The remaining checks depend on the data arguments. if (HasVAListArg) @@ -2080,22 +2579,57 @@ bool CheckScanfHandler::HandleScanfSpecifier( if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex)) return false; - // FIXME: Check that the argument type matches the format specifier. - + // Check that the argument type matches the format specifier. + const Expr *Ex = getDataArg(argIndex); + const analyze_scanf::ScanfArgTypeResult &ATR = FS.getArgType(S.Context); + if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) { + ScanfSpecifier fixedFS = FS; + bool success = fixedFS.fixType(Ex->getType(), S.getLangOpts(), + S.Context); + + if (success) { + // Get the fix string from the fixed format specifier. + SmallString<128> buf; + llvm::raw_svector_ostream os(buf); + fixedFS.toString(os); + + EmitFormatDiagnostic( + S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) + << ATR.getRepresentativeTypeName(S.Context) << Ex->getType() + << Ex->getSourceRange(), + getLocationOfByte(CS.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen), + FixItHint::CreateReplacement( + getSpecifierRange(startSpecifier, specifierLen), + os.str())); + } else { + EmitFormatDiagnostic( + S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) + << ATR.getRepresentativeTypeName(S.Context) << Ex->getType() + << Ex->getSourceRange(), + getLocationOfByte(CS.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); + } + } + return true; } void Sema::CheckFormatString(const StringLiteral *FExpr, const Expr *OrigFormatExpr, - const CallExpr *TheCall, bool HasVAListArg, - unsigned format_idx, unsigned firstDataArg, - bool isPrintf) { + Expr **Args, unsigned NumArgs, + bool HasVAListArg, unsigned format_idx, + unsigned firstDataArg, FormatStringType Type, + bool inFunctionCall) { // CHECK: is the format string a wide literal? if (!FExpr->isAscii()) { - Diag(FExpr->getLocStart(), - diag::warn_format_string_is_wide_literal) - << OrigFormatExpr->getSourceRange(); + CheckFormatHandler::EmitFormatDiagnostic( + *this, inFunctionCall, Args[format_idx], + PDiag(diag::warn_format_string_is_wide_literal), FExpr->getLocStart(), + /*IsStringLocation*/true, OrigFormatExpr->getSourceRange()); return; } @@ -2103,33 +2637,36 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, StringRef StrRef = FExpr->getString(); const char *Str = StrRef.data(); unsigned StrLen = StrRef.size(); - const unsigned numDataArgs = TheCall->getNumArgs() - firstDataArg; + const unsigned numDataArgs = NumArgs - firstDataArg; // CHECK: empty format string? if (StrLen == 0 && numDataArgs > 0) { - Diag(FExpr->getLocStart(), diag::warn_empty_format_string) - << OrigFormatExpr->getSourceRange(); + CheckFormatHandler::EmitFormatDiagnostic( + *this, inFunctionCall, Args[format_idx], + PDiag(diag::warn_empty_format_string), FExpr->getLocStart(), + /*IsStringLocation*/true, OrigFormatExpr->getSourceRange()); return; } - if (isPrintf) { + if (Type == FST_Printf || Type == FST_NSString) { CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs, isa<ObjCStringLiteral>(OrigFormatExpr), - Str, HasVAListArg, TheCall, format_idx); + Str, HasVAListArg, Args, NumArgs, format_idx, + inFunctionCall); - bool FormatExtensions = getLangOptions().FormatExtensions; if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen, - FormatExtensions)) + getLangOpts())) H.DoneProcessing(); - } - else { + } else if (Type == FST_Scanf) { CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs, isa<ObjCStringLiteral>(OrigFormatExpr), - Str, HasVAListArg, TheCall, format_idx); + Str, HasVAListArg, Args, NumArgs, format_idx, + inFunctionCall); - if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen)) + if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen, + getLangOpts())) H.DoneProcessing(); - } + } // TODO: handle other formats } //===--- CHECK: Standard memory functions ---------------------------------===// @@ -2174,16 +2711,19 @@ static QualType getSizeOfArgType(const Expr* E) { /// /// \param Call The call expression to diagnose. void Sema::CheckMemaccessArguments(const CallExpr *Call, - CheckedMemoryFunction CMF, + unsigned BId, IdentifierInfo *FnName) { + assert(BId != 0); + // It is possible to have a non-standard definition of memset. Validate // we have enough arguments, and if not, abort further checking. - unsigned ExpectedNumArgs = (CMF == CMF_Strndup ? 2 : 3); + unsigned ExpectedNumArgs = (BId == Builtin::BIstrndup ? 2 : 3); if (Call->getNumArgs() < ExpectedNumArgs) return; - unsigned LastArg = (CMF == CMF_Memset || CMF == CMF_Strndup ? 1 : 2); - unsigned LenArg = (CMF == CMF_Strndup ? 1 : 2); + unsigned LastArg = (BId == Builtin::BImemset || + BId == Builtin::BIstrndup ? 1 : 2); + unsigned LenArg = (BId == Builtin::BIstrndup ? 1 : 2); const Expr *LenExpr = Call->getArg(LenArg)->IgnoreParenImpCasts(); // We have special checking when the length is a sizeof expression. @@ -2227,7 +2767,8 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, if (Context.getTypeSize(PointeeTy) == Context.getCharWidth()) ActionIdx = 2; // If the pointee's size is sizeof(char), // suggest an explicit length. - unsigned DestSrcSelect = (CMF == CMF_Strndup ? 1 : ArgIdx); + unsigned DestSrcSelect = + (BId == Builtin::BIstrndup ? 1 : ArgIdx); DiagRuntimeBehavior(SizeOfArg->getExprLoc(), Dest, PDiag(diag::warn_sizeof_pointer_expr_memaccess) << FnName << DestSrcSelect << ActionIdx @@ -2253,16 +2794,29 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, } // Always complain about dynamic classes. - if (isDynamicClassType(PointeeTy)) + if (isDynamicClassType(PointeeTy)) { + + unsigned OperationType = 0; + // "overwritten" if we're warning about the destination for any call + // but memcmp; otherwise a verb appropriate to the call. + if (ArgIdx != 0 || BId == Builtin::BImemcmp) { + if (BId == Builtin::BImemcpy) + OperationType = 1; + else if(BId == Builtin::BImemmove) + OperationType = 2; + else if (BId == Builtin::BImemcmp) + OperationType = 3; + } + DiagRuntimeBehavior( Dest->getExprLoc(), Dest, PDiag(diag::warn_dyn_class_memaccess) - << (CMF == CMF_Memcmp ? ArgIdx + 2 : ArgIdx) << FnName << PointeeTy - // "overwritten" if we're warning about the destination for any call - // but memcmp; otherwise a verb appropriate to the call. - << (ArgIdx == 0 && CMF != CMF_Memcmp ? 0 : (unsigned)CMF) + << (BId == Builtin::BImemcmp ? ArgIdx + 2 : ArgIdx) + << FnName << PointeeTy + << OperationType << Call->getCallee()->getSourceRange()); - else if (PointeeTy.hasNonTrivialObjCLifetime() && CMF != CMF_Memset) + } else if (PointeeTy.hasNonTrivialObjCLifetime() && + BId != Builtin::BImemset) DiagRuntimeBehavior( Dest->getExprLoc(), Dest, PDiag(diag::warn_arc_object_memaccess) @@ -2324,7 +2878,7 @@ 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(Context) == Builtin::BIstrlen + if (SizeCall->isBuiltinCall() == Builtin::BIstrlen && SizeCall->getNumArgs() == 1) CompareWithSrc = ignoreLiteralAdditions(SizeCall->getArg(0), Context); } @@ -2366,7 +2920,7 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call, return; } - llvm::SmallString<128> sizeString; + SmallString<128> sizeString; llvm::raw_svector_ostream OS(sizeString); OS << "sizeof("; DstArg->printPretty(OS, Context, 0, getPrintingPolicy()); @@ -2377,6 +2931,108 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call, OS.str()); } +/// Check if two expressions refer to the same declaration. +static bool referToTheSameDecl(const Expr *E1, const Expr *E2) { + if (const DeclRefExpr *D1 = dyn_cast_or_null<DeclRefExpr>(E1)) + if (const DeclRefExpr *D2 = dyn_cast_or_null<DeclRefExpr>(E2)) + return D1->getDecl() == D2->getDecl(); + return false; +} + +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 CE->getArg(0)->IgnoreParenCasts(); + } + return 0; +} + +// Warn on anti-patterns as the 'size' argument to strncat. +// The correct size argument should look like following: +// strncat(dst, src, sizeof(dst) - strlen(dest) - 1); +void Sema::CheckStrncatArguments(const CallExpr *CE, + IdentifierInfo *FnName) { + // Don't crash if the user has the wrong number of arguments. + if (CE->getNumArgs() < 3) + return; + const Expr *DstArg = CE->getArg(0)->IgnoreParenCasts(); + const Expr *SrcArg = CE->getArg(1)->IgnoreParenCasts(); + const Expr *LenArg = CE->getArg(2)->IgnoreParenCasts(); + + // Identify common expressions, which are wrongly used as the size argument + // to strncat and may lead to buffer overflows. + unsigned PatternType = 0; + if (const Expr *SizeOfArg = getSizeOfExprArg(LenArg)) { + // - sizeof(dst) + if (referToTheSameDecl(SizeOfArg, DstArg)) + PatternType = 1; + // - sizeof(src) + else if (referToTheSameDecl(SizeOfArg, SrcArg)) + PatternType = 2; + } else if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(LenArg)) { + if (BE->getOpcode() == BO_Sub) { + const Expr *L = BE->getLHS()->IgnoreParenCasts(); + const Expr *R = BE->getRHS()->IgnoreParenCasts(); + // - sizeof(dst) - strlen(dst) + if (referToTheSameDecl(DstArg, getSizeOfExprArg(L)) && + referToTheSameDecl(DstArg, getStrlenExprArg(R))) + PatternType = 1; + // - sizeof(src) - (anything) + else if (referToTheSameDecl(SrcArg, getSizeOfExprArg(L))) + PatternType = 2; + } + } + + if (PatternType == 0) + return; + + // Generate the diagnostic. + SourceLocation SL = LenArg->getLocStart(); + SourceRange SR = LenArg->getSourceRange(); + SourceManager &SM = PP.getSourceManager(); + + // If the function is defined as a builtin macro, do not show macro expansion. + if (SM.isMacroArgExpansion(SL)) { + SL = SM.getSpellingLoc(SL); + SR = SourceRange(SM.getSpellingLoc(SR.getBegin()), + SM.getSpellingLoc(SR.getEnd())); + } + + if (PatternType == 1) + Diag(SL, diag::warn_strncat_large_size) << SR; + else + Diag(SL, diag::warn_strncat_src_size) << SR; + + // Output a FIXIT hint if the destination is an array (rather than a + // pointer to an array). This could be enhanced to handle some + // pointers if we know the actual size, like if DstArg is 'array+2' + // we could say 'sizeof(array)-2'. + QualType DstArgTy = DstArg->getType(); + + // Only handle constant-sized or VLAs, but not flexible members. + if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(DstArgTy)) { + // Only issue the FIXIT for arrays of size > 1. + if (CAT->getSize().getSExtValue() <= 1) + return; + } else if (!DstArgTy->isVariableArrayType()) { + return; + } + + SmallString<128> sizeString; + llvm::raw_svector_ostream OS(sizeString); + OS << "sizeof("; + DstArg->printPretty(OS, Context, 0, getPrintingPolicy()); + OS << ") - "; + OS << "strlen("; + DstArg->printPretty(OS, Context, 0, getPrintingPolicy()); + OS << ") - 1"; + + Diag(SL, diag::note_strncat_wrong_size) + << FixItHint::CreateReplacement(SR, OS.str()); +} + //===--- CHECK: Return Address of Stack Variable --------------------------===// static Expr *EvalVal(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars); @@ -2394,7 +3050,7 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, // Perform checking for returned stack addresses, local blocks, // label addresses or references to temporaries. if (lhsType->isPointerType() || - (!getLangOptions().ObjCAutoRefCount && lhsType->isBlockPointerType())) { + (!getLangOpts().ObjCAutoRefCount && lhsType->isBlockPointerType())) { stackE = EvalAddr(RetValExp, refVars); } else if (lhsType->isReferenceType()) { stackE = EvalVal(RetValExp, refVars); @@ -2561,42 +3217,39 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars) { case Stmt::AddrLabelExprClass: return E; // address of label. + case Stmt::ExprWithCleanupsClass: + return EvalAddr(cast<ExprWithCleanups>(E)->getSubExpr(), refVars); + // For casts, we need to handle conversions from arrays to // pointer values, and pointer-to-pointer conversions. case Stmt::ImplicitCastExprClass: case Stmt::CStyleCastExprClass: case Stmt::CXXFunctionalCastExprClass: - case Stmt::ObjCBridgedCastExprClass: { - Expr* SubExpr = cast<CastExpr>(E)->getSubExpr(); - QualType T = SubExpr->getType(); - - if (SubExpr->getType()->isPointerType() || - SubExpr->getType()->isBlockPointerType() || - SubExpr->getType()->isObjCQualifiedIdType()) - return EvalAddr(SubExpr, refVars); - else if (T->isArrayType()) - return EvalVal(SubExpr, refVars); - else - return 0; - } - - // C++ casts. For dynamic casts, static casts, and const casts, we - // are always converting from a pointer-to-pointer, so we just blow - // through the cast. In the case the dynamic cast doesn't fail (and - // return NULL), we take the conservative route and report cases - // where we return the address of a stack variable. For Reinterpre - // FIXME: The comment about is wrong; we're not always converting - // from pointer to pointer. I'm guessing that this code should also - // handle references to objects. + case Stmt::ObjCBridgedCastExprClass: case Stmt::CXXStaticCastExprClass: case Stmt::CXXDynamicCastExprClass: case Stmt::CXXConstCastExprClass: case Stmt::CXXReinterpretCastExprClass: { - Expr *S = cast<CXXNamedCastExpr>(E)->getSubExpr(); - if (S->getType()->isPointerType() || S->getType()->isBlockPointerType()) - return EvalAddr(S, refVars); - else - return NULL; + Expr* SubExpr = cast<CastExpr>(E)->getSubExpr(); + switch (cast<CastExpr>(E)->getCastKind()) { + case CK_BitCast: + case CK_LValueToRValue: + case CK_NoOp: + case CK_BaseToDerived: + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + case CK_Dynamic: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: + case CK_AnyPointerToBlockPointerCast: + return EvalAddr(SubExpr, refVars); + + case CK_ArrayToPointerDecay: + return EvalVal(SubExpr, refVars); + + default: + return 0; + } } case Stmt::MaterializeTemporaryExprClass: @@ -2637,6 +3290,9 @@ do { return NULL; } + case Stmt::ExprWithCleanupsClass: + return EvalVal(cast<ExprWithCleanups>(E)->getSubExpr(), refVars); + case Stmt::DeclRefExprClass: { // When we hit a DeclRefExpr we are looking at code that refers to a // variable's name. If it's not a reference variable we check if it has @@ -2766,12 +3422,12 @@ void Sema::CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr *RHS) { // Check for comparisons with builtin types. if (EmitWarning) if (CallExpr* CL = dyn_cast<CallExpr>(LeftExprSansParen)) - if (CL->isBuiltinCall(Context)) + if (CL->isBuiltinCall()) EmitWarning = false; if (EmitWarning) if (CallExpr* CR = dyn_cast<CallExpr>(RightExprSansParen)) - if (CR->isBuiltinCall(Context)) + if (CR->isBuiltinCall()) EmitWarning = false; // Emit the diagnostic. @@ -2870,7 +3526,8 @@ struct IntRange { } }; -IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, unsigned MaxWidth) { +static IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, + unsigned MaxWidth) { if (value.isSigned() && value.isNegative()) return IntRange(value.getMinSignedBits(), false); @@ -2882,8 +3539,8 @@ IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, unsigned MaxWidth) { return IntRange(value.getActiveBits(), true); } -IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty, - unsigned MaxWidth) { +static IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty, + unsigned MaxWidth) { if (result.isInt()) return GetValueRange(C, result.getInt(), MaxWidth); @@ -2907,7 +3564,7 @@ IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty, // FIXME: The only reason we need to pass the type in here is to get // the sign right on this one case. It would be nice if APValue // preserved this. - assert(result.isLValue()); + assert(result.isLValue() || result.isAddrLabelDiff()); return IntRange(MaxWidth, Ty->isUnsignedIntegerOrEnumerationType()); } @@ -2915,19 +3572,19 @@ IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty, /// range of values it might take. /// /// \param MaxWidth - the width to which the value will be truncated -IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { +static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { E = E->IgnoreParens(); // Try a full evaluation first. Expr::EvalResult result; - if (E->Evaluate(result, C)) + if (E->EvaluateAsRValue(result, C)) return GetValueRange(C, result.Val, E->getType(), MaxWidth); // I think we only want to look through implicit casts here; if the // user has an explicit widening cast, we should treat the value as // being of the new, wider type. if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) { - if (CE->getCastKind() == CK_NoOp) + if (CE->getCastKind() == CK_NoOp || CE->getCastKind() == CK_LValueToRValue) return GetExprRange(C, CE->getSubExpr(), MaxWidth); IntRange OutputTypeRange = IntRange::forValueOfType(C, CE->getType()); @@ -3133,16 +3790,16 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { return IntRange::forValueOfType(C, E->getType()); } -IntRange GetExprRange(ASTContext &C, Expr *E) { +static IntRange GetExprRange(ASTContext &C, Expr *E) { return GetExprRange(C, E, C.getIntWidth(E->getType())); } /// Checks whether the given value, which currently has the given /// source semantics, has the same value when coerced through the /// target semantics. -bool IsSameFloatAfterCast(const llvm::APFloat &value, - const llvm::fltSemantics &Src, - const llvm::fltSemantics &Tgt) { +static bool IsSameFloatAfterCast(const llvm::APFloat &value, + const llvm::fltSemantics &Src, + const llvm::fltSemantics &Tgt) { llvm::APFloat truncated = value; bool ignored; @@ -3157,9 +3814,9 @@ bool IsSameFloatAfterCast(const llvm::APFloat &value, /// target semantics. /// /// The value might be a vector of floats (or a complex number). -bool IsSameFloatAfterCast(const APValue &value, - const llvm::fltSemantics &Src, - const llvm::fltSemantics &Tgt) { +static bool IsSameFloatAfterCast(const APValue &value, + const llvm::fltSemantics &Src, + const llvm::fltSemantics &Tgt) { if (value.isFloat()) return IsSameFloatAfterCast(value.getFloat(), Src, Tgt); @@ -3175,7 +3832,7 @@ bool IsSameFloatAfterCast(const APValue &value, IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt)); } -void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC); +static void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC); static bool IsZero(Sema &S, Expr *E) { // Suppress cases where we are comparing against an enum constant. @@ -3204,7 +3861,7 @@ static bool HasEnumType(Expr *E) { return E->getType()->isEnumeralType(); } -void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) { +static void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) { BinaryOperatorKind op = E->getOpcode(); if (E->isValueDependent()) return; @@ -3230,7 +3887,7 @@ void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) { /// Analyze the operands of the given comparison. Implements the /// fallback case from AnalyzeComparison. -void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) { +static void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) { AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc()); } @@ -3238,7 +3895,7 @@ void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) { /// \brief Implements -Wsign-compare. /// /// \param E the binary operator to check for warnings -void AnalyzeComparison(Sema &S, BinaryOperator *E) { +static void AnalyzeComparison(Sema &S, BinaryOperator *E) { // The type the comparison is being performed in. QualType T = E->getLHS()->getType(); assert(S.Context.hasSameUnqualifiedType(T, E->getRHS()->getType()) @@ -3311,8 +3968,8 @@ void AnalyzeComparison(Sema &S, BinaryOperator *E) { /// Analyzes an attempt to assign the given value to a bitfield. /// /// Returns true if there was something fishy about the attempt. -bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, - SourceLocation InitLoc) { +static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, + SourceLocation InitLoc) { assert(Bitfield->isBitField()); if (Bitfield->isInvalidDecl()) return false; @@ -3330,31 +3987,30 @@ bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, Expr *OriginalInit = Init->IgnoreParenImpCasts(); - Expr::EvalResult InitValue; - if (!OriginalInit->Evaluate(InitValue, S.Context) || - !InitValue.Val.isInt()) + llvm::APSInt Value; + if (!OriginalInit->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects)) return false; - const llvm::APSInt &Value = InitValue.Val.getInt(); unsigned OriginalWidth = Value.getBitWidth(); unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context); if (OriginalWidth <= FieldWidth) return false; + // Compute the value which the bitfield will contain. llvm::APSInt TruncatedValue = Value.trunc(FieldWidth); + TruncatedValue.setIsSigned(Bitfield->getType()->isSignedIntegerType()); - // It's fairly common to write values into signed bitfields - // that, if sign-extended, would end up becoming a different - // value. We don't want to warn about that. - if (Value.isSigned() && Value.isNegative()) - TruncatedValue = TruncatedValue.sext(OriginalWidth); - else - TruncatedValue = TruncatedValue.zext(OriginalWidth); - + // Check whether the stored value is equal to the original value. + TruncatedValue = TruncatedValue.extend(OriginalWidth); if (Value == TruncatedValue) return false; + // Special-case bitfields of width 1: booleans are naturally 0/1, and + // therefore don't strictly fit into a signed bitfield of width 1. + if (FieldWidth == 1 && Value == 1) + return false; + std::string PrettyValue = Value.toString(10); std::string PrettyTrunc = TruncatedValue.toString(10); @@ -3367,7 +4023,7 @@ bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, /// Analyze the given simple or compound assignment for warning-worthy /// operations. -void AnalyzeAssignment(Sema &S, BinaryOperator *E) { +static void AnalyzeAssignment(Sema &S, BinaryOperator *E) { // Just recurse on the LHS. AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); @@ -3386,16 +4042,25 @@ void AnalyzeAssignment(Sema &S, BinaryOperator *E) { } /// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. -void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T, - SourceLocation CContext, unsigned diag) { +static void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T, + SourceLocation CContext, unsigned diag, + bool pruneControlFlow = false) { + if (pruneControlFlow) { + S.DiagRuntimeBehavior(E->getExprLoc(), E, + S.PDiag(diag) + << SourceType << T << E->getSourceRange() + << SourceRange(CContext)); + return; + } S.Diag(E->getExprLoc(), diag) << SourceType << T << E->getSourceRange() << SourceRange(CContext); } /// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. -void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext, - unsigned diag) { - DiagnoseImpCast(S, E, E->getType(), T, CContext, diag); +static void DiagnoseImpCast(Sema &S, Expr *E, QualType T, + SourceLocation CContext, unsigned diag, + bool pruneControlFlow = false) { + DiagnoseImpCast(S, E, E->getType(), T, CContext, diag, pruneControlFlow); } /// Diagnose an implicit cast from a literal expression. Does not warn when the @@ -3425,11 +4090,6 @@ std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { return ValueInRange.toString(10); } -static bool isFromSystemMacro(Sema &S, SourceLocation loc) { - SourceManager &smgr = S.Context.getSourceManager(); - return loc.isMacroID() && smgr.isInSystemHeader(smgr.getSpellingLoc(loc)); -} - void CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, bool *ICContext = 0) { if (E->isTypeDependent() || E->isValueDependent()) return; @@ -3455,13 +4115,43 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // 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.isExprCallable(*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; + } + } + } return; // Other casts to bool are not checked. } // Strip vector types. if (isa<VectorType>(Source)) { if (!isa<VectorType>(Target)) { - if (isFromSystemMacro(S, CC)) + if (S.SourceMgr.isInSystemMacro(CC)) return; return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar); } @@ -3478,7 +4168,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // Strip complex types. if (isa<ComplexType>(Source)) { if (!isa<ComplexType>(Target)) { - if (isFromSystemMacro(S, CC)) + if (S.SourceMgr.isInSystemMacro(CC)) return; return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_complex_scalar); @@ -3502,7 +4192,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // Don't warn about float constants that are precisely // representable in the target type. Expr::EvalResult result; - if (E->Evaluate(result, S.Context)) { + if (E->EvaluateAsRValue(result, S.Context)) { // Value might be a float, a float vector, or a float complex. if (IsSameFloatAfterCast(result.Val, S.Context.getFloatTypeSemantics(QualType(TargetBT, 0)), @@ -3510,7 +4200,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, return; } - if (isFromSystemMacro(S, CC)) + if (S.SourceMgr.isInSystemMacro(CC)) return; DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision); @@ -3520,7 +4210,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // If the target is integral, always warn. if ((TargetBT && TargetBT->isInteger())) { - if (isFromSystemMacro(S, CC)) + if (S.SourceMgr.isInSystemMacro(CC)) return; Expr *InnerE = E->IgnoreParenImpCasts(); @@ -3544,8 +4234,11 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if ((E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) == Expr::NPCK_GNUNull) && Target->isIntegerType()) { - S.Diag(E->getExprLoc(), diag::warn_impcast_null_pointer_to_integer) - << E->getSourceRange() << clang::SourceRange(CC); + SourceLocation Loc = E->getSourceRange().getBegin(); + if (Loc.isMacroID()) + Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first; + S.Diag(Loc, diag::warn_impcast_null_pointer_to_integer) + << T << Loc << clang::SourceRange(CC); return; } @@ -3557,24 +4250,27 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // TODO: this should happen for bitfield stores, too. llvm::APSInt Value(32); if (E->isIntegerConstantExpr(Value, S.Context)) { - if (isFromSystemMacro(S, CC)) + if (S.SourceMgr.isInSystemMacro(CC)) return; std::string PrettySourceValue = Value.toString(10); std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); - S.Diag(E->getExprLoc(), diag::warn_impcast_integer_precision_constant) - << PrettySourceValue << PrettyTargetValue - << E->getType() << T << E->getSourceRange() << clang::SourceRange(CC); + S.DiagRuntimeBehavior(E->getExprLoc(), E, + S.PDiag(diag::warn_impcast_integer_precision_constant) + << PrettySourceValue << PrettyTargetValue + << E->getType() << T << E->getSourceRange() + << clang::SourceRange(CC)); return; } // People want to build with -Wshorten-64-to-32 and not -Wconversion. - if (isFromSystemMacro(S, CC)) + if (S.SourceMgr.isInSystemMacro(CC)) return; - if (SourceRange.Width == 64 && TargetRange.Width == 32) - return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_64_32); + if (TargetRange.Width == 32 && S.Context.getIntWidth(E->getType()) == 64) + return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_64_32, + /* pruneControlFlow */ true); return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision); } @@ -3582,7 +4278,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, (!TargetRange.NonNegative && SourceRange.NonNegative && SourceRange.Width == TargetRange.Width)) { - if (isFromSystemMacro(S, CC)) + if (S.SourceMgr.isInSystemMacro(CC)) return; unsigned DiagID = diag::warn_impcast_integer_sign; @@ -3604,7 +4300,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // In C, we pretend that the type of an EnumConstantDecl is its enumeration // type, to give us better diagnostics. QualType SourceType = E->getType(); - if (!S.getLangOptions().CPlusPlus) { + if (!S.getLangOpts().CPlusPlus) { if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) if (EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(DRE->getDecl())) { EnumDecl *Enum = cast<EnumDecl>(ECD->getDeclContext()); @@ -3620,7 +4316,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, (TargetEnum->getDecl()->getIdentifier() || TargetEnum->getDecl()->getTypedefNameForAnonDecl()) && SourceEnum != TargetEnum) { - if (isFromSystemMacro(S, CC)) + if (S.SourceMgr.isInSystemMacro(CC)) return; return DiagnoseImpCast(S, E, SourceType, T, CC, @@ -3712,8 +4408,8 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { if (BO->isComparisonOp()) return AnalyzeComparison(S, BO); - // And with assignments and compound assignments. - if (BO->isAssignmentOp()) + // And with simple assignments. + if (BO->getOpcode() == BO_Assign) return AnalyzeAssignment(S, BO); } @@ -3731,7 +4427,10 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { BinaryOperator *BO = dyn_cast<BinaryOperator>(E); bool IsLogicalOperator = BO && BO->isLogicalOp(); for (Stmt::child_range I = E->children(); I; ++I) { - Expr *ChildExpr = cast<Expr>(*I); + Expr *ChildExpr = dyn_cast_or_null<Expr>(*I); + if (!ChildExpr) + continue; + if (IsLogicalOperator && isa<StringLiteral>(ChildExpr->IgnoreParenImpCasts())) // Ignore checking string literals that are in logical operators. @@ -3801,7 +4500,7 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl **P, ParmVarDecl **PEnd, if (CheckParameterNames && Param->getIdentifier() == 0 && !Param->isImplicit() && - !getLangOptions().CPlusPlus) + !getLangOpts().CPlusPlus) Diag(Param->getLocation(), diag::err_parameter_name_omitted); // C99 6.7.5.3p12: @@ -3897,8 +4596,11 @@ static bool IsTailPaddedMemberArray(Sema &S, llvm::APInt Size, return false; const RecordDecl *RD = dyn_cast<RecordDecl>(FD->getDeclContext()); - if (!RD || !RD->isStruct()) - return false; + if (!RD) return false; + if (RD->isUnion()) return false; + if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) { + if (!CRD->isStandardLayout()) return false; + } // See if this is the last field decl in the record. const Decl *D = FD; @@ -3909,21 +4611,24 @@ static bool IsTailPaddedMemberArray(Sema &S, llvm::APInt Size, } void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, - bool isSubscript, bool AllowOnePastEnd) { - const Type* EffectiveType = getElementType(BaseExpr); - BaseExpr = BaseExpr->IgnoreParenCasts(); - IndexExpr = IndexExpr->IgnoreParenCasts(); + const ArraySubscriptExpr *ASE, + bool AllowOnePastEnd, bool IndexNegated) { + IndexExpr = IndexExpr->IgnoreParenImpCasts(); + if (IndexExpr->isValueDependent()) + return; + const Type *EffectiveType = getElementType(BaseExpr); + BaseExpr = BaseExpr->IgnoreParenCasts(); const ConstantArrayType *ArrayTy = Context.getAsConstantArrayType(BaseExpr->getType()); if (!ArrayTy) return; - if (IndexExpr->isValueDependent()) - return; llvm::APSInt index; - if (!IndexExpr->isIntegerConstantExpr(index, Context)) + if (!IndexExpr->EvaluateAsInt(index, Context)) return; + if (IndexNegated) + index = -index; const NamedDecl *ND = NULL; if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr)) @@ -3954,15 +4659,15 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, } if (size.getBitWidth() > index.getBitWidth()) - index = index.sext(size.getBitWidth()); + index = index.zext(size.getBitWidth()); else if (size.getBitWidth() < index.getBitWidth()) - size = size.sext(index.getBitWidth()); + size = size.zext(index.getBitWidth()); // For array subscripting the index must be less than size, but for pointer // arithmetic also allow the index (offset) to be equal to size since // computing the next address after the end of the array is legal and // commonly done e.g. in C++ iterators and range-based for loops. - if (AllowOnePastEnd ? index.sle(size) : index.slt(size)) + if (AllowOnePastEnd ? index.ule(size) : index.ult(size)) return; // Also don't warn for arrays of size 1 which are members of some @@ -3971,8 +4676,22 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, if (IsTailPaddedMemberArray(*this, size, ND)) return; + // Suppress the warning if the subscript expression (as identified by the + // ']' location) and the index expression are both from macro expansions + // within a system header. + if (ASE) { + SourceLocation RBracketLoc = SourceMgr.getSpellingLoc( + ASE->getRBracketLoc()); + if (SourceMgr.isInSystemHeader(RBracketLoc)) { + SourceLocation IndexLoc = SourceMgr.getSpellingLoc( + IndexExpr->getLocStart()); + if (SourceMgr.isFromSameFile(RBracketLoc, IndexLoc)) + return; + } + } + unsigned DiagID = diag::warn_ptr_arith_exceeds_bounds; - if (isSubscript) + if (ASE) DiagID = diag::warn_array_index_exceeds_bounds; DiagRuntimeBehavior(BaseExpr->getLocStart(), BaseExpr, @@ -3982,7 +4701,7 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, << IndexExpr->getSourceRange()); } else { unsigned DiagID = diag::warn_array_index_precedes_bounds; - if (!isSubscript) { + if (!ASE) { DiagID = diag::warn_ptr_arith_precedes_bounds; if (index.isNegative()) index = -index; } @@ -3992,6 +4711,17 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, << IndexExpr->getSourceRange()); } + if (!ND) { + // Try harder to find a NamedDecl to point at in the note. + while (const ArraySubscriptExpr *ASE = + dyn_cast<ArraySubscriptExpr>(BaseExpr)) + BaseExpr = ASE->getBase()->IgnoreParenCasts(); + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr)) + ND = dyn_cast<NamedDecl>(DRE->getDecl()); + if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr)) + ND = dyn_cast<NamedDecl>(ME->getMemberDecl()); + } + if (ND) DiagRuntimeBehavior(ND->getLocStart(), BaseExpr, PDiag(diag::note_array_index_out_of_bounds) @@ -4005,7 +4735,7 @@ void Sema::CheckArrayAccess(const Expr *expr) { switch (expr->getStmtClass()) { case Stmt::ArraySubscriptExprClass: { const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(expr); - CheckArrayAccess(ASE->getBase(), ASE->getIdx(), true, + CheckArrayAccess(ASE->getBase(), ASE->getIdx(), ASE, AllowOnePastEnd > 0); return; } @@ -4070,7 +4800,7 @@ static bool considerVariable(VarDecl *var, Expr *ref, RetainCycleOwner &owner) { return true; } -static bool findRetainCycleOwner(Expr *e, RetainCycleOwner &owner) { +static bool findRetainCycleOwner(Sema &S, Expr *e, RetainCycleOwner &owner) { while (true) { e = e->IgnoreParens(); if (CastExpr *cast = dyn_cast<CastExpr>(e)) { @@ -4082,22 +4812,6 @@ static bool findRetainCycleOwner(Expr *e, RetainCycleOwner &owner) { e = cast->getSubExpr(); continue; - case CK_GetObjCProperty: { - // Bail out if this isn't a strong explicit property. - const ObjCPropertyRefExpr *pre = cast->getSubExpr()->getObjCProperty(); - if (pre->isImplicitProperty()) return false; - ObjCPropertyDecl *property = pre->getExplicitProperty(); - if (!property->isRetaining() && - !(property->getPropertyIvarDecl() && - property->getPropertyIvarDecl()->getType() - .getObjCLifetime() == Qualifiers::OCL_Strong)) - return false; - - owner.Indirect = true; - e = const_cast<Expr*>(pre->getBase()); - continue; - } - default: return false; } @@ -4109,7 +4823,7 @@ static bool findRetainCycleOwner(Expr *e, RetainCycleOwner &owner) { return false; // Try to find a retain cycle in the base. - if (!findRetainCycleOwner(ref->getBase(), owner)) + if (!findRetainCycleOwner(S, ref->getBase(), owner)) return false; if (ref->isFreeIvar()) owner.setLocsFrom(ref); @@ -4123,12 +4837,6 @@ static bool findRetainCycleOwner(Expr *e, RetainCycleOwner &owner) { return considerVariable(var, ref, owner); } - if (BlockDeclRefExpr *ref = dyn_cast<BlockDeclRefExpr>(e)) { - owner.Variable = ref->getDecl(); - owner.setLocsFrom(ref); - return true; - } - if (MemberExpr *member = dyn_cast<MemberExpr>(e)) { if (member->isArrow()) return false; @@ -4137,6 +4845,34 @@ static bool findRetainCycleOwner(Expr *e, RetainCycleOwner &owner) { continue; } + if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(e)) { + // Only pay attention to pseudo-objects on property references. + ObjCPropertyRefExpr *pre + = dyn_cast<ObjCPropertyRefExpr>(pseudo->getSyntacticForm() + ->IgnoreParens()); + if (!pre) return false; + if (pre->isImplicitProperty()) return false; + ObjCPropertyDecl *property = pre->getExplicitProperty(); + if (!property->isRetaining() && + !(property->getPropertyIvarDecl() && + property->getPropertyIvarDecl()->getType() + .getObjCLifetime() == Qualifiers::OCL_Strong)) + return false; + + owner.Indirect = true; + if (pre->isSuperReceiver()) { + owner.Variable = S.getCurMethodDecl()->getSelfDecl(); + if (!owner.Variable) + return false; + owner.Loc = pre->getLocation(); + owner.Range = pre->getSourceRange(); + return true; + } + e = const_cast<Expr*>(cast<OpaqueValueExpr>(pre->getBase()) + ->getSourceExpr()); + continue; + } + // Array ivars? return false; @@ -4157,11 +4893,6 @@ namespace { Capturer = ref; } - void VisitBlockDeclRefExpr(BlockDeclRefExpr *ref) { - if (ref->getDecl() == Variable && !Capturer) - Capturer = ref; - } - void VisitObjCIvarRefExpr(ObjCIvarRefExpr *ref) { if (Capturer) return; Visit(ref->getBase()); @@ -4210,8 +4941,14 @@ static bool isSetterLikeSelector(Selector sel) { StringRef str = sel.getNameForSlot(0); while (!str.empty() && str.front() == '_') str = str.substr(1); - if (str.startswith("set") || str.startswith("add")) + if (str.startswith("set")) str = str.substr(3); + else if (str.startswith("add")) { + // Specially whitelist 'addOperationWithBlock:'. + if (sel.getNumArgs() == 1 && str.startswith("addOperationWithBlock")) + return false; + str = str.substr(3); + } else return false; @@ -4228,7 +4965,7 @@ void Sema::checkRetainCycles(ObjCMessageExpr *msg) { // Try to find a variable that the receiver is strongly owned by. RetainCycleOwner owner; if (msg->getReceiverKind() == ObjCMessageExpr::Instance) { - if (!findRetainCycleOwner(msg->getInstanceReceiver(), owner)) + if (!findRetainCycleOwner(*this, msg->getInstanceReceiver(), owner)) return; } else { assert(msg->getReceiverKind() == ObjCMessageExpr::SuperInstance); @@ -4246,7 +4983,7 @@ void Sema::checkRetainCycles(ObjCMessageExpr *msg) { /// Check a property assign to see if it's likely to cause a retain cycle. void Sema::checkRetainCycles(Expr *receiver, Expr *argument) { RetainCycleOwner owner; - if (!findRetainCycleOwner(receiver, owner)) + if (!findRetainCycleOwner(*this, receiver, owner)) return; if (Expr *capturer = findCapturingExpr(*this, argument, owner)) @@ -4273,7 +5010,19 @@ bool Sema::checkUnsafeAssigns(SourceLocation Loc, void Sema::checkUnsafeExprAssigns(SourceLocation Loc, Expr *LHS, Expr *RHS) { - QualType LHSType = LHS->getType(); + QualType LHSType; + // PropertyRef on LHS type need be directly obtained from + // its declaration as it has a PsuedoType. + ObjCPropertyRefExpr *PRE + = dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens()); + if (PRE && !PRE->isImplicitProperty()) { + const ObjCPropertyDecl *PD = PRE->getExplicitProperty(); + if (PD) + LHSType = PD->getType(); + } + + if (LHSType.isNull()) + LHSType = LHS->getType(); if (checkUnsafeAssigns(Loc, LHSType, RHS)) return; Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime(); @@ -4281,7 +5030,7 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc, if (LT != Qualifiers::OCL_None) return; - if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(LHS)) { + if (PRE) { if (PRE->isImplicitProperty()) return; const ObjCPropertyDecl *PD = PRE->getExplicitProperty(); @@ -4289,7 +5038,15 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc, return; unsigned Attributes = PD->getPropertyAttributes(); - if (Attributes & ObjCPropertyDecl::OBJC_PR_assign) + if (Attributes & ObjCPropertyDecl::OBJC_PR_assign) { + // when 'assign' attribute was not explicitly specified + // by user, ignore it and rely on property type itself + // for lifetime info. + unsigned AsWrittenAttr = PD->getPropertyAttributesAsWritten(); + if (!(AsWrittenAttr & ObjCPropertyDecl::OBJC_PR_assign) && + LHSType->isObjCRetainableType()) + return; + while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) { if (cast->getCastKind() == CK_ARCConsumeObject) { Diag(Loc, diag::warn_arc_retained_property_assign) @@ -4298,5 +5055,132 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc, } RHS = cast->getSubExpr(); } + } + } +} + +//===--- CHECK: Empty statement body (-Wempty-body) ---------------------===// + +namespace { +bool ShouldDiagnoseEmptyStmtBody(const SourceManager &SourceMgr, + SourceLocation StmtLoc, + const NullStmt *Body) { + // Do not warn if the body is a macro that expands to nothing, e.g: + // + // #define CALL(x) + // if (condition) + // CALL(0); + // + if (Body->hasLeadingEmptyMacro()) + return false; + + // Get line numbers of statement and body. + bool StmtLineInvalid; + unsigned StmtLine = SourceMgr.getSpellingLineNumber(StmtLoc, + &StmtLineInvalid); + if (StmtLineInvalid) + return false; + + bool BodyLineInvalid; + unsigned BodyLine = SourceMgr.getSpellingLineNumber(Body->getSemiLoc(), + &BodyLineInvalid); + if (BodyLineInvalid) + return false; + + // Warn if null statement and body are on the same line. + if (StmtLine != BodyLine) + return false; + + return true; +} +} // Unnamed namespace + +void Sema::DiagnoseEmptyStmtBody(SourceLocation StmtLoc, + const Stmt *Body, + unsigned DiagID) { + // Since this is a syntactic check, don't emit diagnostic for template + // instantiations, this just adds noise. + if (CurrentInstantiationScope) + return; + + // The body should be a null statement. + const NullStmt *NBody = dyn_cast<NullStmt>(Body); + if (!NBody) + return; + + // Do the usual checks. + if (!ShouldDiagnoseEmptyStmtBody(SourceMgr, StmtLoc, NBody)) + return; + + Diag(NBody->getSemiLoc(), DiagID); + Diag(NBody->getSemiLoc(), diag::note_empty_body_on_separate_line); +} + +void Sema::DiagnoseEmptyLoopBody(const Stmt *S, + const Stmt *PossibleBody) { + assert(!CurrentInstantiationScope); // Ensured by caller + + SourceLocation StmtLoc; + const Stmt *Body; + unsigned DiagID; + if (const ForStmt *FS = dyn_cast<ForStmt>(S)) { + StmtLoc = FS->getRParenLoc(); + Body = FS->getBody(); + DiagID = diag::warn_empty_for_body; + } else if (const WhileStmt *WS = dyn_cast<WhileStmt>(S)) { + StmtLoc = WS->getCond()->getSourceRange().getEnd(); + Body = WS->getBody(); + DiagID = diag::warn_empty_while_body; + } else + return; // Neither `for' nor `while'. + + // The body should be a null statement. + const NullStmt *NBody = dyn_cast<NullStmt>(Body); + if (!NBody) + return; + + // Skip expensive checks if diagnostic is disabled. + if (Diags.getDiagnosticLevel(DiagID, NBody->getSemiLoc()) == + DiagnosticsEngine::Ignored) + return; + + // Do the usual checks. + if (!ShouldDiagnoseEmptyStmtBody(SourceMgr, StmtLoc, NBody)) + return; + + // `for(...);' and `while(...);' are popular idioms, so in order to keep + // noise level low, emit diagnostics only if for/while is followed by a + // CompoundStmt, e.g.: + // for (int i = 0; i < n; i++); + // { + // a(i); + // } + // or if for/while is followed by a statement with more indentation + // than for/while itself: + // for (int i = 0; i < n; i++); + // a(i); + bool ProbableTypo = isa<CompoundStmt>(PossibleBody); + if (!ProbableTypo) { + bool BodyColInvalid; + unsigned BodyCol = SourceMgr.getPresumedColumnNumber( + PossibleBody->getLocStart(), + &BodyColInvalid); + if (BodyColInvalid) + return; + + bool StmtColInvalid; + unsigned StmtCol = SourceMgr.getPresumedColumnNumber( + S->getLocStart(), + &StmtColInvalid); + if (StmtColInvalid) + return; + + if (BodyCol > StmtCol) + ProbableTypo = true; + } + + if (ProbableTypo) { + Diag(NBody->getSemiLoc(), DiagID); + Diag(NBody->getSemiLoc(), diag::note_empty_body_on_separate_line); } } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp index 405d626..1ee7532 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp @@ -20,10 +20,13 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/Lex/HeaderSearch.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" @@ -120,6 +123,8 @@ namespace { /// \brief The allocator used to allocate new code-completion strings. CodeCompletionAllocator &Allocator; + + CodeCompletionTUInfo &CCTUInfo; /// \brief If non-NULL, a filter function used to remove any code-completion /// results that are not desirable. @@ -163,9 +168,11 @@ namespace { public: explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo, const CodeCompletionContext &CompletionContext, LookupFilter Filter = 0) - : SemaRef(SemaRef), Allocator(Allocator), Filter(Filter), + : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo), + Filter(Filter), AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false), CompletionContext(CompletionContext), ObjCImplementation(0) @@ -248,6 +255,8 @@ namespace { /// \brief Retrieve the allocator used to allocate code completion strings. CodeCompletionAllocator &getAllocator() const { return Allocator; } + + CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; } /// \brief Determine whether the given declaration is at all interesting /// as a code-completion result. @@ -271,9 +280,9 @@ namespace { /// of the shadow maps), or replace an existing result (for, e.g., a /// redeclaration). /// - /// \param CurContext the result to add (if it is unique). + /// \param R the result to add (if it is unique). /// - /// \param R the context in which this result will be named. + /// \param CurContext the context in which this result will be named. void MaybeAddResult(Result R, DeclContext *CurContext = 0); /// \brief Add a new result to this result set, where we already know @@ -322,6 +331,7 @@ namespace { bool IsMember(NamedDecl *ND) const; bool IsObjCIvar(NamedDecl *ND) const; bool IsObjCMessageReceiver(NamedDecl *ND) const; + bool IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const; bool IsObjCCollection(NamedDecl *ND) const; bool IsImpossibleToSatisfy(NamedDecl *ND) const; //@} @@ -510,14 +520,6 @@ bool ResultBuilder::isInterestingDecl(NamedDecl *ND, return false; } } - - // Skip out-of-line declarations and definitions. - // NOTE: Unless it's an Objective-C property, method, or ivar, where - // the contexts can be messy. - if (!ND->getDeclContext()->Equals(ND->getLexicalDeclContext()) && - !(isa<ObjCPropertyDecl>(ND) || isa<ObjCIvarDecl>(ND) || - isa<ObjCMethodDecl>(ND))) - return false; if (Filter == &ResultBuilder::IsNestedNameSpecifier || ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) && @@ -529,7 +531,7 @@ bool ResultBuilder::isInterestingDecl(NamedDecl *ND, // Filter out any unwanted results. if (Filter && !(this->*Filter)(ND)) { // Check whether it is interesting as a nested-name-specifier. - if (AllowNestedNameSpecifiers && SemaRef.getLangOptions().CPlusPlus && + if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus && IsNestedNameSpecifier(ND) && (Filter != &ResultBuilder::IsMember || (isa<CXXRecordDecl>(ND) && @@ -549,7 +551,7 @@ bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext, // In C, there is no way to refer to a hidden name. // FIXME: This isn't true; we can find a tag name hidden by an ordinary // name if we introduce the tag type. - if (!SemaRef.getLangOptions().CPlusPlus) + if (!SemaRef.getLangOpts().CPlusPlus) return true; DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext(); @@ -596,8 +598,7 @@ SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) { default: return STC_Arithmetic; } - return STC_Other; - + case Type::Complex: return STC_Arithmetic; @@ -729,7 +730,7 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) { } void ResultBuilder::MaybeAddConstructorResults(Result R) { - if (!SemaRef.getLangOptions().CPlusPlus || !R.Declaration || + if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration || !CompletionContext.wantConstructorResults()) return; @@ -901,7 +902,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, if (Hiding && CheckHiddenResult(R, CurContext, Hiding)) return; - + // Make sure that any given declaration only shows up in the result set once. if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl())) return; @@ -985,9 +986,9 @@ bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const { ND = cast<NamedDecl>(ND->getUnderlyingDecl()); unsigned IDNS = Decl::IDNS_Ordinary; - if (SemaRef.getLangOptions().CPlusPlus) + if (SemaRef.getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; - else if (SemaRef.getLangOptions().ObjC1) { + else if (SemaRef.getLangOpts().ObjC1) { if (isa<ObjCIvarDecl>(ND)) return true; } @@ -1003,9 +1004,9 @@ bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const { return false; unsigned IDNS = Decl::IDNS_Ordinary; - if (SemaRef.getLangOptions().CPlusPlus) + if (SemaRef.getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; - else if (SemaRef.getLangOptions().ObjC1) { + else if (SemaRef.getLangOpts().ObjC1) { if (isa<ObjCIvarDecl>(ND)) return true; } @@ -1030,7 +1031,7 @@ bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const { ND = cast<NamedDecl>(ND->getUnderlyingDecl()); unsigned IDNS = Decl::IDNS_Ordinary; - if (SemaRef.getLangOptions().CPlusPlus) + if (SemaRef.getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace; return (ND->getIdentifierNamespace() & IDNS) && @@ -1132,7 +1133,7 @@ static bool isObjCReceiverType(ASTContext &C, QualType T) { break; } - if (!C.getLangOptions().CPlusPlus) + if (!C.getLangOpts().CPlusPlus) return false; // FIXME: We could perform more analysis here to determine whether a @@ -1150,9 +1151,20 @@ bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const { return isObjCReceiverType(SemaRef.Context, T); } +bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const { + if (IsObjCMessageReceiver(ND)) + return true; + + VarDecl *Var = dyn_cast<VarDecl>(ND); + if (!Var) + return false; + + return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>(); +} + bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const { - if ((SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryName(ND)) || - (!SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryNonTypeName(ND))) + if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) || + (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND))) return false; QualType T = getDeclUsageType(SemaRef.Context, ND); @@ -1162,7 +1174,7 @@ bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const { T = SemaRef.Context.getBaseElementType(T); return T->isObjCObjectType() || T->isObjCObjectPointerType() || T->isObjCIdType() || - (SemaRef.getLangOptions().CPlusPlus && T->isRecordType()); + (SemaRef.getLangOpts().CPlusPlus && T->isRecordType()); } bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const { @@ -1189,11 +1201,9 @@ namespace { virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, bool InBaseClass) { bool Accessible = true; - if (Ctx) { - if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) - Accessible = Results.getSema().IsSimplyAccessible(ND, Class); - // FIXME: ObjC access checks are missing. - } + if (Ctx) + Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx); + ResultBuilder::Result Result(ND, 0, false, Accessible); Results.AddResult(Result, CurContext, Hiding, InBaseClass); } @@ -1227,7 +1237,8 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, Results.AddResult(Result("restrict", CCP_Type)); } - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); if (LangOpts.CPlusPlus) { // C++-specific Results.AddResult(Result("bool", CCP_Type + @@ -1337,7 +1348,8 @@ static void AddObjCInterfaceResults(const LangOptions &LangOpts, static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt); static void AddTypedefResult(ResultBuilder &Results) { - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); Builder.AddTypedTextChunk("typedef"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("type"); @@ -1372,8 +1384,72 @@ static bool WantTypesInContext(Sema::ParserCompletionContext CCC, case Sema::PCC_ForInit: return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99; } + + llvm_unreachable("Invalid ParserCompletionContext!"); +} + +static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context, + const Preprocessor &PP) { + PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP); + Policy.AnonymousTagLocations = false; + Policy.SuppressStrongLifetime = true; + Policy.SuppressUnwrittenScope = true; + return Policy; +} + +/// \brief Retrieve a printing policy suitable for code completion. +static PrintingPolicy getCompletionPrintingPolicy(Sema &S) { + return getCompletionPrintingPolicy(S.Context, S.PP); +} + +/// \brief Retrieve the string representation of the given type as a string +/// that has the appropriate lifetime for code completion. +/// +/// This routine provides a fast path where we provide constant strings for +/// common type names. +static const char *GetCompletionTypeString(QualType T, + ASTContext &Context, + const PrintingPolicy &Policy, + CodeCompletionAllocator &Allocator) { + if (!T.getLocalQualifiers()) { + // Built-in type names are constant strings. + if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) + return BT->getName(Policy); + + // Anonymous tag types are constant strings. + if (const TagType *TagT = dyn_cast<TagType>(T)) + if (TagDecl *Tag = TagT->getDecl()) + if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) { + switch (Tag->getTagKind()) { + case TTK_Struct: return "struct <anonymous>"; + case TTK_Class: return "class <anonymous>"; + case TTK_Union: return "union <anonymous>"; + case TTK_Enum: return "enum <anonymous>"; + } + } + } - return false; + // Slow path: format the type as a string. + std::string Result; + T.getAsStringInternal(Result, Policy); + return Allocator.CopyString(Result); +} + +/// \brief Add a completion for "this", if we're in a member function. +static void addThisCompletion(Sema &S, ResultBuilder &Results) { + QualType ThisTy = S.getCurrentThisType(); + if (ThisTy.isNull()) + return; + + CodeCompletionAllocator &Allocator = Results.getAllocator(); + CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); + PrintingPolicy Policy = getCompletionPrintingPolicy(S); + Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy, + S.Context, + Policy, + Allocator)); + Builder.AddTypedTextChunk("this"); + Results.AddResult(CodeCompletionResult(Builder.TakeString())); } /// \brief Add language constructs that show up for "ordinary" names. @@ -1381,12 +1457,14 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, Sema &SemaRef, ResultBuilder &Results) { - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionAllocator &Allocator = Results.getAllocator(); + CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); + PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef); typedef CodeCompletionResult Result; switch (CCC) { case Sema::PCC_Namespace: - if (SemaRef.getLangOptions().CPlusPlus) { + if (SemaRef.getLangOpts().CPlusPlus) { if (Results.includeCodePatterns()) { // namespace <identifier> { declarations } Builder.AddTypedTextChunk("namespace"); @@ -1431,14 +1509,14 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, } } - if (SemaRef.getLangOptions().ObjC1) + if (SemaRef.getLangOpts().ObjC1) AddObjCTopLevelResults(Results, true); AddTypedefResult(Results); // Fall through case Sema::PCC_Class: - if (SemaRef.getLangOptions().CPlusPlus) { + if (SemaRef.getLangOpts().CPlusPlus) { // Using declaration Builder.AddTypedTextChunk("using"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -1464,17 +1542,20 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, // public: Builder.AddTypedTextChunk("public"); - Builder.AddChunk(CodeCompletionString::CK_Colon); + if (Results.includeCodePatterns()) + Builder.AddChunk(CodeCompletionString::CK_Colon); Results.AddResult(Result(Builder.TakeString())); // protected: Builder.AddTypedTextChunk("protected"); - Builder.AddChunk(CodeCompletionString::CK_Colon); + if (Results.includeCodePatterns()) + Builder.AddChunk(CodeCompletionString::CK_Colon); Results.AddResult(Result(Builder.TakeString())); // private: Builder.AddTypedTextChunk("private"); - Builder.AddChunk(CodeCompletionString::CK_Colon); + if (Results.includeCodePatterns()) + Builder.AddChunk(CodeCompletionString::CK_Colon); Results.AddResult(Result(Builder.TakeString())); } } @@ -1482,7 +1563,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, case Sema::PCC_Template: case Sema::PCC_MemberTemplate: - if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) { + if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) { // template < parameters > Builder.AddTypedTextChunk("template"); Builder.AddChunk(CodeCompletionString::CK_LeftAngle); @@ -1491,32 +1572,32 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Results.AddResult(Result(Builder.TakeString())); } - AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results); - AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results); + AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); + AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); break; case Sema::PCC_ObjCInterface: - AddObjCInterfaceResults(SemaRef.getLangOptions(), Results, true); - AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results); - AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results); + AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true); + AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); + AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); break; case Sema::PCC_ObjCImplementation: - AddObjCImplementationResults(SemaRef.getLangOptions(), Results, true); - AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results); - AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results); + AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true); + AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); + AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); break; case Sema::PCC_ObjCInstanceVariableList: - AddObjCVisibilityResults(SemaRef.getLangOptions(), Results, true); + AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true); break; case Sema::PCC_RecoveryInFunction: case Sema::PCC_Statement: { AddTypedefResult(Results); - if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns() && - SemaRef.getLangOptions().CXXExceptions) { + if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() && + SemaRef.getLangOpts().CXXExceptions) { Builder.AddTypedTextChunk("try"); Builder.AddChunk(CodeCompletionString::CK_LeftBrace); Builder.AddPlaceholderChunk("statements"); @@ -1532,14 +1613,14 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_RightBrace); Results.AddResult(Result(Builder.TakeString())); } - if (SemaRef.getLangOptions().ObjC1) + if (SemaRef.getLangOpts().ObjC1) AddObjCStatementResults(Results, true); if (Results.includeCodePatterns()) { // if (condition) { statements } Builder.AddTypedTextChunk("if"); Builder.AddChunk(CodeCompletionString::CK_LeftParen); - if (SemaRef.getLangOptions().CPlusPlus) + if (SemaRef.getLangOpts().CPlusPlus) Builder.AddPlaceholderChunk("condition"); else Builder.AddPlaceholderChunk("expression"); @@ -1553,7 +1634,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, // switch (condition) { } Builder.AddTypedTextChunk("switch"); Builder.AddChunk(CodeCompletionString::CK_LeftParen); - if (SemaRef.getLangOptions().CPlusPlus) + if (SemaRef.getLangOpts().CPlusPlus) Builder.AddPlaceholderChunk("condition"); else Builder.AddPlaceholderChunk("expression"); @@ -1583,7 +1664,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, /// while (condition) { statements } Builder.AddTypedTextChunk("while"); Builder.AddChunk(CodeCompletionString::CK_LeftParen); - if (SemaRef.getLangOptions().CPlusPlus) + if (SemaRef.getLangOpts().CPlusPlus) Builder.AddPlaceholderChunk("condition"); else Builder.AddPlaceholderChunk("expression"); @@ -1609,7 +1690,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, // for ( for-init-statement ; condition ; expression ) { statements } Builder.AddTypedTextChunk("for"); Builder.AddChunk(CodeCompletionString::CK_LeftParen); - if (SemaRef.getLangOptions().CPlusPlus || SemaRef.getLangOptions().C99) + if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99) Builder.AddPlaceholderChunk("init-statement"); else Builder.AddPlaceholderChunk("init-expression"); @@ -1674,11 +1755,11 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, // Fall through (for statement expressions). case Sema::PCC_ForInit: case Sema::PCC_Condition: - AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results); + AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); // Fall through: conditions and statements can have expressions. case Sema::PCC_ParenthesizedExpression: - if (SemaRef.getLangOptions().ObjCAutoRefCount && + if (SemaRef.getLangOpts().ObjCAutoRefCount && CCC == Sema::PCC_ParenthesizedExpression) { // (__bridge <type>)<expression> Builder.AddTypedTextChunk("__bridge"); @@ -1707,17 +1788,21 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, // Fall through case Sema::PCC_Expression: { - if (SemaRef.getLangOptions().CPlusPlus) { + if (SemaRef.getLangOpts().CPlusPlus) { // 'this', if we're in a non-static member function. - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(SemaRef.CurContext)) - if (!Method->isStatic()) - Results.AddResult(Result("this")); + addThisCompletion(SemaRef, Results); - // true, false - Results.AddResult(Result("true")); - Results.AddResult(Result("false")); + // true + Builder.AddResultTypeChunk("bool"); + Builder.AddTypedTextChunk("true"); + Results.AddResult(Result(Builder.TakeString())); + + // false + Builder.AddResultTypeChunk("bool"); + Builder.AddTypedTextChunk("false"); + Results.AddResult(Result(Builder.TakeString())); - if (SemaRef.getLangOptions().RTTI) { + if (SemaRef.getLangOpts().RTTI) { // dynamic_cast < type-id > ( expression ) Builder.AddTypedTextChunk("dynamic_cast"); Builder.AddChunk(CodeCompletionString::CK_LeftAngle); @@ -1759,8 +1844,9 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_RightParen); Results.AddResult(Result(Builder.TakeString())); - if (SemaRef.getLangOptions().RTTI) { + if (SemaRef.getLangOpts().RTTI) { // typeid ( expression-or-type ) + Builder.AddResultTypeChunk("std::type_info"); Builder.AddTypedTextChunk("typeid"); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("expression-or-type"); @@ -1790,12 +1876,14 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Results.AddResult(Result(Builder.TakeString())); // delete expression + Builder.AddResultTypeChunk("void"); Builder.AddTypedTextChunk("delete"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("expression"); Results.AddResult(Result(Builder.TakeString())); // delete [] expression + Builder.AddResultTypeChunk("void"); Builder.AddTypedTextChunk("delete"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddChunk(CodeCompletionString::CK_LeftBracket); @@ -1804,30 +1892,71 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddPlaceholderChunk("expression"); Results.AddResult(Result(Builder.TakeString())); - if (SemaRef.getLangOptions().CXXExceptions) { + if (SemaRef.getLangOpts().CXXExceptions) { // throw expression + Builder.AddResultTypeChunk("void"); Builder.AddTypedTextChunk("throw"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("expression"); Results.AddResult(Result(Builder.TakeString())); } - + // FIXME: Rethrow? + + if (SemaRef.getLangOpts().CPlusPlus0x) { + // nullptr + Builder.AddResultTypeChunk("std::nullptr_t"); + Builder.AddTypedTextChunk("nullptr"); + Results.AddResult(Result(Builder.TakeString())); + + // alignof + Builder.AddResultTypeChunk("size_t"); + Builder.AddTypedTextChunk("alignof"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // noexcept + Builder.AddResultTypeChunk("bool"); + Builder.AddTypedTextChunk("noexcept"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // sizeof... expression + Builder.AddResultTypeChunk("size_t"); + Builder.AddTypedTextChunk("sizeof..."); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("parameter-pack"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + } } - if (SemaRef.getLangOptions().ObjC1) { + if (SemaRef.getLangOpts().ObjC1) { // Add "super", if we're in an Objective-C class with a superclass. if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) { // The interface can be NULL. if (ObjCInterfaceDecl *ID = Method->getClassInterface()) - if (ID->getSuperClass()) - Results.AddResult(Result("super")); + if (ID->getSuperClass()) { + std::string SuperType; + SuperType = ID->getSuperClass()->getNameAsString(); + if (Method->isInstanceMethod()) + SuperType += " *"; + + Builder.AddResultTypeChunk(Allocator.CopyString(SuperType)); + Builder.AddTypedTextChunk("super"); + Results.AddResult(Result(Builder.TakeString())); + } } AddObjCExpressionResults(Results, true); } // sizeof expression + Builder.AddResultTypeChunk("size_t"); Builder.AddTypedTextChunk("sizeof"); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("expression-or-type"); @@ -1841,54 +1970,13 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, break; } - if (WantTypesInContext(CCC, SemaRef.getLangOptions())) - AddTypeSpecifierResults(SemaRef.getLangOptions(), Results); + if (WantTypesInContext(CCC, SemaRef.getLangOpts())) + AddTypeSpecifierResults(SemaRef.getLangOpts(), Results); - if (SemaRef.getLangOptions().CPlusPlus && CCC != Sema::PCC_Type) + if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type) Results.AddResult(Result("operator")); } -/// \brief Retrieve a printing policy suitable for code completion. -static PrintingPolicy getCompletionPrintingPolicy(Sema &S) { - PrintingPolicy Policy = S.getPrintingPolicy(); - Policy.AnonymousTagLocations = false; - Policy.SuppressStrongLifetime = true; - return Policy; -} - -/// \brief Retrieve the string representation of the given type as a string -/// that has the appropriate lifetime for code completion. -/// -/// This routine provides a fast path where we provide constant strings for -/// common type names. -static const char *GetCompletionTypeString(QualType T, - ASTContext &Context, - const PrintingPolicy &Policy, - CodeCompletionAllocator &Allocator) { - if (!T.getLocalQualifiers()) { - // Built-in type names are constant strings. - if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) - return BT->getName(Policy); - - // Anonymous tag types are constant strings. - if (const TagType *TagT = dyn_cast<TagType>(T)) - if (TagDecl *Tag = TagT->getDecl()) - if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) { - switch (Tag->getTagKind()) { - case TTK_Struct: return "struct <anonymous>"; - case TTK_Class: return "class <anonymous>"; - case TTK_Union: return "union <anonymous>"; - case TTK_Enum: return "enum <anonymous>"; - } - } - } - - // Slow path: format the type as a string. - std::string Result; - T.getAsStringInternal(Result, Policy); - return Allocator.CopyString(Result); -} - /// \brief If the given declaration has an associated type, add it as a result /// type chunk. static void AddResultTypeChunk(ASTContext &Context, @@ -1931,7 +2019,7 @@ static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod, CodeCompletionBuilder &Result) { if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>()) if (Sentinel->getSentinel() == 0) { - if (Context.getLangOptions().ObjC1 && + if (Context.getLangOpts().ObjC1 && Context.Idents.get("nil").hasMacroDefinition()) Result.AddTextChunk(", nil"); else if (Context.Idents.get("NULL").hasMacroDefinition()) @@ -1941,32 +2029,28 @@ static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod, } } -static void appendWithSpace(std::string &Result, StringRef Text) { - if (!Result.empty()) - Result += ' '; - Result += Text.str(); -} static std::string formatObjCParamQualifiers(unsigned ObjCQuals) { std::string Result; if (ObjCQuals & Decl::OBJC_TQ_In) - appendWithSpace(Result, "in"); + Result += "in "; else if (ObjCQuals & Decl::OBJC_TQ_Inout) - appendWithSpace(Result, "inout"); + Result += "inout "; else if (ObjCQuals & Decl::OBJC_TQ_Out) - appendWithSpace(Result, "out"); + Result += "out "; if (ObjCQuals & Decl::OBJC_TQ_Bycopy) - appendWithSpace(Result, "bycopy"); + Result += "bycopy "; else if (ObjCQuals & Decl::OBJC_TQ_Byref) - appendWithSpace(Result, "byref"); + Result += "byref "; if (ObjCQuals & Decl::OBJC_TQ_Oneway) - appendWithSpace(Result, "oneway"); + Result += "oneway "; return Result; } static std::string FormatFunctionParameter(ASTContext &Context, const PrintingPolicy &Policy, ParmVarDecl *Param, - bool SuppressName = false) { + bool SuppressName = false, + bool SuppressBlock = false) { bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext()); if (Param->getType()->isDependentType() || !Param->getType()->isBlockPointerType()) { @@ -1997,20 +2081,22 @@ static std::string FormatFunctionParameter(ASTContext &Context, TL = TSInfo->getTypeLoc().getUnqualifiedLoc(); while (true) { // Look through typedefs. - if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) { - if (TypeSourceInfo *InnerTSInfo - = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) { - TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc(); + if (!SuppressBlock) { + if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) { + if (TypeSourceInfo *InnerTSInfo + = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) { + TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc(); + continue; + } + } + + // Look through qualified types + if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) { + TL = QualifiedTL->getUnqualifiedLoc(); continue; } } - // Look through qualified types - if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) { - TL = QualifiedTL->getUnqualifiedLoc(); - continue; - } - // Try to get the function prototype behind the block pointer type, // then we're done. if (BlockPointerTypeLoc *BlockPtr @@ -2027,6 +2113,9 @@ static std::string FormatFunctionParameter(ASTContext &Context, // We were unable to find a FunctionProtoTypeLoc with parameter names // for the block; just use the parameter type as a placeholder. std::string Result; + if (!ObjCMethodParam && Param->getIdentifier()) + Result = Param->getIdentifier()->getName(); + Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy); if (ObjCMethodParam) { @@ -2038,36 +2127,52 @@ static std::string FormatFunctionParameter(ASTContext &Context, return Result; } - + // 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(); - if (!ResultType->isVoidType()) + if (!ResultType->isVoidType() || SuppressBlock) ResultType.getAsStringInternal(Result, Policy); - - Result = '^' + Result; + + // Format the parameter list. + std::string Params; if (!BlockProto || Block->getNumArgs() == 0) { if (BlockProto && BlockProto->getTypePtr()->isVariadic()) - Result += "(...)"; + Params = "(...)"; else - Result += "(void)"; + Params = "(void)"; } else { - Result += "("; + Params += "("; for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) { if (I) - Result += ", "; - Result += FormatFunctionParameter(Context, Policy, Block->getArg(I)); + Params += ", "; + Params += FormatFunctionParameter(Context, Policy, Block->getArg(I), + /*SuppressName=*/false, + /*SuppressBlock=*/true); if (I == N - 1 && BlockProto->getTypePtr()->isVariadic()) - Result += ", ..."; + Params += ", ..."; } + Params += ")"; + } + + if (SuppressBlock) { + // Format as a parameter. + Result = Result + " (^"; + if (Param->getIdentifier()) + Result += Param->getIdentifier()->getName(); Result += ")"; + Result += Params; + } else { + // Format as a block literal argument. + Result = '^' + Result; + Result += Params; + + if (Param->getIdentifier()) + Result += Param->getIdentifier()->getName(); } - if (Param->getIdentifier()) - Result += Param->getIdentifier()->getName(); - return Result; } @@ -2078,7 +2183,6 @@ static void AddFunctionParameterChunks(ASTContext &Context, CodeCompletionBuilder &Result, unsigned Start = 0, bool InOptional = false) { - typedef CodeCompletionString::Chunk Chunk; bool FirstParameter = true; for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) { @@ -2087,9 +2191,10 @@ static void AddFunctionParameterChunks(ASTContext &Context, if (Param->hasDefaultArg() && !InOptional) { // When we see an optional default argument, put that argument and // the remaining default arguments into a new, optional string. - CodeCompletionBuilder Opt(Result.getAllocator()); + CodeCompletionBuilder Opt(Result.getAllocator(), + Result.getCodeCompletionTUInfo()); if (!FirstParameter) - Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma)); + Opt.AddChunk(CodeCompletionString::CK_Comma); AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true); Result.AddOptionalChunk(Opt.TakeString()); break; @@ -2098,7 +2203,7 @@ static void AddFunctionParameterChunks(ASTContext &Context, if (FirstParameter) FirstParameter = false; else - Result.AddChunk(Chunk(CodeCompletionString::CK_Comma)); + Result.AddChunk(CodeCompletionString::CK_Comma); InOptional = false; @@ -2132,7 +2237,6 @@ static void AddTemplateParameterChunks(ASTContext &Context, unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) { - typedef CodeCompletionString::Chunk Chunk; bool FirstParameter = true; TemplateParameterList *Params = Template->getTemplateParameters(); @@ -2179,9 +2283,10 @@ static void AddTemplateParameterChunks(ASTContext &Context, if (HasDefaultArg && !InDefaultArg) { // When we see an optional default argument, put that argument and // the remaining default arguments into a new, optional string. - CodeCompletionBuilder Opt(Result.getAllocator()); + CodeCompletionBuilder Opt(Result.getAllocator(), + Result.getCodeCompletionTUInfo()); if (!FirstParameter) - Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma)); + Opt.AddChunk(CodeCompletionString::CK_Comma); AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters, P - Params->begin(), true); Result.AddOptionalChunk(Opt.TakeString()); @@ -2193,7 +2298,7 @@ static void AddTemplateParameterChunks(ASTContext &Context, if (FirstParameter) FirstParameter = false; else - Result.AddChunk(Chunk(CodeCompletionString::CK_Comma)); + Result.AddChunk(CodeCompletionString::CK_Comma); // Add the placeholder string. Result.AddPlaceholderChunk( @@ -2263,8 +2368,6 @@ AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, /// \brief Add the name of the given declaration static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, NamedDecl *ND, CodeCompletionBuilder &Result) { - typedef CodeCompletionString::Chunk Chunk; - DeclarationName Name = ND->getDeclName(); if (!Name) return; @@ -2326,15 +2429,21 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, Result.AddTypedTextChunk( Result.getAllocator().CopyString(Record->getNameAsString())); if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) { - Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle)); + Result.AddChunk(CodeCompletionString::CK_LeftAngle); AddTemplateParameterChunks(Context, Policy, Template, Result); - Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle)); + Result.AddChunk(CodeCompletionString::CK_RightAngle); } break; } } } +CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S, + CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo) { + return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo); +} + /// \brief If possible, create a new code completion string for the given /// result. /// @@ -2342,15 +2451,23 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, /// how to use this result, or NULL to indicate that the string or name of the /// result is all that is needed. CodeCompletionString * -CodeCompletionResult::CreateCodeCompletionString(Sema &S, - CodeCompletionAllocator &Allocator) { - typedef CodeCompletionString::Chunk Chunk; - CodeCompletionBuilder Result(Allocator, Priority, Availability); +CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, + Preprocessor &PP, + CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo) { + CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability); - PrintingPolicy Policy = getCompletionPrintingPolicy(S); + PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP); if (Kind == RK_Pattern) { Pattern->Priority = Priority; Pattern->Availability = Availability; + + if (Declaration) { + Result.addParentContext(Declaration->getDeclContext()); + Pattern->ParentKind = Result.getParentKind(); + Pattern->ParentName = Result.getParentName(); + } + return Pattern; } @@ -2360,7 +2477,7 @@ CodeCompletionResult::CreateCodeCompletionString(Sema &S, } if (Kind == RK_Macro) { - MacroInfo *MI = S.PP.getMacroInfo(Macro); + MacroInfo *MI = PP.getMacroInfo(Macro); assert(MI && "Not a macro?"); Result.AddTypedTextChunk( @@ -2370,54 +2487,44 @@ CodeCompletionResult::CreateCodeCompletionString(Sema &S, return Result.TakeString(); // Format a function-like macro with placeholders for the arguments. - Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); - bool CombineVariadicArgument = false; + Result.AddChunk(CodeCompletionString::CK_LeftParen); MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end(); - if (MI->isVariadic() && AEnd - A > 1) { - AEnd -= 2; - CombineVariadicArgument = true; + + // C99 variadic macros add __VA_ARGS__ at the end. Skip it. + if (MI->isC99Varargs()) { + --AEnd; + + if (A == AEnd) { + Result.AddPlaceholderChunk("..."); + } } + for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) { if (A != MI->arg_begin()) - Result.AddChunk(Chunk(CodeCompletionString::CK_Comma)); - - if (!MI->isVariadic() || A + 1 != AEnd) { - // Non-variadic argument. - Result.AddPlaceholderChunk( - Result.getAllocator().CopyString((*A)->getName())); - continue; - } - - // Variadic argument; cope with the difference between GNU and C99 - // variadic macros, providing a single placeholder for the rest of the - // arguments. - if ((*A)->isStr("__VA_ARGS__")) - Result.AddPlaceholderChunk("..."); - else { - std::string Arg = (*A)->getName(); - Arg += "..."; + Result.AddChunk(CodeCompletionString::CK_Comma); + + if (MI->isVariadic() && (A+1) == AEnd) { + SmallString<32> Arg = (*A)->getName(); + if (MI->isC99Varargs()) + Arg += ", ..."; + else + Arg += "..."; Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg)); + break; } + + // Non-variadic macros are simple. + Result.AddPlaceholderChunk( + Result.getAllocator().CopyString((*A)->getName())); } - - if (CombineVariadicArgument) { - // Handle the next-to-last argument, combining it with the variadic - // argument. - std::string LastArg = (*A)->getName(); - ++A; - if ((*A)->isStr("__VA_ARGS__")) - LastArg += ", ..."; - else - LastArg += ", " + (*A)->getName().str() + "..."; - Result.AddPlaceholderChunk(Result.getAllocator().CopyString(LastArg)); - } - Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen)); + Result.AddChunk(CodeCompletionString::CK_RightParen); return Result.TakeString(); } assert(Kind == RK_Declaration && "Missed a result kind?"); NamedDecl *ND = Declaration; - + Result.addParentContext(ND->getDeclContext()); + if (StartsNestedNameSpecifier) { Result.AddTypedTextChunk( Result.getAllocator().CopyString(ND->getNameAsString())); @@ -2431,29 +2538,29 @@ CodeCompletionResult::CreateCodeCompletionString(Sema &S, } } - AddResultTypeChunk(S.Context, Policy, ND, Result); + AddResultTypeChunk(Ctx, Policy, ND, Result); if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) { AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, - S.Context, Policy); - AddTypedNameChunk(S.Context, Policy, ND, Result); - Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); - AddFunctionParameterChunks(S.Context, Policy, Function, Result); - Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen)); + Ctx, Policy); + AddTypedNameChunk(Ctx, Policy, ND, Result); + Result.AddChunk(CodeCompletionString::CK_LeftParen); + AddFunctionParameterChunks(Ctx, Policy, Function, Result); + Result.AddChunk(CodeCompletionString::CK_RightParen); AddFunctionTypeQualsToCompletionString(Result, Function); return Result.TakeString(); } if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) { AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, - S.Context, Policy); + Ctx, Policy); FunctionDecl *Function = FunTmpl->getTemplatedDecl(); - AddTypedNameChunk(S.Context, Policy, Function, Result); + AddTypedNameChunk(Ctx, Policy, Function, Result); // Figure out which template parameters are deduced (or have default // arguments). - SmallVector<bool, 16> Deduced; - S.MarkDeducedTemplateParameters(FunTmpl, Deduced); + llvm::SmallBitVector Deduced; + Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced); unsigned LastDeducibleArgument; for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0; --LastDeducibleArgument) { @@ -2484,28 +2591,28 @@ CodeCompletionResult::CreateCodeCompletionString(Sema &S, // Some of the function template arguments cannot be deduced from a // function call, so we introduce an explicit template argument list // containing all of the arguments up to the first deducible argument. - Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle)); - AddTemplateParameterChunks(S.Context, Policy, FunTmpl, Result, + Result.AddChunk(CodeCompletionString::CK_LeftAngle); + AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result, LastDeducibleArgument); - Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle)); + Result.AddChunk(CodeCompletionString::CK_RightAngle); } // Add the function parameters - Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); - AddFunctionParameterChunks(S.Context, Policy, Function, Result); - Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen)); + Result.AddChunk(CodeCompletionString::CK_LeftParen); + AddFunctionParameterChunks(Ctx, Policy, Function, Result); + Result.AddChunk(CodeCompletionString::CK_RightParen); AddFunctionTypeQualsToCompletionString(Result, Function); return Result.TakeString(); } if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) { AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, - S.Context, Policy); + Ctx, Policy); Result.AddTypedTextChunk( Result.getAllocator().CopyString(Template->getNameAsString())); - Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle)); - AddTemplateParameterChunks(S.Context, Policy, Template, Result); - Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle)); + Result.AddChunk(CodeCompletionString::CK_LeftAngle); + AddTemplateParameterChunks(Ctx, Policy, Template, Result); + Result.AddChunk(CodeCompletionString::CK_RightAngle); return Result.TakeString(); } @@ -2553,7 +2660,7 @@ CodeCompletionResult::CreateCodeCompletionString(Sema &S, std::string Arg; if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity) - Arg = FormatFunctionParameter(S.Context, Policy, *P, true); + Arg = FormatFunctionParameter(Ctx, Policy, *P, true); else { (*P)->getType().getAsStringInternal(Arg, Policy); Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier()) @@ -2584,7 +2691,7 @@ CodeCompletionResult::CreateCodeCompletionString(Sema &S, Result.AddPlaceholderChunk(", ..."); } - MaybeAddSentinel(S.Context, Method, Result); + MaybeAddSentinel(Ctx, Method, Result); } return Result.TakeString(); @@ -2592,7 +2699,7 @@ CodeCompletionResult::CreateCodeCompletionString(Sema &S, if (Qualifier) AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, - S.Context, Policy); + Ctx, Policy); Result.AddTypedTextChunk( Result.getAllocator().CopyString(ND->getNameAsString())); @@ -2603,12 +2710,12 @@ CodeCompletionString * CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( unsigned CurrentArg, Sema &S, - CodeCompletionAllocator &Allocator) const { - typedef CodeCompletionString::Chunk Chunk; + CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo) const { PrintingPolicy Policy = getCompletionPrintingPolicy(S); // FIXME: Set priority, availability appropriately. - CodeCompletionBuilder Result(Allocator, 1, CXAvailability_Available); + CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available); FunctionDecl *FDecl = getFunction(); AddResultTypeChunk(S.Context, Policy, FDecl, Result); const FunctionProtoType *Proto @@ -2620,9 +2727,9 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(), S.Context, Policy, Result.getAllocator())); - Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); - Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "...")); - Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen)); + Result.AddChunk(CodeCompletionString::CK_LeftParen); + Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "..."); + Result.AddChunk(CodeCompletionString::CK_RightParen); return Result.TakeString(); } @@ -2634,11 +2741,11 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( Result.getAllocator().CopyString( Proto->getResultType().getAsString(Policy))); - Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); + Result.AddChunk(CodeCompletionString::CK_LeftParen); unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs(); for (unsigned I = 0; I != NumParams; ++I) { if (I) - Result.AddChunk(Chunk(CodeCompletionString::CK_Comma)); + Result.AddChunk(CodeCompletionString::CK_Comma); std::string ArgString; QualType ArgType; @@ -2653,20 +2760,20 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( ArgType.getAsStringInternal(ArgString, Policy); if (I == CurrentArg) - Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, - Result.getAllocator().CopyString(ArgString))); + Result.AddChunk(CodeCompletionString::CK_CurrentParameter, + Result.getAllocator().CopyString(ArgString)); else Result.AddTextChunk(Result.getAllocator().CopyString(ArgString)); } if (Proto && Proto->isVariadic()) { - Result.AddChunk(Chunk(CodeCompletionString::CK_Comma)); + Result.AddChunk(CodeCompletionString::CK_Comma); if (CurrentArg < NumParams) Result.AddTextChunk("..."); else - Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "...")); + Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "..."); } - Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen)); + Result.AddChunk(CodeCompletionString::CK_RightParen); return Result.TakeString(); } @@ -2707,13 +2814,8 @@ CXCursorKind clang::getCursorKindForDecl(Decl *D) { return CXCursor_FunctionDecl; case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl; case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl; - case Decl::ObjCClass: - // FIXME - return CXCursor_UnexposedDecl; - case Decl::ObjCForwardProtocol: - // FIXME - return CXCursor_UnexposedDecl; case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl; + case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl; case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl; case Decl::ObjCMethod: @@ -2754,7 +2856,6 @@ CXCursorKind clang::getCursorKindForDecl(Decl *D) { case ObjCPropertyImplDecl::Synthesize: return CXCursor_ObjCSynthesizeDecl; } - break; default: if (TagDecl *TD = dyn_cast<TagDecl>(D)) { @@ -2781,7 +2882,7 @@ static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, M != MEnd; ++M) { Results.AddResult(Result(M->first, getMacroUsagePriority(M->first->getName(), - PP.getLangOptions(), + PP.getLangOpts(), TargetTypeIsPointer))); } @@ -2833,17 +2934,16 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, case Sema::PCC_MemberTemplate: if (S.CurContext->isFileContext()) return CodeCompletionContext::CCC_TopLevel; - else if (S.CurContext->isRecord()) + if (S.CurContext->isRecord()) return CodeCompletionContext::CCC_ClassStructUnion; - else - return CodeCompletionContext::CCC_Other; + return CodeCompletionContext::CCC_Other; case Sema::PCC_RecoveryInFunction: return CodeCompletionContext::CCC_Recovery; case Sema::PCC_ForInit: - if (S.getLangOptions().CPlusPlus || S.getLangOptions().C99 || - S.getLangOptions().ObjC1) + if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 || + S.getLangOpts().ObjC1) return CodeCompletionContext::CCC_ParenthesizedExpression; else return CodeCompletionContext::CCC_Expression; @@ -2864,8 +2964,8 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, case Sema::PCC_LocalDeclarationSpecifiers: return CodeCompletionContext::CCC_Type; } - - return CodeCompletionContext::CCC_Other; + + llvm_unreachable("Invalid ParserCompletionContext!"); } /// \brief If we're in a C++ virtual member function, add completion results @@ -2902,7 +3002,8 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(), MEnd = Method->end_overridden_methods(); M != MEnd; ++M) { - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M); if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl()) continue; @@ -2939,15 +3040,70 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, Builder.AddChunk(CodeCompletionString::CK_RightParen); Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion, - CXCursor_CXXMethod)); + CXCursor_CXXMethod, + CXAvailability_Available, + Overridden)); Results.Ignore(Overridden); } } +void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, + ModuleIdPath Path) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + + CodeCompletionAllocator &Allocator = Results.getAllocator(); + CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); + typedef CodeCompletionResult Result; + if (Path.empty()) { + // Enumerate all top-level modules. + llvm::SmallVector<Module *, 8> Modules; + PP.getHeaderSearchInfo().collectAllModules(Modules); + for (unsigned I = 0, N = Modules.size(); I != N; ++I) { + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString(Modules[I]->Name)); + Results.AddResult(Result(Builder.TakeString(), + CCP_Declaration, + CXCursor_NotImplemented, + Modules[I]->isAvailable() + ? CXAvailability_Available + : CXAvailability_NotAvailable)); + } + } else { + // Load the named module. + Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path, + Module::AllVisible, + /*IsInclusionDirective=*/false); + // Enumerate submodules. + if (Mod) { + for (Module::submodule_iterator Sub = Mod->submodule_begin(), + SubEnd = Mod->submodule_end(); + Sub != SubEnd; ++Sub) { + + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString((*Sub)->Name)); + Results.AddResult(Result(Builder.TakeString(), + CCP_Declaration, + CXCursor_NotImplemented, + (*Sub)->isAvailable() + ? CXAvailability_Available + : CXAvailability_NotAvailable)); + } + } + } + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(),Results.size()); +} + void Sema::CodeCompleteOrdinaryName(Scope *S, ParserCompletionContext CompletionContext) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), mapCodeCompletionContext(*this, CompletionContext)); Results.EnterNewScope(); @@ -2972,12 +3128,12 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, case PCC_Expression: case PCC_ForInit: case PCC_Condition: - if (WantTypesInContext(CompletionContext, getLangOptions())) + if (WantTypesInContext(CompletionContext, getLangOpts())) Results.setFilter(&ResultBuilder::IsOrdinaryName); else Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); - if (getLangOptions().CPlusPlus) + if (getLangOpts().CPlusPlus) MaybeAddOverrideCalls(*this, /*InContext=*/0, Results); break; @@ -3006,7 +3162,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, case PCC_Statement: case PCC_RecoveryInFunction: if (S->getFnParent()) - AddPrettyFunctionResults(PP.getLangOptions(), Results); + AddPrettyFunctionResults(PP.getLangOpts(), Results); break; case PCC_Namespace: @@ -3043,6 +3199,7 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, bool AllowNestedNameSpecifiers) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), AllowNestedNameSpecifiers ? CodeCompletionContext::CCC_PotentiallyQualifiedName : CodeCompletionContext::CCC_Name); @@ -3051,10 +3208,10 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, // Type qualifiers can come after names. Results.AddResult(Result("const")); Results.AddResult(Result("volatile")); - if (getLangOptions().C99) + if (getLangOpts().C99) Results.AddResult(Result("restrict")); - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { if (AllowNonIdentifiers) { Results.AddResult(Result("operator")); } @@ -3120,12 +3277,13 @@ void Sema::CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData &Data) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Expression); if (Data.ObjCCollection) Results.setFilter(&ResultBuilder::IsObjCCollection); else if (Data.IntegralConstantExpression) Results.setFilter(&ResultBuilder::IsIntegralConstantValue); - else if (WantTypesInContext(PCC_Expression, getLangOptions())) + else if (WantTypesInContext(PCC_Expression, getLangOpts())) Results.setFilter(&ResultBuilder::IsOrdinaryName); else Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); @@ -3154,7 +3312,7 @@ void Sema::CodeCompleteExpression(Scope *S, if (S->getFnParent() && !Data.ObjCCollection && !Data.IntegralConstantExpression) - AddPrettyFunctionResults(PP.getLangOptions(), Results); + AddPrettyFunctionResults(PP.getLangOpts(), Results); if (CodeCompleter->includeMacros()) AddMacroResults(PP, Results, PreferredTypeIsPointer); @@ -3167,7 +3325,7 @@ void Sema::CodeCompleteExpression(Scope *S, void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) { if (E.isInvalid()) CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction); - else if (getLangOptions().ObjC1) + else if (getLangOpts().ObjC1) CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false); } @@ -3202,33 +3360,14 @@ static void AddObjCProperties(ObjCContainerDecl *Container, if (M->getSelector().isUnarySelector()) if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0)) if (AddedProperties.insert(Name)) { - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); AddResultTypeChunk(Context, Policy, *M, Builder); Builder.AddTypedTextChunk( Results.getAllocator().CopyString(Name->getName())); - CXAvailabilityKind Availability = CXAvailability_Available; - switch (M->getAvailability()) { - case AR_Available: - case AR_NotYetIntroduced: - Availability = CXAvailability_Available; - break; - - case AR_Deprecated: - Availability = CXAvailability_Deprecated; - break; - - case AR_Unavailable: - Availability = CXAvailability_NotAvailable; - break; - } - - Results.MaybeAddResult(Result(Builder.TakeString(), - CCP_MemberDeclaration + CCD_MethodAsProperty, - M->isInstanceMethod() - ? CXCursor_ObjCInstanceMethodDecl - : CXCursor_ObjCClassMethodDecl, - Availability), + Results.MaybeAddResult(Result(Builder.TakeString(), *M, + CCP_MemberDeclaration + CCD_MethodAsProperty), CurContext); } } @@ -3274,15 +3413,19 @@ static void AddObjCProperties(ObjCContainerDecl *Container, } } -void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *BaseE, +void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, SourceLocation OpLoc, bool IsArrow) { - if (!BaseE || !CodeCompleter) + if (!Base || !CodeCompleter) return; + ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow); + if (ConvertedBase.isInvalid()) + return; + Base = ConvertedBase.get(); + typedef CodeCompletionResult Result; - Expr *Base = static_cast<Expr *>(BaseE); QualType BaseType = Base->getType(); if (IsArrow) { @@ -3310,6 +3453,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *BaseE, } ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext(contextKind, BaseType), &ResultBuilder::IsMember); @@ -3325,7 +3469,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *BaseE, LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer, CodeCompleter->includeGlobals()); - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { if (!Results.empty()) { // The "template" keyword can follow "->" or "." in the grammar. // However, we only want to suggest the template keyword if something @@ -3419,7 +3563,8 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { llvm_unreachable("Unknown type specifier kind in CodeCompleteTag"); } - ResultBuilder Results(*this, CodeCompleter->getAllocator(), ContextKind); + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), ContextKind); CodeCompletionDeclConsumer Consumer(Results, CurContext); // First pass: look for tags. @@ -3439,13 +3584,14 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_TypeQualifiers); Results.EnterNewScope(); if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const)) Results.AddResult("const"); if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile)) Results.AddResult("volatile"); - if (getLangOptions().C99 && + if (getLangOpts().C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict)) Results.AddResult("restrict"); Results.ExitScope(); @@ -3510,18 +3656,16 @@ void Sema::CodeCompleteCase(Scope *S) { } } - if (getLangOptions().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) { + if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) { // If there are no prior enumerators in C++, check whether we have to // qualify the names of the enumerators that we suggest, because they // may not be visible in this scope. - Qualifier = getRequiredQualification(Context, CurContext, - Enum->getDeclContext()); - - // FIXME: Scoped enums need to start with "EnumDecl" as the context! + Qualifier = getRequiredQualification(Context, CurContext, Enum); } // Add any enumerators that have not yet been mentioned. ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Expression); Results.EnterNewScope(); for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(), @@ -3544,7 +3688,6 @@ void Sema::CodeCompleteCase(Scope *S) { kind = CodeCompletionContext::CCC_OtherWithMacros; } - HandleCodeCompleteResults(this, CodeCompleter, kind, Results.data(),Results.size()); @@ -3566,19 +3709,19 @@ namespace { }; } -static bool anyNullArguments(Expr **Args, unsigned NumArgs) { - if (NumArgs && !Args) +static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) { + if (Args.size() && !Args.data()) return true; - - for (unsigned I = 0; I != NumArgs; ++I) + + for (unsigned I = 0; I != Args.size(); ++I) if (!Args[I]) return true; - + return false; } void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, - Expr **ArgsIn, unsigned NumArgs) { + llvm::ArrayRef<Expr *> Args) { if (!CodeCompleter) return; @@ -3588,11 +3731,10 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, // e.g., by merging the two kinds of results. Expr *Fn = (Expr *)FnIn; - Expr **Args = (Expr **)ArgsIn; // Ignore type-dependent call expressions entirely. - if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args, NumArgs) || - Expr::hasAnyTypeDependentArguments(Args, NumArgs)) { + if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) || + Expr::hasAnyTypeDependentArguments(Args)) { CodeCompleteOrdinaryName(S, PCC_Expression); return; } @@ -3610,19 +3752,18 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, Expr *NakedFn = Fn->IgnoreParenCasts(); if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) - AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet, + AddOverloadedCallCandidates(ULE, Args, CandidateSet, /*PartialOverloading=*/ true); else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) { FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl()); if (FDecl) { - if (!getLangOptions().CPlusPlus || + if (!getLangOpts().CPlusPlus || !FDecl->getType()->getAs<FunctionProtoType>()) Results.push_back(ResultCandidate(FDecl)); else // FIXME: access? - AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), - Args, NumArgs, CandidateSet, - false, /*PartialOverloading*/true); + AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args, + CandidateSet, false, /*PartialOverloading*/true); } } @@ -3645,12 +3786,12 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, 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 (NumArgs < Proto->getNumArgs()) { + if (Args.size() < Proto->getNumArgs()) { if (ParamType.isNull()) - ParamType = Proto->getArgType(NumArgs); + ParamType = Proto->getArgType(Args.size()); else if (!Context.hasSameUnqualifiedType( ParamType.getNonReferenceType(), - Proto->getArgType(NumArgs).getNonReferenceType())) { + Proto->getArgType(Args.size()).getNonReferenceType())) { ParamType = QualType(); break; } @@ -3671,8 +3812,8 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, if (const FunctionProtoType *Proto = FunctionType->getAs<FunctionProtoType>()) { - if (NumArgs < Proto->getNumArgs()) - ParamType = Proto->getArgType(NumArgs); + if (Args.size() < Proto->getNumArgs()) + ParamType = Proto->getArgType(Args.size()); } } @@ -3682,7 +3823,7 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, CodeCompleteExpression(S, ParamType); if (!Results.empty()) - CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(), + CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(), Results.size()); } @@ -3715,6 +3856,7 @@ void Sema::CodeCompleteReturn(Scope *S) { void Sema::CodeCompleteAfterIf(Scope *S) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), mapCodeCompletionContext(*this, PCC_Statement)); Results.setFilter(&ResultBuilder::IsOrdinaryName); Results.EnterNewScope(); @@ -3726,14 +3868,17 @@ void Sema::CodeCompleteAfterIf(Scope *S) { AddOrdinaryNameResults(PCC_Statement, S, *this, Results); // "else" block - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); Builder.AddTypedTextChunk("else"); - Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); - Builder.AddChunk(CodeCompletionString::CK_LeftBrace); - Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); - Builder.AddPlaceholderChunk("statements"); - Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); - Builder.AddChunk(CodeCompletionString::CK_RightBrace); + if (Results.includeCodePatterns()) { + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + } Results.AddResult(Builder.TakeString()); // "else if" block @@ -3742,23 +3887,25 @@ void Sema::CodeCompleteAfterIf(Scope *S) { Builder.AddTextChunk("if"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddChunk(CodeCompletionString::CK_LeftParen); - if (getLangOptions().CPlusPlus) + if (getLangOpts().CPlusPlus) Builder.AddPlaceholderChunk("condition"); else Builder.AddPlaceholderChunk("expression"); Builder.AddChunk(CodeCompletionString::CK_RightParen); - Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); - Builder.AddChunk(CodeCompletionString::CK_LeftBrace); - Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); - Builder.AddPlaceholderChunk("statements"); - Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); - Builder.AddChunk(CodeCompletionString::CK_RightBrace); + if (Results.includeCodePatterns()) { + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + } Results.AddResult(Builder.TakeString()); Results.ExitScope(); if (S->getFnParent()) - AddPrettyFunctionResults(PP.getLangOptions(), Results); + AddPrettyFunctionResults(PP.getLangOpts(), Results); if (CodeCompleter->includeMacros()) AddMacroResults(PP, Results); @@ -3789,6 +3936,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, return; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Name); Results.EnterNewScope(); @@ -3820,6 +3968,7 @@ void Sema::CodeCompleteUsing(Scope *S) { return; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_PotentiallyQualifiedName, &ResultBuilder::IsNestedNameSpecifier); Results.EnterNewScope(); @@ -3847,6 +3996,7 @@ void Sema::CodeCompleteUsingDirective(Scope *S) { // After "using namespace", we expect to see a namespace name or namespace // alias. ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Namespace, &ResultBuilder::IsNamespaceOrAlias); Results.EnterNewScope(); @@ -3871,6 +4021,7 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx); ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), SuppressedGlobalResults ? CodeCompletionContext::CCC_Namespace : CodeCompletionContext::CCC_Other, @@ -3891,7 +4042,8 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { // namespace to the list of results. Results.EnterNewScope(); for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator - NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end(); + NS = OrigToLatest.begin(), + NSEnd = OrigToLatest.end(); NS != NSEnd; ++NS) Results.AddResult(CodeCompletionResult(NS->second, 0), CurContext, 0, false); @@ -3909,6 +4061,7 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { // After "namespace", we expect to see a namespace or alias. ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Namespace, &ResultBuilder::IsNamespaceOrAlias); CodeCompletionDeclConsumer Consumer(Results, CurContext); @@ -3925,6 +4078,7 @@ void Sema::CodeCompleteOperatorName(Scope *S) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Type, &ResultBuilder::IsType); Results.EnterNewScope(); @@ -3942,7 +4096,7 @@ void Sema::CodeCompleteOperatorName(Scope *S) { CodeCompleter->includeGlobals()); // Add any type specifiers - AddTypeSpecifierResults(getLangOptions(), Results); + AddTypeSpecifierResults(getLangOpts(), Results); Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, @@ -3960,6 +4114,7 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, return; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_PotentiallyQualifiedName); Results.EnterNewScope(); @@ -3976,7 +4131,8 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, } // Add completions for base classes. - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); bool SawLastInitializer = (NumInitializers == 0); CXXRecordDecl *ClassDecl = Constructor->getParent(); for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), @@ -4051,7 +4207,9 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, Results.AddResult(CodeCompletionResult(Builder.TakeString(), SawLastInitializer? CCP_NextInitializer : CCP_MemberDeclaration, - CXCursor_MemberRef)); + CXCursor_MemberRef, + CXAvailability_Available, + *Field)); SawLastInitializer = false; } Results.ExitScope(); @@ -4060,6 +4218,61 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, Results.data(), Results.size()); } +/// \brief Determine whether this scope denotes a namespace. +static bool isNamespaceScope(Scope *S) { + DeclContext *DC = static_cast<DeclContext *>(S->getEntity()); + if (!DC) + return false; + + return DC->isFileContext(); +} + +void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, + bool AfterAmpersand) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + + // 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) { + IncludedThis = true; + continue; + } + + 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); + if (!Var || + !Var->hasLocalStorage() || + Var->hasAttr<BlocksAttr>()) + continue; + + if (Known.insert(Var->getIdentifier())) + Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false); + } + } + + // Add 'this', if it would be valid. + if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy) + addThisCompletion(*this, Results); + + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); +} + // Macro that expands to @Keyword or Keyword, depending on whether NeedAt is // true or false. #define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword @@ -4070,7 +4283,8 @@ static void AddObjCImplementationResults(const LangOptions &LangOpts, // Since we have an implementation, we can end it. Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end))); - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); if (LangOpts.ObjC2) { // @dynamic Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic)); @@ -4108,7 +4322,8 @@ static void AddObjCInterfaceResults(const LangOptions &LangOpts, static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { typedef CodeCompletionResult Result; - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); // @class name ; Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class)); @@ -4150,12 +4365,13 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { void Sema::CodeCompleteObjCAtDirective(Scope *S) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); if (isa<ObjCImplDecl>(CurContext)) - AddObjCImplementationResults(getLangOptions(), Results, false); + AddObjCImplementationResults(getLangOpts(), Results, false); else if (CurContext->isObjCContainer()) - AddObjCInterfaceResults(getLangOptions(), Results, false); + AddObjCInterfaceResults(getLangOpts(), Results, false); else AddObjCTopLevelResults(Results, false); Results.ExitScope(); @@ -4166,9 +4382,15 @@ void Sema::CodeCompleteObjCAtDirective(Scope *S) { static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { typedef CodeCompletionResult Result; - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); // @encode ( type-name ) + const char *EncodeType = "char[]"; + if (Results.getSema().getLangOpts().CPlusPlus || + Results.getSema().getLangOpts().ConstStrings) + EncodeType = " const char[]"; + Builder.AddResultTypeChunk(EncodeType); Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode)); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("type-name"); @@ -4176,6 +4398,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { Results.AddResult(Result(Builder.TakeString())); // @protocol ( protocol-name ) + Builder.AddResultTypeChunk("Protocol *"); Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol)); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("protocol-name"); @@ -4183,16 +4406,38 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { Results.AddResult(Result(Builder.TakeString())); // @selector ( selector ) + Builder.AddResultTypeChunk("SEL"); Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector)); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("selector"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Results.AddResult(Result(Builder.TakeString())); + + // @[ objects, ... ] + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,[)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("objects, ..."); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBracket); + Results.AddResult(Result(Builder.TakeString())); + + // @{ key : object, ... } + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,{)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("key"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_Colon); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("object, ..."); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); } static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { typedef CodeCompletionResult Result; - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); if (Results.includeCodePatterns()) { // @try { statements } @catch ( declaration ) { statements } @finally @@ -4248,9 +4493,10 @@ static void AddObjCVisibilityResults(const LangOptions &LangOpts, void Sema::CodeCompleteObjCAtVisibility(Scope *S) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); - AddObjCVisibilityResults(getLangOptions(), Results, false); + AddObjCVisibilityResults(getLangOpts(), Results, false); Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, CodeCompletionContext::CCC_Other, @@ -4259,6 +4505,7 @@ void Sema::CodeCompleteObjCAtVisibility(Scope *S) { void Sema::CodeCompleteObjCAtStatement(Scope *S) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); AddObjCStatementResults(Results, false); @@ -4271,6 +4518,7 @@ void Sema::CodeCompleteObjCAtStatement(Scope *S) { void Sema::CodeCompleteObjCAtExpression(Scope *S) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); AddObjCExpressionResults(Results, false); @@ -4324,6 +4572,7 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly)) @@ -4346,14 +4595,16 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic)) Results.AddResult(CodeCompletionResult("atomic")); if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) { - CodeCompletionBuilder Setter(Results.getAllocator()); + CodeCompletionBuilder Setter(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); Setter.AddTypedTextChunk("setter"); Setter.AddTextChunk(" = "); Setter.AddPlaceholderChunk("method"); Results.AddResult(CodeCompletionResult(Setter.TakeString())); } if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) { - CodeCompletionBuilder Getter(Results.getAllocator()); + CodeCompletionBuilder Getter(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); Getter.AddTypedTextChunk("getter"); Getter.AddTextChunk(" = "); Getter.AddPlaceholderChunk("method"); @@ -4467,23 +4718,25 @@ static void AddObjCMethods(ObjCContainerDecl *Container, // Visit the protocols of protocols. if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { - const ObjCList<ObjCProtocolDecl> &Protocols - = Protocol->getReferencedProtocols(); - for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), - E = Protocols.end(); - I != E; ++I) - AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents, - CurContext, Selectors, AllowSameLength, Results, false); + if (Protocol->hasDefinition()) { + const ObjCList<ObjCProtocolDecl> &Protocols + = Protocol->getReferencedProtocols(); + for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, + NumSelIdents, CurContext, Selectors, AllowSameLength, + Results, false); + } } ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container); - if (!IFace) + if (!IFace || !IFace->hasDefinition()) return; // Add methods in protocols. - const ObjCList<ObjCProtocolDecl> &Protocols= IFace->getReferencedProtocols(); - for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), - E = Protocols.end(); + for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(), + E = IFace->protocol_end(); I != E; ++I) AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents, CurContext, Selectors, AllowSameLength, Results, false); @@ -4542,6 +4795,7 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S) { // Find all of the potential getters. ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); @@ -4571,6 +4825,7 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S) { // Find all of the potential getters. ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); @@ -4588,6 +4843,7 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, bool IsParameter) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Type); Results.EnterNewScope(); @@ -4619,16 +4875,16 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, // IBAction)<#selector#>:(id)sender if (DS.getObjCDeclQualifier() == 0 && !IsParameter && Context.Idents.get("IBAction").hasMacroDefinition()) { - typedef CodeCompletionString::Chunk Chunk; - CodeCompletionBuilder Builder(Results.getAllocator(), CCP_CodePattern, - CXAvailability_Available); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo(), + CCP_CodePattern, CXAvailability_Available); Builder.AddTypedTextChunk("IBAction"); - Builder.AddChunk(Chunk(CodeCompletionString::CK_RightParen)); + Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddPlaceholderChunk("selector"); - Builder.AddChunk(Chunk(CodeCompletionString::CK_Colon)); - Builder.AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); + Builder.AddChunk(CodeCompletionString::CK_Colon); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddTextChunk("id"); - Builder.AddChunk(Chunk(CodeCompletionString::CK_RightParen)); + Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("sender"); Results.AddResult(CodeCompletionResult(Builder.TakeString())); } @@ -4792,7 +5048,8 @@ static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword, } // We have a superclass method. Now, form the send-to-super completion. - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); // Give this completion a return type. AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod, @@ -4838,18 +5095,19 @@ static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword, } } - Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion, - SuperMethod->isInstanceMethod() - ? CXCursor_ObjCInstanceMethodDecl - : CXCursor_ObjCClassMethodDecl)); + Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod, + CCP_SuperCompletion)); return SuperMethod; } void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCMessageReceiver, - &ResultBuilder::IsObjCMessageReceiver); + getLangOpts().CPlusPlus0x + ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture + : &ResultBuilder::IsObjCMessageReceiver); CodeCompletionDeclConsumer Consumer(Results, CurContext); Results.EnterNewScope(); @@ -4866,6 +5124,9 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results); } + if (getLangOpts().CPlusPlus0x) + addThisCompletion(*this, Results); + Results.ExitScope(); if (CodeCompleter->includeMacros()) @@ -4919,9 +5180,11 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, } else { // Assume that "super" names some kind of value and parse that way. CXXScopeSpec SS; + SourceLocation TemplateKWLoc; UnqualifiedId id; id.setIdentifier(Super, SuperLoc); - ExprResult SuperExpr = ActOnIdExpression(S, SS, id, false, false); + ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id, + false, false); return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(), SelIdents, NumSelIdents, AtArgumentExpression); @@ -5061,6 +5324,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, QualType T = this->GetTypeFromParser(Receiver); ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T, SelIdents, NumSelIdents)); @@ -5126,6 +5390,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, // Build the set of methods we can see. ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage, ReceiverType, SelIdents, NumSelIdents)); @@ -5277,6 +5542,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents, } ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_SelectorName); Results.EnterNewScope(); for (GlobalMethodPool::iterator M = MethodPool.begin(), @@ -5287,7 +5553,8 @@ void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents, if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents)) continue; - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); if (Sel.isUnarySelector()) { Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Sel.getNameForSlot(0))); @@ -5330,25 +5597,15 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, D != DEnd; ++D) { // Record any protocols we find. if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D)) - if (!OnlyForwardDeclarations || Proto->isForwardDecl()) + if (!OnlyForwardDeclarations || !Proto->hasDefinition()) Results.AddResult(Result(Proto, 0), CurContext, 0, false); - - // Record any forward-declared protocols we find. - if (ObjCForwardProtocolDecl *Forward - = dyn_cast<ObjCForwardProtocolDecl>(*D)) { - for (ObjCForwardProtocolDecl::protocol_iterator - P = Forward->protocol_begin(), - PEnd = Forward->protocol_end(); - P != PEnd; ++P) - if (!OnlyForwardDeclarations || (*P)->isForwardDecl()) - Results.AddResult(Result(*P, 0), CurContext, 0, false); - } } } void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, unsigned NumProtocols) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCProtocolName); if (CodeCompleter && CodeCompleter->includeGlobals()) { @@ -5376,6 +5633,7 @@ void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, void Sema::CodeCompleteObjCProtocolDecl(Scope *) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCProtocolName); if (CodeCompleter && CodeCompleter->includeGlobals()) { @@ -5406,23 +5664,15 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, D != DEnd; ++D) { // Record any interfaces we find. if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D)) - if ((!OnlyForwardDeclarations || Class->isForwardDecl()) && + if ((!OnlyForwardDeclarations || !Class->hasDefinition()) && (!OnlyUnimplemented || !Class->getImplementation())) Results.AddResult(Result(Class, 0), CurContext, 0, false); - - // Record any forward-declared interfaces we find. - if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) { - ObjCInterfaceDecl *IDecl = Forward->getForwardInterfaceDecl(); - if ((!OnlyForwardDeclarations || IDecl->isForwardDecl()) && - (!OnlyUnimplemented || !IDecl->getImplementation())) - Results.AddResult(Result(IDecl, 0), CurContext, - 0, false); - } } } void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); @@ -5442,6 +5692,7 @@ void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) { void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, SourceLocation ClassNameLoc) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCInterfaceName); Results.EnterNewScope(); @@ -5466,6 +5717,7 @@ void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, void Sema::CodeCompleteObjCImplementationDecl(Scope *S) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); @@ -5488,6 +5740,7 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCCategoryName); // Ignore any categories we find that have already been implemented by this @@ -5531,6 +5784,7 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S, return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc); ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCCategoryName); // Add all of the categories that have have corresponding interface @@ -5559,6 +5813,7 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S, void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); // Figure out where this @synthesize lives. @@ -5599,6 +5854,7 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, IdentifierInfo *PropertyName) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); // Figure out where this @synthesize lives. @@ -5668,7 +5924,8 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, unsigned Priority = CCP_MemberDeclaration + 1; typedef CodeCompletionResult Result; CodeCompletionAllocator &Allocator = Results.getAllocator(); - CodeCompletionBuilder Builder(Allocator, Priority,CXAvailability_Available); + CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(), + Priority,CXAvailability_Available); PrintingPolicy Policy = getCompletionPrintingPolicy(*this); Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context, @@ -5702,6 +5959,9 @@ static void FindImplementableMethods(ASTContext &Context, bool InOriginalClass = true) { if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) { // Recurse into protocols. + if (!IFace->hasDefinition()) + return; + const ObjCList<ObjCProtocolDecl> &Protocols = IFace->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), @@ -5742,14 +6002,16 @@ static void FindImplementableMethods(ASTContext &Context, } if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { - // Recurse into protocols. - const ObjCList<ObjCProtocolDecl> &Protocols - = Protocol->getReferencedProtocols(); - for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), - E = Protocols.end(); - I != E; ++I) - FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, - KnownMethods, false); + if (Protocol->hasDefinition()) { + // Recurse into protocols. + const ObjCList<ObjCProtocolDecl> &Protocols + = Protocol->getReferencedProtocols(); + for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, + KnownMethods, false); + } } // Add methods in this container. This operation occurs last because @@ -5771,10 +6033,14 @@ static void FindImplementableMethods(ASTContext &Context, /// \brief Add the parenthesized return or parameter type chunk to a code /// completion string. static void AddObjCPassingTypeChunk(QualType Type, + unsigned ObjCDeclQuals, ASTContext &Context, const PrintingPolicy &Policy, CodeCompletionBuilder &Builder) { Builder.AddChunk(CodeCompletionString::CK_LeftParen); + std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals); + if (!Quals.empty()) + Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals)); Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator())); Builder.AddChunk(CodeCompletionString::CK_RightParen); @@ -5810,7 +6076,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // Builder that will create each code completion. typedef CodeCompletionResult Result; CodeCompletionAllocator &Allocator = Results.getAllocator(); - CodeCompletionBuilder Builder(Allocator); + CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); // The selector table. SelectorTable &Selectors = Context.Selectors; @@ -5849,7 +6115,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, KnownSelectors.insert(Selectors.getNullarySelector(PropName)) && ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) { if (ReturnType.isNull()) - AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder); + AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, + Context, Policy, Builder); Builder.AddTypedTextChunk(Key); Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, @@ -5895,7 +6162,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTypedTextChunk( Allocator.CopyString(SelectorId->getName())); Builder.AddTypedTextChunk(":"); - AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder); + AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, + Context, Policy, Builder); Builder.AddTextChunk(Key); Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, CXCursor_ObjCInstanceMethodDecl)); @@ -6464,6 +6732,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, // Add declarations or definitions for each of the known methods. typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); PrintingPolicy Policy = getCompletionPrintingPolicy(*this); @@ -6471,13 +6740,16 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, MEnd = KnownMethods.end(); M != MEnd; ++M) { ObjCMethodDecl *Method = M->second.first; - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); // If the result type was not already provided, add it to the // pattern as (type). if (ReturnType.isNull()) - AddObjCPassingTypeChunk(Method->getResultType(), Context, Policy, - Builder); + AddObjCPassingTypeChunk(Method->getResultType(), + Method->getObjCDeclQualifier(), + Context, Policy, + Builder); Selector Sel = Method->getSelector(); @@ -6501,7 +6773,9 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, break; // Add the parameter type. - AddObjCPassingTypeChunk((*P)->getOriginalType(), Context, Policy, + AddObjCPassingTypeChunk((*P)->getOriginalType(), + (*P)->getObjCDeclQualifier(), + Context, Policy, Builder); if (IdentifierInfo *Id = (*P)->getIdentifier()) @@ -6536,15 +6810,12 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, if (!M->second.second) Priority += CCD_InBaseClass; - Results.AddResult(Result(Builder.TakeString(), Priority, - Method->isInstanceMethod() - ? CXCursor_ObjCInstanceMethodDecl - : CXCursor_ObjCClassMethodDecl)); + Results.AddResult(Result(Builder.TakeString(), Method, Priority)); } // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of // the properties in this class and its categories. - if (Context.getLangOptions().ObjC2) { + if (Context.getLangOpts().ObjC2) { SmallVector<ObjCContainerDecl *, 4> Containers; Containers.push_back(SearchDecl); @@ -6605,6 +6876,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, // Build the set of methods we can see. typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); if (ReturnTy) @@ -6627,7 +6899,8 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) { ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1]; if (Param->getIdentifier()) { - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Param->getIdentifier()->getName())); Results.AddResult(Builder.TakeString()); @@ -6653,11 +6926,13 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, void Sema::CodeCompletePreprocessorDirective(bool InConditional) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_PreprocessorDirective); Results.EnterNewScope(); // #if <condition> - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); Builder.AddTypedTextChunk("if"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("condition"); @@ -6756,7 +7031,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { Builder.AddPlaceholderChunk("arguments"); Results.AddResult(Builder.TakeString()); - if (getLangOptions().ObjC1) { + if (getLangOpts().ObjC1) { // #import "header" Builder.AddTypedTextChunk("import"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -6816,11 +7091,13 @@ void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) { void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), IsDefinition? CodeCompletionContext::CCC_MacroName : CodeCompletionContext::CCC_MacroNameUse); if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) { // Add just the names of macros, not their arguments. - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); Results.EnterNewScope(); for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end(); @@ -6840,6 +7117,7 @@ void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) { void Sema::CodeCompletePreprocessorExpression() { ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_PreprocessorExpression); if (!CodeCompleter || CodeCompleter->includeMacros()) @@ -6847,7 +7125,8 @@ void Sema::CodeCompletePreprocessorExpression() { // defined (<macro>) Results.EnterNewScope(); - CodeCompletionBuilder Builder(Results.getAllocator()); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); Builder.AddTypedTextChunk("defined"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddChunk(CodeCompletionString::CK_LeftParen); @@ -6879,8 +7158,10 @@ void Sema::CodeCompleteNaturalLanguage() { } void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo, SmallVectorImpl<CodeCompletionResult> &Results) { - ResultBuilder Builder(*this, Allocator, CodeCompletionContext::CCC_Recovery); + ResultBuilder Builder(*this, Allocator, CCTUInfo, + CodeCompletionContext::CCC_Recovery); if (!CodeCompleter || CodeCompleter->includeGlobals()) { CodeCompletionDeclConsumer Consumer(Builder, Context.getTranslationUnitDecl()); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaConsumer.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaConsumer.cpp new file mode 100644 index 0000000..d83a13e --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaConsumer.cpp @@ -0,0 +1,14 @@ +//===-- SemaConsumer.cpp - Abstract interface for AST semantics -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaConsumer.h" + +using namespace clang; + +void SemaConsumer::anchor() { } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp index d90a821..8b314b5 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp @@ -18,7 +18,6 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "TypeLocBuilder.h" -#include "clang/AST/APValue.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" @@ -40,6 +39,7 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/ModuleLoader.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/Triple.h" #include <algorithm> #include <cstring> @@ -56,6 +56,30 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType) { return DeclGroupPtrTy::make(DeclGroupRef(Ptr)); } +namespace { + +class TypeNameValidatorCCC : public CorrectionCandidateCallback { + public: + TypeNameValidatorCCC(bool AllowInvalid) : AllowInvalidDecl(AllowInvalid) { + 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 candidate.isKeyword(); + } + + private: + bool AllowInvalidDecl; +}; + +} + /// \brief If the identifier refers to a type name within this scope, /// return the declaration of that type. /// @@ -71,6 +95,7 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS, bool isClassName, bool HasTrailingDot, ParsedType ObjectTypePtr, + bool IsCtorOrDtorName, bool WantNontrivialTypeSourceInfo, IdentifierInfo **CorrectedII) { // Determine where we will perform name lookup. @@ -93,7 +118,7 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, // // We therefore do not perform any name lookup if the result would // refer to a member of an unknown specialization. - if (!isClassName) + if (!isClassName && !IsCtorOrDtorName) return ParsedType(); // We know from the grammar that this name refers to a type, @@ -148,9 +173,9 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, case LookupResult::NotFound: case LookupResult::NotFoundInCurrentInstantiation: if (CorrectedII) { + TypeNameValidatorCCC Validator(true); TypoCorrection Correction = CorrectTypo(Result.getLookupNameInfo(), - Kind, S, SS, 0, false, - Sema::CTC_Type); + Kind, S, SS, Validator); IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo(); TemplateTy Template; bool MemberOfUnknownSpecialization; @@ -166,16 +191,17 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, // Ignore a correction to a template type as the to-be-corrected // identifier is not a template (typo correction for template names // is handled elsewhere). - !(getLangOptions().CPlusPlus && NewSSPtr && + !(getLangOpts().CPlusPlus && NewSSPtr && isTemplateName(S, *NewSSPtr, false, TemplateName, ParsedType(), false, Template, MemberOfUnknownSpecialization))) { ParsedType Ty = getTypeName(*NewII, NameLoc, S, NewSSPtr, isClassName, HasTrailingDot, ObjectTypePtr, + IsCtorOrDtorName, WantNontrivialTypeSourceInfo); if (Ty) { - std::string CorrectedStr(Correction.getAsString(getLangOptions())); + std::string CorrectedStr(Correction.getAsString(getLangOpts())); std::string CorrectedQuotedStr( - Correction.getQuoted(getLangOptions())); + Correction.getQuoted(getLangOpts())); Diag(NameLoc, diag::err_unknown_typename_suggest) << Result.getLookupName() << CorrectedQuotedStr << FixItHint::CreateReplacement(SourceRange(NameLoc), @@ -249,8 +275,11 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, if (T.isNull()) T = Context.getTypeDeclType(TD); - - if (SS && SS->isNotEmpty()) { + + // NOTE: avoid constructing an ElaboratedType(Loc) if this is a + // constructor or destructor name (in such a case, the scope specifier + // will be attached to the enclosing Expr or Decl node). + if (SS && SS->isNotEmpty() && !IsCtorOrDtorName) { if (WantNontrivialTypeSourceInfo) { // Construct a type with type-source information. TypeLocBuilder Builder; @@ -258,7 +287,7 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, T = getElaboratedType(ETK_None, *SS, T); ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(T); - ElabTL.setKeywordLoc(SourceLocation()); + ElabTL.setElaboratedKeywordLoc(SourceLocation()); ElabTL.setQualifierLoc(SS->getWithLocInContext(Context)); return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); } else { @@ -292,7 +321,6 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { if (R.getResultKind() == LookupResult::Found) if (const TagDecl *TD = R.getAsSingle<TagDecl>()) { switch (TD->getTagKind()) { - default: return DeclSpec::TST_unspecified; case TTK_Struct: return DeclSpec::TST_struct; case TTK_Union: return DeclSpec::TST_union; case TTK_Class: return DeclSpec::TST_class; @@ -341,46 +369,44 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, // 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); if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(&II, IILoc), - LookupOrdinaryName, S, SS, NULL, - false, CTC_Type)) { - std::string CorrectedStr(Corrected.getAsString(getLangOptions())); - std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions())); + LookupOrdinaryName, S, SS, + Validator)) { + std::string CorrectedStr(Corrected.getAsString(getLangOpts())); + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); if (Corrected.isKeyword()) { // We corrected to a keyword. // FIXME: Actually recover with the keyword we suggest, and emit a fix-it. Diag(IILoc, diag::err_unknown_typename_suggest) << &II << CorrectedQuotedStr; - return true; } else { NamedDecl *Result = Corrected.getCorrectionDecl(); - if ((isa<TypeDecl>(Result) || isa<ObjCInterfaceDecl>(Result)) && - !Result->isInvalidDecl()) { - // We found a similarly-named type or interface; suggest that. - if (!SS || !SS->isSet()) - Diag(IILoc, diag::err_unknown_typename_suggest) - << &II << CorrectedQuotedStr - << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr); - else if (DeclContext *DC = computeDeclContext(*SS, false)) - Diag(IILoc, diag::err_unknown_nested_typename_suggest) - << &II << DC << CorrectedQuotedStr << SS->getRange() - << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr); - else - llvm_unreachable("could not have corrected a typo here"); + // We found a similarly-named type or interface; suggest that. + if (!SS || !SS->isSet()) + Diag(IILoc, diag::err_unknown_typename_suggest) + << &II << CorrectedQuotedStr + << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr); + else if (DeclContext *DC = computeDeclContext(*SS, false)) + Diag(IILoc, diag::err_unknown_nested_typename_suggest) + << &II << DC << CorrectedQuotedStr << SS->getRange() + << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr); + else + llvm_unreachable("could not have corrected a typo here"); - Diag(Result->getLocation(), diag::note_previous_decl) - << CorrectedQuotedStr; - - SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS, - false, false, ParsedType(), - /*NonTrivialTypeSourceInfo=*/true); - return true; - } + Diag(Result->getLocation(), diag::note_previous_decl) + << CorrectedQuotedStr; + + SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS, + false, false, ParsedType(), + /*IsCtorOrDtorName=*/false, + /*NonTrivialTypeSourceInfo=*/true); } + return true; } - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { // See if II is a class template that the user forgot to pass arguments to. UnqualifiedId Name; Name.setIdentifier(&II, IILoc); @@ -410,14 +436,15 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, << &II << DC << SS->getRange(); else if (isDependentScopeSpecifier(*SS)) { unsigned DiagID = diag::err_typename_missing; - if (getLangOptions().MicrosoftMode && isMicrosoftMissingTypename(SS, S)) + if (getLangOpts().MicrosoftMode && isMicrosoftMissingTypename(SS, S)) DiagID = diag::warn_typename_missing; Diag(SS->getRange().getBegin(), DiagID) << (NestedNameSpecifier *)SS->getScopeRep() << II.getName() << SourceRange(SS->getRange().getBegin(), IILoc) << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename "); - SuggestedType = ActOnTypenameType(S, SourceLocation(), *SS, II, IILoc).get(); + SuggestedType = ActOnTypenameType(S, SourceLocation(), *SS, II, IILoc) + .get(); } else { assert(SS && SS->isInvalid() && "Invalid scope specifier has already been diagnosed"); @@ -429,7 +456,7 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, /// \brief Determine whether the given result set contains either a type name /// or static bool isResultTypeOrTemplate(LookupResult &R, const Token &NextToken) { - bool CheckTemplate = R.getSema().getLangOptions().CPlusPlus && + bool CheckTemplate = R.getSema().getLangOpts().CPlusPlus && NextToken.is(tok::less); for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) { @@ -481,7 +508,7 @@ Corrected: if (!SS.isSet() && NextToken.is(tok::l_paren)) { // In C++, this is an ADL-only call. // FIXME: Reference? - if (getLangOptions().CPlusPlus) + if (getLangOpts().CPlusPlus) return BuildDeclarationNameExpr(SS, Result, /*ADL=*/true); // C90 6.3.2.2: @@ -506,7 +533,7 @@ Corrected: // In C, we first see whether there is a tag type by the same name, in // which case it's likely that the user just forget to write "enum", // "struct", or "union". - if (!getLangOptions().CPlusPlus && !SecondTry) { + if (!getLangOpts().CPlusPlus && !SecondTry) { Result.clear(LookupTagName); LookupParsedName(Result, S, &SS); if (TagDecl *Tag = Result.getAsSingle<TagDecl>()) { @@ -535,7 +562,7 @@ Corrected: } Diag(NameLoc, diag::err_use_of_tag_name_without_tag) - << Name << TagName << getLangOptions().CPlusPlus + << Name << TagName << getLangOpts().CPlusPlus << FixItHint::CreateInsertion(NameLoc, FixItTagName); break; } @@ -547,17 +574,19 @@ Corrected: // close to this name. if (!SecondTry) { SecondTry = true; + CorrectionCandidateCallback DefaultValidator; if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(), - Result.getLookupKind(), S, &SS)) { + Result.getLookupKind(), S, + &SS, DefaultValidator)) { unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest; unsigned QualifiedDiag = diag::err_no_member_suggest; - std::string CorrectedStr(Corrected.getAsString(getLangOptions())); - std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions())); + std::string CorrectedStr(Corrected.getAsString(getLangOpts())); + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); NamedDecl *FirstDecl = Corrected.getCorrectionDecl(); NamedDecl *UnderlyingFirstDecl = FirstDecl? FirstDecl->getUnderlyingDecl() : 0; - if (getLangOptions().CPlusPlus && NextToken.is(tok::less) && + if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) { UnqualifiedDiag = diag::err_no_template_suggest; QualifiedDiag = diag::err_no_member_template_suggest; @@ -582,19 +611,19 @@ Corrected: // Update the name, so that the caller has the new name. Name = Corrected.getCorrectionAsIdentifierInfo(); + // Typo correction corrected to a keyword. + if (Corrected.isKeyword()) + return Corrected.getCorrectionAsIdentifierInfo(); + // Also update the LookupResult... // FIXME: This should probably go away at some point Result.clear(); Result.setLookupName(Corrected.getCorrection()); - if (FirstDecl) Result.addDecl(FirstDecl); - - // Typo correction corrected to a keyword. - if (Corrected.isKeyword()) - return Corrected.getCorrectionAsIdentifierInfo(); - - if (FirstDecl) + if (FirstDecl) { + Result.addDecl(FirstDecl); Diag(FirstDecl->getLocation(), diag::note_previous_decl) << CorrectedQuotedStr; + } // If we found an Objective-C instance variable, let // LookupInObjCMethod build the appropriate expression to @@ -614,7 +643,7 @@ Corrected: Result.suppressDiagnostics(); return NameClassification::Unknown(); - case LookupResult::NotFoundInCurrentInstantiation: + case LookupResult::NotFoundInCurrentInstantiation: { // We performed name lookup into the current instantiation, and there were // dependent bases, so we treat this result the same way as any other // dependent nested-name-specifier. @@ -629,7 +658,9 @@ Corrected: // perform some heroics to see if we actually have a // template-argument-list, which would indicate a missing 'template' // keyword here. - return BuildDependentDeclRefExpr(SS, NameInfo, /*TemplateArgs=*/0); + return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), + NameInfo, /*TemplateArgs=*/0); + } case LookupResult::Found: case LookupResult::FoundOverloaded: @@ -637,7 +668,7 @@ Corrected: break; case LookupResult::Ambiguous: - if (getLangOptions().CPlusPlus && NextToken.is(tok::less) && + if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && hasAnyAcceptableTemplateNames(Result)) { // C++ [temp.local]p3: // A lookup that finds an injected-class-name (10.2) can result in an @@ -661,7 +692,7 @@ Corrected: return NameClassification::Error(); } - if (getLangOptions().CPlusPlus && NextToken.is(tok::less) && + if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && (IsFilteredTemplateName || hasAnyAcceptableTemplateNames(Result))) { // C++ [temp.names]p3: // After name lookup (3.4) finds that a name is a template-name or that @@ -735,7 +766,7 @@ Corrected: } if (!Result.empty() && (*Result.begin())->isCXXClassMember()) - return BuildPossibleImplicitMemberExpr(SS, Result, 0); + return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, 0); bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren)); return BuildDeclarationNameExpr(SS, Result, ADL); @@ -841,7 +872,13 @@ void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) { if (!FD) return; - PushDeclContext(S, FD); + // Same implementation as PushDeclContext, but enters the context + // from the lexical parent, rather than the top-level class. + assert(CurContext == FD->getLexicalParent() && + "The next DeclContext should be lexically contained in the current one."); + CurContext = FD; + S->setEntity(CurContext); + for (unsigned P = 0, NumParams = FD->getNumParams(); P < NumParams; ++P) { ParmVarDecl *Param = FD->getParamDecl(P); // If the parameter has an identifier, then add it to the scope @@ -853,6 +890,15 @@ void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) { } +void Sema::ActOnExitFunctionContext() { + // Same implementation as PopDeclContext, but returns to the lexical parent, + // rather than the top-level class. + assert(CurContext && "DeclContext imbalance!"); + CurContext = CurContext->getLexicalParent(); + assert(CurContext && "Popped translation unit!"); +} + + /// \brief Determine whether we allow overloading of the function /// PrevDecl with another declaration. /// @@ -864,7 +910,7 @@ void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) { /// attribute. static bool AllowOverloadingOfFunction(LookupResult &Previous, ASTContext &Context) { - if (Context.getLangOptions().CPlusPlus) + if (Context.getLangOpts().CPlusPlus) return true; if (Previous.getResultKind() == LookupResult::FoundOverloaded) @@ -891,7 +937,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { // Out-of-line definitions shouldn't be pushed into scope in C++. // Out-of-line variable and function definitions shouldn't even in C. - if ((getLangOptions().CPlusPlus || isa<VarDecl>(D) || isa<FunctionDecl>(D)) && + if ((getLangOpts().CPlusPlus || isa<VarDecl>(D) || isa<FunctionDecl>(D)) && D->isOutOfLine() && !D->getDeclContext()->getRedeclContext()->Equals( D->getLexicalDeclContext()->getRedeclContext())) @@ -936,6 +982,11 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { } } +void Sema::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { + if (IdResolver.tryAddTopLevelDecl(D, Name) && TUScope) + TUScope->AddDecl(D); +} + bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S, bool ExplicitInstantiationOrSpecialization) { return IdResolver.isDeclInScope(D, Ctx, Context, S, @@ -1089,7 +1140,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { if (D->isInvalidDecl()) return false; - if (D->isUsed() || D->hasAttr<UnusedAttr>()) + if (D->isReferenced() || D->isUsed() || D->hasAttr<UnusedAttr>()) return false; if (isa<LabelDecl>(D)) @@ -1101,7 +1152,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { return false; // Types of valid local variables should be complete, so this should succeed. - if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) { + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { // White-list anything with an __attribute__((unused)) type. QualType Ty = VD->getType(); @@ -1123,11 +1174,18 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { return false; if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) { - // FIXME: Checking for the presence of a user-declared constructor - // isn't completely accurate; we'd prefer to check that the initializer - // has no side effects. - if (RD->hasUserDeclaredConstructor() || !RD->hasTrivialDestructor()) + if (!RD->hasTrivialDestructor()) return false; + + if (const Expr *Init = VD->getInit()) { + const CXXConstructExpr *Construct = + dyn_cast<CXXConstructExpr>(Init); + if (Construct && !Construct->isElidable()) { + CXXConstructorDecl *CD = Construct->getConstructor(); + if (!CD->isTrivial()) + return false; + } + } } } @@ -1141,7 +1199,7 @@ static void GenerateFixForUnusedDecl(const NamedDecl *D, ASTContext &Ctx, FixItHint &Hint) { if (isa<LabelDecl>(D)) { SourceLocation AfterColon = Lexer::findLocationAfterToken(D->getLocEnd(), - tok::colon, Ctx.getSourceManager(), Ctx.getLangOptions(), true); + tok::colon, Ctx.getSourceManager(), Ctx.getLangOpts(), true); if (AfterColon.isInvalid()) return; Hint = FixItHint::CreateRemoval(CharSourceRange:: @@ -1206,6 +1264,15 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { } } +void Sema::ActOnStartFunctionDeclarator() { + ++InFunctionDeclarator; +} + +void Sema::ActOnEndFunctionDeclarator() { + assert(InFunctionDeclarator); + --InFunctionDeclarator; +} + /// \brief Look for an Objective-C class in the translation unit. /// /// \param Id The name of the Objective-C class we're looking for. If @@ -1229,10 +1296,11 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id, if (!IDecl && DoTypoCorrection) { // Perform typo correction at the given location, but only if we // find an Objective-C class name. - TypoCorrection C; - if ((C = CorrectTypo(DeclarationNameInfo(Id, IdLoc), LookupOrdinaryName, - TUScope, NULL, NULL, false, CTC_NoKeywords)) && - (IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>())) { + DeclFilterCCC<ObjCInterfaceDecl> Validator; + if (TypoCorrection C = CorrectTypo(DeclarationNameInfo(Id, IdLoc), + LookupOrdinaryName, TUScope, NULL, + Validator)) { + IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>(); Diag(IdLoc, diag::err_undef_interface_suggest) << Id << IDecl->getDeclName() << FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString()); @@ -1242,8 +1310,11 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id, Id = IDecl->getIdentifier(); } } - - return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl); + ObjCInterfaceDecl *Def = dyn_cast_or_null<ObjCInterfaceDecl>(IDecl); + // This routine must always return a class definition, if any. + if (Def && Def->getDefinition()) + Def = Def->getDefinition(); + return Def; } /// getNonFieldDeclScope - Retrieves the innermost scope, starting @@ -1273,7 +1344,7 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) { while (((S->getFlags() & Scope::DeclScope) == 0) || (S->getEntity() && ((DeclContext *)S->getEntity())->isTransparentContext()) || - (S->isClassScope() && !getLangOptions().CPlusPlus)) + (S->isClassScope() && !getLangOpts().CPlusPlus)) S = S->getParent(); return S; } @@ -1362,6 +1433,40 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, return New; } +bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) { + QualType OldType; + if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old)) + OldType = OldTypedef->getUnderlyingType(); + else + OldType = Context.getTypeDeclType(Old); + QualType NewType = New->getUnderlyingType(); + + if (NewType->isVariablyModifiedType()) { + // Must not redefine a typedef with a variably-modified type. + int Kind = isa<TypeAliasDecl>(Old) ? 1 : 0; + Diag(New->getLocation(), diag::err_redefinition_variably_modified_typedef) + << Kind << NewType; + if (Old->getLocation().isValid()) + Diag(Old->getLocation(), diag::note_previous_definition); + New->setInvalidDecl(); + return true; + } + + if (OldType != NewType && + !OldType->isDependentType() && + !NewType->isDependentType() && + !Context.hasSameType(OldType, NewType)) { + int Kind = isa<TypeAliasDecl>(Old) ? 1 : 0; + Diag(New->getLocation(), diag::err_redefinition_different_typedef) + << Kind << NewType << OldType; + if (Old->getLocation().isValid()) + Diag(Old->getLocation(), diag::note_previous_definition); + New->setInvalidDecl(); + return true; + } + return false; +} + /// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the /// same name and scope as a previous declaration 'Old'. Figure out /// how to resolve this situation, merging decls or emitting @@ -1374,7 +1479,7 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { // Allow multiple definitions for ObjC built-in typedefs. // FIXME: Verify the underlying types are equivalent! - if (getLangOptions().ObjC1) { + if (getLangOpts().ObjC1) { const IdentifierInfo *TypeID = New->getIdentifier(); switch (TypeID->getLength()) { default: break; @@ -1420,46 +1525,20 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { if (Old->isInvalidDecl()) return New->setInvalidDecl(); - // Determine the "old" type we'll use for checking and diagnostics. - QualType OldType; - if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old)) - OldType = OldTypedef->getUnderlyingType(); - else - OldType = Context.getTypeDeclType(Old); - // If the typedef types are not identical, reject them in all languages and // with any extensions enabled. - - if (OldType != New->getUnderlyingType() && - Context.getCanonicalType(OldType) != - Context.getCanonicalType(New->getUnderlyingType())) { - int Kind = 0; - if (isa<TypeAliasDecl>(Old)) - Kind = 1; - Diag(New->getLocation(), diag::err_redefinition_different_typedef) - << Kind << New->getUnderlyingType() << OldType; - if (Old->getLocation().isValid()) - Diag(Old->getLocation(), diag::note_previous_definition); - return New->setInvalidDecl(); - } + if (isIncompatibleTypedef(Old, New)) + return; // The types match. Link up the redeclaration chain if the old // declaration was a typedef. - // FIXME: this is a potential source of weirdness if the type - // spellings don't match exactly. if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old)) New->setPreviousDeclaration(Typedef); - // __module_private__ is propagated to later declarations. - if (Old->isModulePrivate()) - New->setModulePrivate(); - else if (New->isModulePrivate()) - diagnoseModulePrivateRedeclaration(New, Old); - - if (getLangOptions().MicrosoftExt) + if (getLangOpts().MicrosoftExt) return; - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { // C++ [dcl.typedef]p2: // In a given non-class scope, a typedef specifier can be used to // redefine the name of any type declared in that scope to refer @@ -1497,6 +1576,10 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { return New->setInvalidDecl(); } + // Modules always permit redefinition of typedefs, as does C11. + if (getLangOpts().Modules || getLangOpts().C11) + return; + // If we have a redefinition of a typedef in C, emit a warning. This warning // is normally mapped to an error, but can be controlled with // -Wtypedef-redefinition. If either the original or the redefinition is @@ -1535,36 +1618,37 @@ DeclHasAttr(const Decl *D, const Attr *A) { } /// mergeDeclAttributes - Copy attributes from the Old decl to the New one. -static void mergeDeclAttributes(Decl *newDecl, const Decl *oldDecl, - ASTContext &C, bool mergeDeprecation = true) { - if (!oldDecl->hasAttrs()) +void Sema::mergeDeclAttributes(Decl *New, Decl *Old, + bool MergeDeprecation) { + if (!Old->hasAttrs()) return; - bool foundAny = newDecl->hasAttrs(); + bool foundAny = New->hasAttrs(); // Ensure that any moving of objects within the allocated map is done before // we process them. - if (!foundAny) newDecl->setAttrs(AttrVec()); + if (!foundAny) New->setAttrs(AttrVec()); for (specific_attr_iterator<InheritableAttr> - i = oldDecl->specific_attr_begin<InheritableAttr>(), - e = oldDecl->specific_attr_end<InheritableAttr>(); i != e; ++i) { + i = Old->specific_attr_begin<InheritableAttr>(), + e = Old->specific_attr_end<InheritableAttr>(); + i != e; ++i) { // Ignore deprecated/unavailable/availability attributes if requested. - if (!mergeDeprecation && + if (!MergeDeprecation && (isa<DeprecatedAttr>(*i) || isa<UnavailableAttr>(*i) || isa<AvailabilityAttr>(*i))) continue; - if (!DeclHasAttr(newDecl, *i)) { - InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(C)); + if (!DeclHasAttr(New, *i)) { + InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(Context)); newAttr->setInherited(true); - newDecl->addAttr(newAttr); + New->addAttr(newAttr); foundAny = true; } } - if (!foundAny) newDecl->dropAttrs(); + if (!foundAny) New->dropAttrs(); } /// mergeParamDeclAttributes - Copy attributes from the old parameter @@ -1651,7 +1735,7 @@ static bool canRedefineFunction(const FunctionDecl *FD, /// merged with. /// /// Returns true if there was an error, false otherwise. -bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { +bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { // Verify the old decl was also a function. FunctionDecl *Old = 0; if (FunctionTemplateDecl *OldFunctionTemplate @@ -1693,8 +1777,8 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) && New->getStorageClass() == SC_Static && Old->getStorageClass() != SC_Static && - !canRedefineFunction(Old, getLangOptions())) { - if (getLangOptions().MicrosoftExt) { + !canRedefineFunction(Old, getLangOpts())) { + if (getLangOpts().MicrosoftExt) { Diag(New->getLocation(), diag::warn_static_non_static) << New; Diag(Old->getLocation(), PrevDiag); } else { @@ -1776,7 +1860,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { NewQType = Context.getCanonicalType(New->getType()); } - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { // (C++98 13.1p2): // Certain function declarations cannot be overloaded: // -- Function declarations that differ only in the return type @@ -1881,14 +1965,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { } if (OldQTypeForComparison == NewQType) - return MergeCompatibleFunctionDecls(New, Old); + return MergeCompatibleFunctionDecls(New, Old, S); // Fall through for conflicting redeclarations and redefinitions. } // C: Function types need to be compatible, not identical. This handles // duplicate function decls like "void f(int); void f(enum X);" properly. - if (!getLangOptions().CPlusPlus && + if (!getLangOpts().CPlusPlus && Context.typesAreCompatible(OldQType, NewQType)) { const FunctionType *OldFuncType = OldQType->getAs<FunctionType>(); const FunctionType *NewFuncType = NewQType->getAs<FunctionType>(); @@ -1926,7 +2010,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { New->setParams(Params); } - return MergeCompatibleFunctionDecls(New, Old); + return MergeCompatibleFunctionDecls(New, Old, S); } // GNU C permits a K&R definition to follow a prototype declaration @@ -1940,7 +2024,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { // the K&R definition becomes variadic. This is sort of an edge case, but // it's legal per the standard depending on how you read C99 6.7.5.3p15 and // C99 6.9.1p8. - if (!getLangOptions().CPlusPlus && + if (!getLangOpts().CPlusPlus && Old->hasPrototype() && !New->hasPrototype() && New->getType()->getAs<FunctionProtoType>() && Old->getNumParams() == New->getNumParams()) { @@ -1987,7 +2071,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { New->setType(Context.getFunctionType(MergedReturn, &ArgTypes[0], ArgTypes.size(), OldProto->getExtProtoInfo())); - return MergeCompatibleFunctionDecls(New, Old); + return MergeCompatibleFunctionDecls(New, Old, S); } // Fall through to diagnose conflicting types. @@ -2028,9 +2112,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { /// redeclaration of Old. /// /// \returns false -bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { +bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, + Scope *S) { // Merge the attributes - mergeDeclAttributes(New, Old, Context); + mergeDeclAttributes(New, Old); // Merge the storage class. if (Old->getStorageClass() != SC_Extern && @@ -2041,12 +2126,6 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { if (Old->isPure()) New->setPure(); - // __module_private__ is propagated to later declarations. - if (Old->isModulePrivate()) - New->setModulePrivate(); - else if (New->isModulePrivate()) - diagnoseModulePrivateRedeclaration(New, Old); - // Merge attributes from the parameters. These can mismatch with K&R // declarations. if (New->getNumParams() == Old->getNumParams()) @@ -2054,21 +2133,21 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { mergeParamDeclAttributes(New->getParamDecl(i), Old->getParamDecl(i), Context); - if (getLangOptions().CPlusPlus) - return MergeCXXFunctionDecl(New, Old); + if (getLangOpts().CPlusPlus) + return MergeCXXFunctionDecl(New, Old, S); return false; } void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, - const ObjCMethodDecl *oldMethod) { + ObjCMethodDecl *oldMethod) { // We don't want to merge unavailable and deprecated attributes // except from interface to implementation. bool mergeDeprecation = isa<ObjCImplDecl>(newMethod->getDeclContext()); // Merge the attributes. - mergeDeclAttributes(newMethod, oldMethod, Context, mergeDeprecation); + mergeDeclAttributes(newMethod, oldMethod, mergeDeprecation); // Merge attributes from the parameters. ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin(); @@ -2085,15 +2164,14 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, /// emitting diagnostics as appropriate. /// /// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back -/// to here in AddInitializerToDecl and AddCXXDirectInitializerToDecl. We can't -/// check them before the initializer is attached. -/// +/// to here in AddInitializerToDecl. We can't check them before the initializer +/// is attached. void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) { if (New->isInvalidDecl() || Old->isInvalidDecl()) return; QualType MergedT; - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { AutoType *AT = New->getType()->getContainedAutoType(); if (AT && !AT->isDeduced()) { // We don't know what the new type is until the initializer is attached. @@ -2175,8 +2253,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { New->setInvalidDecl(); } - mergeDeclAttributes(New, Old, Context); - // Warn if an already-declared variable is made a weak_import in a subsequent declaration + mergeDeclAttributes(New, Old); + // Warn if an already-declared variable is made a weak_import in a subsequent + // declaration if (New->getAttr<WeakImportAttr>() && Old->getStorageClass() == SC_None && !Old->getAttr<WeakImportAttr>()) { @@ -2230,12 +2309,6 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { return New->setInvalidDecl(); } - // __module_private__ is propagated to later declarations. - if (Old->isModulePrivate()) - New->setModulePrivate(); - else if (New->isModulePrivate()) - diagnoseModulePrivateRedeclaration(New, Old); - // Variables with external linkage are analyzed in FinalizeDeclaratorGroup. // FIXME: The test for external storage here seems wrong? We still @@ -2259,7 +2332,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { // C++ doesn't have tentative definitions, so go right ahead and check here. const VarDecl *Def; - if (getLangOptions().CPlusPlus && + if (getLangOpts().CPlusPlus && New->isThisDeclarationADefinition() == VarDecl::Definition && (Def = Old->getDefinition())) { Diag(New->getLocation(), diag::err_redefinition) @@ -2315,11 +2388,17 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, // Note that the above type specs guarantee that the // type rep is a Decl, whereas in many of the others // it's a Type. - Tag = dyn_cast<TagDecl>(TagD); + if (isa<TagDecl>(TagD)) + Tag = cast<TagDecl>(TagD); + else if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(TagD)) + Tag = CTD->getTemplatedDecl(); } - if (Tag) + if (Tag) { Tag->setFreeStanding(); + if (Tag->isInvalidDecl()) + return Tag; + } if (unsigned TypeQuals = DS.getTypeQualifiers()) { // Enforce C99 6.7.3p2: "Types other than pointer types derived from object @@ -2357,22 +2436,20 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, bool emittedWarning = false; if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) { - ProcessDeclAttributeList(S, Record, DS.getAttributes().getList()); - if (!Record->getDeclName() && Record->isCompleteDefinition() && DS.getStorageClassSpec() != DeclSpec::SCS_typedef) { - if (getLangOptions().CPlusPlus || + if (getLangOpts().CPlusPlus || Record->getDeclContext()->isRecord()) return BuildAnonymousStructOrUnion(S, DS, AS, Record); - Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators) + Diag(DS.getLocStart(), diag::ext_no_declarators) << DS.getSourceRange(); emittedWarning = true; } } // Check for Microsoft C extension: anonymous struct. - if (getLangOptions().MicrosoftExt && !getLangOptions().CPlusPlus && + if (getLangOpts().MicrosoftExt && !getLangOpts().CPlusPlus && CurContext->isRecord() && DS.getStorageClassSpec() == DeclSpec::SCS_unspecified) { // Handle 2 kinds of anonymous struct: @@ -2383,13 +2460,13 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, if ((Record && Record->getDeclName() && !Record->isCompleteDefinition()) || (DS.getTypeSpecType() == DeclSpec::TST_typename && DS.getRepAsType().get()->isStructureType())) { - Diag(DS.getSourceRange().getBegin(), diag::ext_ms_anonymous_struct) + Diag(DS.getLocStart(), diag::ext_ms_anonymous_struct) << DS.getSourceRange(); return BuildMicrosoftCAnonymousStruct(S, DS, Record); } } - if (getLangOptions().CPlusPlus && + if (getLangOpts().CPlusPlus && DS.getStorageClassSpec() != DeclSpec::SCS_typedef) if (EnumDecl *Enum = dyn_cast_or_null<EnumDecl>(Tag)) if (Enum->enumerator_begin() == Enum->enumerator_end() && @@ -2407,12 +2484,12 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, // extension in both Microsoft and GNU. if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef && Tag && isa<EnumDecl>(Tag)) { - Diag(DS.getSourceRange().getBegin(), diag::ext_typedef_without_a_name) + Diag(DS.getLocStart(), diag::ext_typedef_without_a_name) << DS.getSourceRange(); return Tag; } - Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators) + Diag(DS.getLocStart(), diag::ext_no_declarators) << DS.getSourceRange(); emittedWarning = true; } @@ -2453,28 +2530,29 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, << Tag->getTagKind() << FixItHint::CreateRemoval(DS.getModulePrivateSpecLoc()); - // FIXME: Warn on useless attributes - - return TagD; -} - -/// ActOnVlaStmt - This rouine if finds a vla expression in a decl spec. -/// builds a statement for it and returns it so it is evaluated. -StmtResult Sema::ActOnVlaStmt(const DeclSpec &DS) { - StmtResult R; - if (DS.getTypeSpecType() == DeclSpec::TST_typeofExpr) { - Expr *Exp = DS.getRepAsExpr(); - QualType Ty = Exp->getType(); - if (Ty->isPointerType()) { - do - Ty = Ty->getAs<PointerType>()->getPointeeType(); - while (Ty->isPointerType()); - } - if (Ty->isVariableArrayType()) { - R = ActOnExprStmt(MakeFullExpr(Exp)); + // Warn about ignored type attributes, for example: + // __attribute__((aligned)) struct A; + // Attributes should be placed after tag to apply to type declaration. + if (!DS.getAttributes().empty()) { + DeclSpec::TST TypeSpecType = DS.getTypeSpecType(); + if (TypeSpecType == DeclSpec::TST_class || + TypeSpecType == DeclSpec::TST_struct || + TypeSpecType == DeclSpec::TST_union || + TypeSpecType == DeclSpec::TST_enum) { + AttributeList* attrs = DS.getAttributes().getList(); + while (attrs) { + Diag(attrs->getScopeLoc(), + diag::warn_declspec_attribute_ignored) + << attrs->getName() + << (TypeSpecType == DeclSpec::TST_class ? 0 : + TypeSpecType == DeclSpec::TST_struct ? 1 : + TypeSpecType == DeclSpec::TST_union ? 2 : 3); + attrs = attrs->getNext(); + } } } - return R; + + return TagD; } /// We are trying to inject an anonymous member into the given scope; @@ -2629,51 +2707,56 @@ StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec) { /// BuildAnonymousStructOrUnion - Handle the declaration of an /// anonymous structure or union. Anonymous unions are a C++ feature -/// (C++ [class.union]) and a GNU C extension; anonymous structures -/// are a GNU C and GNU C++ extension. +/// (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) { DeclContext *Owner = Record->getDeclContext(); // Diagnose whether this anonymous struct/union is an extension. - if (Record->isUnion() && !getLangOptions().CPlusPlus) + if (Record->isUnion() && !getLangOpts().CPlusPlus && !getLangOpts().C11) Diag(Record->getLocation(), diag::ext_anonymous_union); - else if (!Record->isUnion()) - Diag(Record->getLocation(), diag::ext_anonymous_struct); + else if (!Record->isUnion() && getLangOpts().CPlusPlus) + Diag(Record->getLocation(), diag::ext_gnu_anonymous_struct); + else if (!Record->isUnion() && !getLangOpts().C11) + Diag(Record->getLocation(), diag::ext_c11_anonymous_struct); // C and C++ require different kinds of checks for anonymous // structs/unions. bool Invalid = false; - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { const char* PrevSpec = 0; unsigned DiagID; - // C++ [class.union]p3: - // Anonymous unions declared in a named namespace or in the - // global namespace shall be declared static. - if (DS.getStorageClassSpec() != DeclSpec::SCS_static && - (isa<TranslationUnitDecl>(Owner) || - (isa<NamespaceDecl>(Owner) && - cast<NamespaceDecl>(Owner)->getDeclName()))) { - Diag(Record->getLocation(), diag::err_anonymous_union_not_static); - Invalid = true; - - // Recover by adding 'static'. - DS.SetStorageClassSpec(*this, DeclSpec::SCS_static, SourceLocation(), - PrevSpec, DiagID); - } - // C++ [class.union]p3: - // A storage class is not allowed in a declaration of an - // anonymous union in a class scope. - else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified && - isa<RecordDecl>(Owner)) { - Diag(DS.getStorageClassSpecLoc(), - diag::err_anonymous_union_with_storage_spec); - Invalid = true; - - // Recover by removing the storage specifier. - DS.SetStorageClassSpec(*this, DeclSpec::SCS_unspecified, SourceLocation(), - PrevSpec, DiagID); + if (Record->isUnion()) { + // C++ [class.union]p6: + // Anonymous unions declared in a named namespace or in the + // global namespace shall be declared static. + if (DS.getStorageClassSpec() != DeclSpec::SCS_static && + (isa<TranslationUnitDecl>(Owner) || + (isa<NamespaceDecl>(Owner) && + cast<NamespaceDecl>(Owner)->getDeclName()))) { + Diag(Record->getLocation(), diag::err_anonymous_union_not_static) + << FixItHint::CreateInsertion(Record->getLocation(), "static "); + + // Recover by adding 'static'. + DS.SetStorageClassSpec(*this, DeclSpec::SCS_static, SourceLocation(), + PrevSpec, DiagID); + } + // C++ [class.union]p6: + // A storage class is not allowed in a declaration of an + // anonymous union in a class scope. + else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified && + isa<RecordDecl>(Owner)) { + Diag(DS.getStorageClassSpecLoc(), + diag::err_anonymous_union_with_storage_spec) + << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc()); + + // Recover by removing the storage specifier. + DS.SetStorageClassSpec(*this, DeclSpec::SCS_unspecified, + SourceLocation(), + PrevSpec, DiagID); + } } // Ignore const/volatile/restrict qualifiers. @@ -2683,11 +2766,13 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, << Record->isUnion() << 0 << FixItHint::CreateRemoval(DS.getConstSpecLoc()); if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) - Diag(DS.getVolatileSpecLoc(), diag::ext_anonymous_struct_union_qualified) + Diag(DS.getVolatileSpecLoc(), + diag::ext_anonymous_struct_union_qualified) << Record->isUnion() << 1 << FixItHint::CreateRemoval(DS.getVolatileSpecLoc()); if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict) - Diag(DS.getRestrictSpecLoc(), diag::ext_anonymous_struct_union_qualified) + Diag(DS.getRestrictSpecLoc(), + diag::ext_anonymous_struct_union_qualified) << Record->isUnion() << 2 << FixItHint::CreateRemoval(DS.getRestrictSpecLoc()); @@ -2717,7 +2802,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // copy constructor, a non-trivial destructor, or a non-trivial copy // assignment operator cannot be a member of a union, nor can an // array of such objects. - if (!getLangOptions().CPlusPlus0x && CheckNontrivialField(FD)) + if (CheckNontrivialField(FD)) Invalid = true; } else if ((*Mem)->isImplicit()) { // Any implicit members are fine. @@ -2730,7 +2815,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, if (!MemRecord->isAnonymousStructOrUnion() && MemRecord->getDeclName()) { // Visual C++ allows type definition in anonymous struct or union. - if (getLangOptions().MicrosoftExt) + if (getLangOpts().MicrosoftExt) Diag(MemRecord->getLocation(), diag::ext_anonymous_record_with_type) << (int)Record->isUnion(); else { @@ -2754,7 +2839,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, DK = diag::err_anonymous_record_with_static; // Visual C++ allows type definition in anonymous struct or union. - if (getLangOptions().MicrosoftExt && + if (getLangOpts().MicrosoftExt && DK == diag::err_anonymous_record_with_type) Diag((*Mem)->getLocation(), diag::ext_anonymous_record_with_type) << (int)Record->isUnion(); @@ -2769,7 +2854,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, if (!Record->isUnion() && !Owner->isRecord()) { Diag(Record->getLocation(), diag::err_anonymous_struct_not_member) - << (int)getLangOptions().CPlusPlus; + << (int)getLangOpts().CPlusPlus; Invalid = true; } @@ -2782,7 +2867,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, NamedDecl *Anon = 0; if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) { Anon = FieldDecl::Create(Context, OwningClass, - DS.getSourceRange().getBegin(), + DS.getLocStart(), Record->getLocation(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), @@ -2790,7 +2875,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, /*BitWidth=*/0, /*Mutable=*/false, /*HasInit=*/false); Anon->setAccess(AS); - if (getLangOptions().CPlusPlus) + if (getLangOpts().CPlusPlus) FieldCollector->Add(cast<FieldDecl>(Anon)); } else { DeclSpec::SCS SCSpec = DS.getStorageClassSpec(); @@ -2809,7 +2894,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, = StorageClassSpecToVarDeclStorageClass(SCSpec); Anon = VarDecl::Create(Context, Owner, - DS.getSourceRange().getBegin(), + DS.getLocStart(), Record->getLocation(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), TInfo, SC, SCAsWritten); @@ -2879,8 +2964,8 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, // Create a declaration for this anonymous struct. NamedDecl* Anon = FieldDecl::Create(Context, cast<RecordDecl>(CurContext), - DS.getSourceRange().getBegin(), - DS.getSourceRange().getBegin(), + DS.getLocStart(), + DS.getLocStart(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), TInfo, @@ -2897,9 +2982,10 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, SmallVector<NamedDecl*, 2> Chain; Chain.push_back(Anon); - if (InjectAnonymousStructOrUnionMembers(*this, S, CurContext, - Record->getDefinition(), - AS_none, Chain, true)) + RecordDecl *RecordDef = Record->getDefinition(); + if (!RecordDef || InjectAnonymousStructOrUnionMembers(*this, S, CurContext, + RecordDef, AS_none, + Chain, true)) Anon->setInvalidDecl(); return Anon; @@ -3135,8 +3221,14 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, } Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { - D.setFunctionDefinition(false); - return HandleDeclarator(S, D, MultiTemplateParamsArg(*this)); + D.setFunctionDefinitionKind(FDK_Declaration); + Decl *Dcl = HandleDeclarator(S, D, MultiTemplateParamsArg(*this)); + + if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer() && + Dcl->getDeclContext()->isFileContext()) + Dcl->setTopLevelDeclInObjCContainer(); + + return Dcl; } /// DiagnoseClassNameShadow - Implement C++ [class.mem]p13: @@ -3158,7 +3250,100 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC, return false; } + +/// \brief Diagnose a declaration whose declarator-id has the given +/// nested-name-specifier. +/// +/// \param SS The nested-name-specifier of the declarator-id. +/// +/// \param DC The declaration context to which the nested-name-specifier +/// resolves. +/// +/// \param Name The name of the entity being declared. +/// +/// \param Loc The location of the name of the entity being declared. +/// +/// \returns true if we cannot safely recover from this error, false otherwise. +bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, + DeclarationName Name, + SourceLocation Loc) { + DeclContext *Cur = CurContext; + while (isa<LinkageSpecDecl>(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. + // + // class X { + // void X::f(); + // }; + if (Cur->Equals(DC)) { + Diag(Loc, diag::warn_member_extra_qualification) + << Name << FixItHint::CreateRemoval(SS.getRange()); + SS.clear(); + return false; + } + + // Check whether the qualifying scope encloses the scope of the original + // declaration. + if (!Cur->Encloses(DC)) { + if (Cur->isRecord()) + Diag(Loc, diag::err_member_qualification) + << Name << SS.getRange(); + else if (isa<TranslationUnitDecl>(DC)) + Diag(Loc, diag::err_invalid_declarator_global_scope) + << Name << SS.getRange(); + else if (isa<FunctionDecl>(Cur)) + Diag(Loc, diag::err_invalid_declarator_in_function) + << Name << SS.getRange(); + else + Diag(Loc, diag::err_invalid_declarator_scope) + << Name << cast<NamedDecl>(Cur) << cast<NamedDecl>(DC) << SS.getRange(); + + return true; + } + + if (Cur->isRecord()) { + // Cannot qualify members within a class. + Diag(Loc, diag::err_member_qualification) + << Name << SS.getRange(); + SS.clear(); + + // C++ constructors and destructors with incorrect scopes can break + // our AST invariants by having the wrong underlying types. If + // that's the case, then drop this declaration entirely. + if ((Name.getNameKind() == DeclarationName::CXXConstructorName || + Name.getNameKind() == DeclarationName::CXXDestructorName) && + !Context.hasSameType(Name.getCXXNameType(), + Context.getTypeDeclType(cast<CXXRecordDecl>(Cur)))) + return true; + + return false; + } + + // C++11 [dcl.meaning]p1: + // [...] "The nested-name-specifier of the qualified declarator-id shall + // not begin with a decltype-specifer" + NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data()); + while (SpecLoc.getPrefix()) + SpecLoc = SpecLoc.getPrefix(); + if (dyn_cast_or_null<DecltypeType>( + SpecLoc.getNestedNameSpecifier()->getAsType())) + Diag(Loc, diag::err_decltype_in_declarator) + << SpecLoc.getTypeLoc().getSourceRange(); + + return false; +} + Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists) { // TODO: consider using NameInfo for diagnostic. @@ -3169,7 +3354,7 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, // one, the ParsedFreeStandingDeclSpec action should be used. if (!Name) { if (!D.isInvalidType()) // Reject this if we think it is valid. - Diag(D.getDeclSpec().getSourceRange().getBegin(), + Diag(D.getDeclSpec().getLocStart(), diag::err_declarator_need_ident) << D.getDeclSpec().getSourceRange() << D.getSourceRange(); return 0; @@ -3209,29 +3394,18 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, RequireCompleteDeclContext(D.getCXXScopeSpec(), DC)) return 0; - if (isa<CXXRecordDecl>(DC)) { - if (!cast<CXXRecordDecl>(DC)->hasDefinition()) { - Diag(D.getIdentifierLoc(), - diag::err_member_def_undefined_record) - << Name << DC << D.getCXXScopeSpec().getRange(); - D.setInvalidType(); - } else if (isa<CXXRecordDecl>(CurContext) && - !D.getDeclSpec().isFriendSpecified()) { - // The user provided a superfluous scope specifier inside a class - // definition: - // - // class X { - // void X::f(); - // }; - if (CurContext->Equals(DC)) - Diag(D.getIdentifierLoc(), diag::warn_member_extra_qualification) - << Name << FixItHint::CreateRemoval(D.getCXXScopeSpec().getRange()); - else - Diag(D.getIdentifierLoc(), diag::err_member_qualification) - << Name << D.getCXXScopeSpec().getRange(); + if (isa<CXXRecordDecl>(DC) && !cast<CXXRecordDecl>(DC)->hasDefinition()) { + Diag(D.getIdentifierLoc(), + diag::err_member_def_undefined_record) + << Name << DC << D.getCXXScopeSpec().getRange(); + D.setInvalidType(); + } else if (!D.getDeclSpec().isFriendSpecified()) { + if (diagnoseQualifiedDeclaration(D.getCXXScopeSpec(), DC, + Name, D.getIdentifierLoc())) { + if (DC->isRecord()) + return 0; - // Pretend that this qualifier was not here. - D.getCXXScopeSpec().clear(); + D.setInvalidType(); } } @@ -3289,21 +3463,16 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, } else { // Something like "int foo::x;" LookupQualifiedName(Previous, DC); - // Don't consider using declarations as previous declarations for - // out-of-line members. - RemoveUsingDecls(Previous); - - // C++ 7.3.1.2p2: - // Members (including explicit specializations of templates) of a named - // namespace can also be defined outside that namespace by explicit - // qualification of the name being defined, provided that the entity being - // defined was already declared in the namespace and the definition appears - // after the point of declaration in a namespace that encloses the - // declarations namespace. + // C++ [dcl.meaning]p1: + // When the declarator-id is qualified, the declaration shall refer to a + // previously declared member of the class or namespace to which the + // qualifier refers (or, in the case of a namespace, of an element of the + // inline namespace set of that namespace (7.3.1)) or to a specialization + // thereof; [...] // - // Note that we only check the context at this point. We don't yet - // have enough information to make sure that PrevDecl is actually - // the declaration we want to match. For example, given: + // Note that we already checked the context above, and that we do not have + // enough information to make sure that Previous contains the declaration + // we want to match. For example, given: // // class X { // void f(); @@ -3312,40 +3481,23 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, // // void X::f(int) { } // ill-formed // - // In this case, PrevDecl will point to the overload set + // In this case, Previous will point to the overload set // containing the two f's declared in X, but neither of them // matches. - - // First check whether we named the global scope. - if (isa<TranslationUnitDecl>(DC)) { - Diag(D.getIdentifierLoc(), diag::err_invalid_declarator_global_scope) - << Name << D.getCXXScopeSpec().getRange(); - } else { - DeclContext *Cur = CurContext; - while (isa<LinkageSpecDecl>(Cur)) - Cur = Cur->getParent(); - if (!Cur->Encloses(DC)) { - // The qualifying scope doesn't enclose the original declaration. - // Emit diagnostic based on current scope. - SourceLocation L = D.getIdentifierLoc(); - SourceRange R = D.getCXXScopeSpec().getRange(); - if (isa<FunctionDecl>(Cur)) - Diag(L, diag::err_invalid_declarator_in_function) << Name << R; - else - Diag(L, diag::err_invalid_declarator_scope) - << Name << cast<NamedDecl>(DC) << R; - D.setInvalidType(); - } - } + + // C++ [dcl.meaning]p1: + // [...] the member shall not merely have been introduced by a + // using-declaration in the scope of the class or namespace nominated by + // the nested-name-specifier of the declarator-id. + RemoveUsingDecls(Previous); } if (Previous.isSingleResult() && Previous.getFoundDecl()->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. if (!D.isInvalidType()) - if (DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), - Previous.getFoundDecl())) - D.setInvalidType(); + DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), + Previous.getFoundDecl()); // Just pretend that we didn't see the previous declaration. Previous.clear(); @@ -3434,14 +3586,12 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, if (VLATy->getElementType()->isVariablyModifiedType()) return QualType(); - Expr::EvalResult EvalResult; + llvm::APSInt Res; if (!VLATy->getSizeExpr() || - !VLATy->getSizeExpr()->Evaluate(EvalResult, Context) || - !EvalResult.Val.isInt()) + !VLATy->getSizeExpr()->EvaluateAsInt(Res, Context)) return QualType(); // Check whether the array size is negative. - llvm::APSInt &Res = EvalResult.Val.getInt(); if (Res.isSigned() && Res.isNegative()) { SizeIsNegative = true; return QualType(); @@ -3548,7 +3698,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, Previous.clear(); } - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { // Check that there are no default arguments (C++ only). CheckExtraCXXDefaultArguments(D); } @@ -3606,7 +3756,8 @@ Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) { else if (T->isVariableArrayType()) Diag(NewTD->getLocation(), diag::err_vla_decl_in_file_scope); else if (Oversized.getBoolValue()) - Diag(NewTD->getLocation(), diag::err_array_too_large) << Oversized.toString(10); + Diag(NewTD->getLocation(), diag::err_array_too_large) + << Oversized.toString(10); else Diag(NewTD->getLocation(), diag::err_vm_decl_in_file_scope); NewTD->setInvalidDecl(); @@ -3677,7 +3828,7 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, if (!PrevDecl->hasLinkage()) return false; - if (Context.getLangOptions().CPlusPlus) { + if (Context.getLangOpts().CPlusPlus) { // C++ [basic.link]p6: // If there is a visible declaration of an entity with linkage // having the same name and type, ignoring entities declared @@ -3766,7 +3917,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, DeclarationName Name = GetNameForDeclarator(D).getName(); // Check that there are no default arguments (C++ only). - if (getLangOptions().CPlusPlus) + if (getLangOpts().CPlusPlus) CheckExtraCXXDefaultArguments(D); DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec(); @@ -3808,7 +3959,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } - if (getLangOptions().OpenCL) { + if (getLangOpts().OpenCL) { // Set up the special work-group-local storage class for variables in the // OpenCL __local address space. if (R.getAddressSpace() == LangAS::opencl_local) @@ -3817,8 +3968,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, bool isExplicitSpecialization = false; VarDecl *NewVD; - if (!getLangOptions().CPlusPlus) { - NewVD = VarDecl::Create(Context, DC, D.getSourceRange().getBegin(), + if (!getLangOpts().CPlusPlus) { + NewVD = VarDecl::Create(Context, DC, D.getLocStart(), D.getIdentifierLoc(), II, R, TInfo, SC, SCAsWritten); @@ -3834,20 +3985,24 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, } else if (SC == SC_None) SC = SC_Static; } - if (SC == SC_Static) { + if (SC == SC_Static && CurContext->isRecord()) { if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) { if (RD->isLocalClass()) Diag(D.getIdentifierLoc(), diag::err_static_data_member_not_allowed_in_local_class) << Name << RD->getDeclName(); - // C++ [class.union]p1: If a union contains a static data member, - // the program is ill-formed. - // - // We also disallow static data members in anonymous structs. - if (CurContext->isRecord() && (RD->isUnion() || !RD->getDeclName())) + // C++98 [class.union]p1: If a union contains a static data member, + // the program is ill-formed. C++11 drops this restriction. + if (RD->isUnion()) + Diag(D.getIdentifierLoc(), + getLangOpts().CPlusPlus0x + ? diag::warn_cxx98_compat_static_data_member_in_union + : diag::ext_static_data_member_in_union) << Name; + // We conservatively disallow static data members in anonymous structs. + else if (!RD->getDeclName()) Diag(D.getIdentifierLoc(), - diag::err_static_data_member_not_allowed_in_union_or_anon_struct) + diag::err_static_data_member_not_allowed_in_anon_struct) << Name << RD->isUnion(); } } @@ -3858,7 +4013,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, bool Invalid = false; if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( - D.getDeclSpec().getSourceRange().getBegin(), + D.getDeclSpec().getLocStart(), D.getIdentifierLoc(), D.getCXXScopeSpec(), TemplateParamLists.get(), @@ -3884,7 +4039,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } - NewVD = VarDecl::Create(Context, DC, D.getSourceRange().getBegin(), + NewVD = VarDecl::Create(Context, DC, D.getLocStart(), D.getIdentifierLoc(), II, R, TInfo, SC, SCAsWritten); @@ -3905,38 +4060,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, TemplateParamLists.release()); } - if (D.getDeclSpec().isConstexprSpecified()) { - // FIXME: once we know whether there's an initializer, apply this to - // static data members too. - if (!NewVD->isStaticDataMember() && - !NewVD->isThisDeclarationADefinition()) { - // 'constexpr' is redundant and ill-formed on a non-defining declaration - // of a variable. Suggest replacing it with 'const' if appropriate. - SourceLocation ConstexprLoc = D.getDeclSpec().getConstexprSpecLoc(); - SourceRange ConstexprRange(ConstexprLoc, ConstexprLoc); - // If the declarator is complex, we need to move the keyword to the - // innermost chunk as we switch it from 'constexpr' to 'const'. - int Kind = DeclaratorChunk::Paren; - for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) { - Kind = D.getTypeObject(I).Kind; - if (Kind != DeclaratorChunk::Paren) - break; - } - if ((D.getDeclSpec().getTypeQualifiers() & DeclSpec::TQ_const) || - Kind == DeclaratorChunk::Reference) - Diag(ConstexprLoc, diag::err_invalid_constexpr_var_decl) - << FixItHint::CreateRemoval(ConstexprRange); - else if (Kind == DeclaratorChunk::Paren) - Diag(ConstexprLoc, diag::err_invalid_constexpr_var_decl) - << FixItHint::CreateReplacement(ConstexprRange, "const"); - else - Diag(ConstexprLoc, diag::err_invalid_constexpr_var_decl) - << FixItHint::CreateRemoval(ConstexprRange) - << FixItHint::CreateInsertion(D.getIdentifierLoc(), "const "); - } else { - NewVD->setConstexpr(true); - } - } + if (D.getDeclSpec().isConstexprSpecified()) + NewVD->setConstexpr(true); } // Set the lexical context. If the declarator has a C++ scope specifier, the @@ -3971,7 +4096,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // In auto-retain/release, infer strong retension for variables of // retainable type. - if (getLangOptions().ObjCAutoRefCount && inferObjCARCLifetime(NewVD)) + if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewVD)) NewVD->setInvalidDecl(); // Handle GNU asm-label extension (encoded as an attribute). @@ -3999,6 +4124,13 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context, Label)); + } else if (!ExtnameUndeclaredIdentifiers.empty()) { + llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I = + ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier()); + if (I != ExtnameUndeclaredIdentifiers.end()) { + NewVD->addAttr(I->second); + ExtnameUndeclaredIdentifiers.erase(I); + } } // Diagnose shadowed variables before filtering for scope. @@ -4011,7 +4143,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, FilterLookupForScope(Previous, DC, S, NewVD->hasLinkage(), isExplicitSpecialization); - if (!getLangOptions().CPlusPlus) { + if (!getLangOpts().CPlusPlus) { D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); } else { // Merge the decl with the existing one if appropriate. @@ -4204,7 +4336,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, if (NewVD->hasLocalStorage() && T.isObjCGCWeak() && !NewVD->hasAttr<BlocksAttr>()) { - if (getLangOptions().getGC() != LangOptions::NonGC) + if (getLangOpts().getGC() != LangOptions::NonGC) Diag(NewVD->getLocation(), diag::warn_gc_attribute_weak_on_local); else Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local); @@ -4284,20 +4416,9 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, return false; } - // Function pointers and references cannot have qualified function type, only - // function pointer-to-members can do that. - QualType Pointee; - unsigned PtrOrRef = 0; - if (const PointerType *Ptr = T->getAs<PointerType>()) - Pointee = Ptr->getPointeeType(); - else if (const ReferenceType *Ref = T->getAs<ReferenceType>()) { - Pointee = Ref->getPointeeType(); - PtrOrRef = 1; - } - if (!Pointee.isNull() && Pointee->isFunctionProtoType() && - Pointee->getAs<FunctionProtoType>()->getTypeQuals() != 0) { - Diag(NewVD->getLocation(), diag::err_invalid_qualified_function_pointer) - << PtrOrRef; + if (NewVD->isConstexpr() && !T->isDependentType() && + RequireLiteralType(NewVD->getLocation(), T, + PDiag(diag::err_constexpr_var_non_literal))) { NewVD->setInvalidDecl(); return false; } @@ -4387,6 +4508,33 @@ namespace { }; } +namespace { + +// Callback to only accept typo corrections that have a non-zero edit distance. +// Also only accept corrections that have the same parent decl. +class DifferentNameValidatorCCC : public CorrectionCandidateCallback { + public: + DifferentNameValidatorCCC(CXXRecordDecl *Parent) + : ExpectedParent(Parent ? Parent->getCanonicalDecl() : 0) {} + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + if (candidate.getEditDistance() == 0) + return false; + + if (CXXMethodDecl *MD = candidate.getCorrectionDeclAs<CXXMethodDecl>()) { + CXXRecordDecl *Parent = MD->getParent(); + return Parent && Parent->getCanonicalDecl() == ExpectedParent; + } + + return !ExpectedParent; + } + + private: + CXXRecordDecl *ExpectedParent; +}; + +} + /// \brief Generate diagnostics for an invalid function redeclaration. /// /// This routine handles generating the diagnostic messages for an invalid @@ -4407,7 +4555,7 @@ static NamedDecl* DiagnoseInvalidRedeclaration( llvm::SmallVector<unsigned, 1> MismatchedParams; llvm::SmallVector<std::pair<FunctionDecl*, unsigned>, 1> NearMatches; TypoCorrection Correction; - bool isFriendDecl = (SemaRef.getLangOptions().CPlusPlus && + bool isFriendDecl = (SemaRef.getLangOpts().CPlusPlus && ExtraArgs.D.getDeclSpec().isFriendSpecified()); unsigned DiagMsg = isFriendDecl ? diag::err_no_matching_local_friend : diag::err_member_def_does_not_match; @@ -4416,6 +4564,8 @@ static NamedDecl* DiagnoseInvalidRedeclaration( SemaRef.LookupQualifiedName(Prev, NewDC); assert(!Prev.isAmbiguous() && "Cannot have an ambiguity in previous-declaration lookup"); + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD); + DifferentNameValidatorCCC Validator(MD ? MD->getParent() : 0); if (!Prev.empty()) { for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end(); Func != FuncEnd; ++Func) { @@ -4431,8 +4581,8 @@ static NamedDecl* DiagnoseInvalidRedeclaration( } // If the qualified name lookup yielded nothing, try typo correction } else if ((Correction = SemaRef.CorrectTypo(Prev.getLookupNameInfo(), - Prev.getLookupKind(), 0, 0, NewDC)) && - Correction.getCorrection() != Name) { + Prev.getLookupKind(), 0, 0, + Validator, NewDC))) { // Trap errors. Sema::SFINAETrap Trap(SemaRef); @@ -4454,12 +4604,11 @@ static NamedDecl* DiagnoseInvalidRedeclaration( // TODO: Refactor ActOnFunctionDeclarator so that we can call only the // pieces need to verify the typo-corrected C++ declaraction and hopefully // eliminate the need for the parameter pack ExtraArgs. - Result = SemaRef.ActOnFunctionDeclarator(ExtraArgs.S, ExtraArgs.D, - NewFD->getDeclContext(), - NewFD->getTypeSourceInfo(), - Previous, - ExtraArgs.TemplateParamLists, - ExtraArgs.AddToScope); + Result = SemaRef.ActOnFunctionDeclarator( + ExtraArgs.S, ExtraArgs.D, + Correction.getCorrectionDecl()->getDeclContext(), + NewFD->getTypeSourceInfo(), Previous, ExtraArgs.TemplateParamLists, + ExtraArgs.AddToScope); if (Trap.hasErrorOccurred()) { // Pretend the typo correction never occurred ExtraArgs.D.SetIdentifier(Name.getAsIdentifierInfo(), @@ -4487,10 +4636,10 @@ static NamedDecl* DiagnoseInvalidRedeclaration( if (Correction) SemaRef.Diag(NewFD->getLocation(), DiagMsg) - << Name << NewDC << Correction.getQuoted(SemaRef.getLangOptions()) + << Name << NewDC << Correction.getQuoted(SemaRef.getLangOpts()) << FixItHint::CreateReplacement( NewFD->getLocation(), - Correction.getAsString(SemaRef.getLangOptions())); + Correction.getAsString(SemaRef.getLangOpts())); else SemaRef.Diag(NewFD->getLocation(), DiagMsg) << Name << NewDC << NewFD->getLocation(); @@ -4509,12 +4658,13 @@ static NamedDecl* DiagnoseInvalidRedeclaration( if (unsigned Idx = NearMatch->second) { ParmVarDecl *FDParam = FD->getParamDecl(Idx-1); - SemaRef.Diag(FDParam->getTypeSpecStartLoc(), - diag::note_member_def_close_param_match) + SourceLocation Loc = FDParam->getTypeSpecStartLoc(); + if (Loc.isInvalid()) Loc = FD->getLocation(); + SemaRef.Diag(Loc, diag::note_member_def_close_param_match) << Idx << FDParam->getType() << NewFD->getParamDecl(Idx-1)->getType(); } else if (Correction) { SemaRef.Diag(FD->getLocation(), diag::note_previous_decl) - << Correction.getQuoted(SemaRef.getLangOptions()); + << Correction.getQuoted(SemaRef.getLangOpts()); } else if (FDisConst != NewFDisConst) { SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) << NewFDisConst << FD->getSourceRange().getEnd(); @@ -4524,7 +4674,8 @@ static NamedDecl* DiagnoseInvalidRedeclaration( return Result; } -static FunctionDecl::StorageClass getFunctionStorageClass(Sema &SemaRef, Declarator &D) { +static FunctionDecl::StorageClass getFunctionStorageClass(Sema &SemaRef, + Declarator &D) { switch (D.getDeclSpec().getStorageClassSpec()) { default: llvm_unreachable("Unknown storage class!"); case DeclSpec::SCS_auto: @@ -4570,7 +4721,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, FunctionDecl::StorageClass SCAsWritten = StorageClassSpecToFunctionDeclStorageClass(SCSpec); - if (!SemaRef.getLangOptions().CPlusPlus) { + if (!SemaRef.getLangOpts().CPlusPlus) { // Determine whether the function was written with a // prototype. This true when: // - there is a prototype in the declarator, or @@ -4580,8 +4731,9 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) || (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType()); - NewFD = FunctionDecl::Create(SemaRef.Context, DC, D.getSourceRange().getBegin(), - NameInfo, R, TInfo, SC, SCAsWritten, isInline, + NewFD = FunctionDecl::Create(SemaRef.Context, DC, + D.getLocStart(), NameInfo, R, + TInfo, SC, SCAsWritten, isInline, HasPrototype); if (D.isInvalidType()) NewFD->setInvalidDecl(); @@ -4612,7 +4764,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, R = SemaRef.CheckConstructorDeclarator(D, R, SC); return CXXConstructorDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC), - D.getSourceRange().getBegin(), NameInfo, + D.getLocStart(), NameInfo, R, TInfo, isExplicit, isInline, /*isImplicitlyDeclared=*/false, isConstexpr); @@ -4624,14 +4776,14 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); CXXDestructorDecl *NewDD = CXXDestructorDecl::Create( SemaRef.Context, Record, - D.getSourceRange().getBegin(), + D.getLocStart(), NameInfo, R, TInfo, isInline, /*isImplicitlyDeclared=*/false); // If the class is complete, then we now create the implicit exception // specification. If the class is incomplete or dependent, we can't do // it yet. - if (SemaRef.getLangOptions().CPlusPlus0x && !Record->isDependentType() && + if (SemaRef.getLangOpts().CPlusPlus0x && !Record->isDependentType() && Record->getDefinition() && !Record->isBeingDefined() && R->getAs<FunctionProtoType>()->getExceptionSpecType() == EST_None) { SemaRef.AdjustDestructorExceptionSpec(Record, NewDD); @@ -4647,7 +4799,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, // Create a FunctionDecl to satisfy the function definition parsing // code path. return FunctionDecl::Create(SemaRef.Context, DC, - D.getSourceRange().getBegin(), + D.getLocStart(), D.getIdentifierLoc(), Name, R, TInfo, SC, SCAsWritten, isInline, /*hasPrototype=*/true, isConstexpr); @@ -4663,7 +4815,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, SemaRef.CheckConversionDeclarator(D, R, SC); IsVirtualOkay = true; return CXXConversionDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC), - D.getSourceRange().getBegin(), NameInfo, + D.getLocStart(), NameInfo, R, TInfo, isInline, isExplicit, isConstexpr, SourceLocation()); @@ -4699,7 +4851,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, // This is a C++ method declaration. return CXXMethodDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC), - D.getSourceRange().getBegin(), NameInfo, R, + D.getLocStart(), NameInfo, R, TInfo, isStatic, SCAsWritten, isInline, isConstexpr, SourceLocation()); @@ -4708,7 +4860,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, // prototype. This true when: // - we're in C++ (where every function has a prototype), return FunctionDecl::Create(SemaRef.Context, DC, - D.getSourceRange().getBegin(), + D.getLocStart(), NameInfo, R, TInfo, SC, SCAsWritten, isInline, true/*HasPrototype*/, isConstexpr); } @@ -4760,7 +4912,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, isVirtualOkay); if (!NewFD) return 0; - if (getLangOptions().CPlusPlus) { + if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer()) + NewFD->setTopLevelDeclInObjCContainer(); + + if (getLangOpts().CPlusPlus) { bool isInline = D.getDeclSpec().isInlineSpecified(); bool isVirtual = D.getDeclSpec().isVirtualSpecified(); bool isExplicit = D.getDeclSpec().isExplicitSpecified(); @@ -4783,13 +4938,13 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // scope specifier, or is the object of a friend declaration, the // lexical context will be different from the semantic context. NewFD->setLexicalDeclContext(CurContext); - + // Match up the template parameter lists with the scope specifier, then // determine whether we have a template or a template specialization. bool Invalid = false; if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( - D.getDeclSpec().getSourceRange().getBegin(), + D.getDeclSpec().getLocStart(), D.getIdentifierLoc(), D.getCXXScopeSpec(), TemplateParamLists.get(), @@ -4811,7 +4966,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } // If we're adding a template to a dependent context, we may need to - // rebuilding some of the types used within the template parameter list, + // rebuilding some of the types used within the template parameter list, // now that we know what the current instantiation is. if (DC->isDependentContext()) { ContextRAII SavedContext(*this, DC); @@ -4880,6 +5035,56 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, FunctionTemplate->setInvalidDecl(); } + // If we see "T var();" at block scope, where T is a class type, it is + // probably an attempt to initialize a variable, not a function declaration. + // We don't catch this case earlier, since there is no ambiguity here. + if (!FunctionTemplate && D.getFunctionDefinitionKind() == FDK_Declaration && + CurContext->isFunctionOrMethod() && + D.getNumTypeObjects() == 1 && D.isFunctionDeclarator() && + D.getDeclSpec().getStorageClassSpecAsWritten() + == DeclSpec::SCS_unspecified) { + QualType T = R->getAs<FunctionType>()->getResultType(); + DeclaratorChunk &C = D.getTypeObject(0); + if (!T->isVoidType() && C.Fun.NumArgs == 0 && !C.Fun.isVariadic && + !C.Fun.TrailingReturnType && + C.Fun.getExceptionSpecType() == EST_None) { + SourceRange ParenRange(C.Loc, C.EndLoc); + Diag(C.Loc, diag::warn_empty_parens_are_function_decl) << ParenRange; + + // If the declaration looks like: + // T var1, + // f(); + // and name lookup finds a function named 'f', then the ',' was + // probably intended to be a ';'. + if (!D.isFirstDeclarator() && D.getIdentifier()) { + FullSourceLoc Comma(D.getCommaLoc(), SourceMgr); + FullSourceLoc Name(D.getIdentifierLoc(), SourceMgr); + if (Comma.getFileID() != Name.getFileID() || + Comma.getSpellingLineNumber() != Name.getSpellingLineNumber()) { + LookupResult Result(*this, D.getIdentifier(), SourceLocation(), + LookupOrdinaryName); + if (LookupName(Result, S)) + Diag(D.getCommaLoc(), diag::note_empty_parens_function_call) + << FixItHint::CreateReplacement(D.getCommaLoc(), ";") << NewFD; + } + } + const CXXRecordDecl *RD = T->getAsCXXRecordDecl(); + // Empty parens mean value-initialization, and no parens mean default + // initialization. These are equivalent if the default constructor is + // user-provided, or if zero-initialization is a no-op. + if (RD && RD->hasDefinition() && + (RD->isEmpty() || RD->hasUserProvidedDefaultConstructor())) + Diag(C.Loc, diag::note_empty_parens_default_ctor) + << FixItHint::CreateRemoval(ParenRange); + else if (const char *Init = getFixItZeroInitializerForType(T)) + Diag(C.Loc, diag::note_empty_parens_zero_initialize) + << FixItHint::CreateReplacement(ParenRange, Init); + else if (LangOpts.CPlusPlus0x) + Diag(C.Loc, diag::note_empty_parens_zero_initialize) + << FixItHint::CreateReplacement(ParenRange, "{}"); + } + } + // C++ [dcl.fct.spec]p5: // The virtual specifier shall only be used in declarations of // nonstatic class member functions that appear within a @@ -4907,7 +5112,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } // C++ [dcl.fct.spec]p3: - // The inline specifier shall not appear on a block scope function declaration. + // The inline specifier shall not appear on a block scope function + // declaration. if (isInline && !NewFD->isInvalidDecl()) { if (CurContext->isFunctionOrMethod()) { // 'inline' is not allowed on block scope function declaration. @@ -4919,8 +5125,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // C++ [dcl.fct.spec]p6: // The explicit specifier shall be used only in the declaration of a - // constructor or conversion function within its class definition; see 12.3.1 - // and 12.3.2. + // constructor or conversion function within its class definition; + // see 12.3.1 and 12.3.2. if (isExplicit && !NewFD->isInvalidDecl()) { if (!CurContext->isRecord()) { // 'explicit' was specified outside of the class. @@ -4974,10 +5180,26 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->setAccess(AS_public); } + // If a function is defined as defaulted or deleted, mark it as such now. + switch (D.getFunctionDefinitionKind()) { + case FDK_Declaration: + case FDK_Definition: + break; + + case FDK_Defaulted: + NewFD->setDefaulted(); + break; + + case FDK_Deleted: + NewFD->setDeletedAsWritten(); + break; + } + if (isa<CXXMethodDecl>(NewFD) && DC == CurContext && D.isFunctionDefinition()) { - // A method is implicitly inline if it's defined in its class - // definition. + // C++ [class.mfct]p2: + // A member function may be defined (8.4) in its class definition, in + // which case it is an inline member function (7.1.2) NewFD->setImplicitlyInline(); } @@ -5007,6 +5229,13 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, StringLiteral *SE = cast<StringLiteral>(E); NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context, SE->getString())); + } else if (!ExtnameUndeclaredIdentifiers.empty()) { + llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I = + ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier()); + if (I != ExtnameUndeclaredIdentifiers.end()) { + NewFD->addAttr(I->second); + ExtnameUndeclaredIdentifiers.erase(I); + } } // Copy the parameter declarations from the declarator D to the function @@ -5028,7 +5257,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // In C++, the empty parameter-type-list must be spelled "void"; a // typedef of void is not permitted. - if (getLangOptions().CPlusPlus && + if (getLangOpts().CPlusPlus && Param->getType().getUnqualifiedType() != Context.VoidTy) { bool IsTypeAlias = false; if (const TypedefType *TT = Param->getType()->getAs<TypedefType>()) @@ -5077,25 +5306,35 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Finally, we know we have the right number of parameters, install them. NewFD->setParams(Params); + // Find all anonymous symbols defined during the declaration of this function + // and add to NewFD. This lets us track decls such 'enum Y' in: + // + // void f(enum Y {AA} x) {} + // + // which would otherwise incorrectly end up in the translation unit scope. + NewFD->setDeclsInPrototypeScope(DeclsInPrototypeScope); + DeclsInPrototypeScope.clear(); + // Process the non-inheritable attributes on this declaration. ProcessDeclAttributes(S, NewFD, D, /*NonInheritable=*/true, /*Inheritable=*/false); - if (!getLangOptions().CPlusPlus) { + // Functions returning a variably modified type violate C99 6.7.5.2p2 + // because all functions have linkage. + if (!NewFD->isInvalidDecl() && + NewFD->getResultType()->isVariablyModifiedType()) { + Diag(NewFD->getLocation(), diag::err_vm_func_decl); + NewFD->setInvalidDecl(); + } + + if (!getLangOpts().CPlusPlus) { // Perform semantic checking on the function declaration. bool isExplicitSpecialization=false; if (!NewFD->isInvalidDecl()) { - if (NewFD->getResultType()->isVariablyModifiedType()) { - // Functions returning a variably modified type violate C99 6.7.5.2p2 - // because all functions have linkage. - Diag(NewFD->getLocation(), diag::err_vm_func_decl); - NewFD->setInvalidDecl(); - } else { - if (NewFD->isMain()) - CheckMain(NewFD, D.getDeclSpec()); - D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, - isExplicitSpecialization)); - } + if (NewFD->isMain()) + CheckMain(NewFD, D.getDeclSpec()); + D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, + isExplicitSpecialization)); } assert((NewFD->isInvalidDecl() || !D.isRedeclaration() || Previous.getResultKind() != LookupResult::FoundOverloaded) && @@ -5135,8 +5374,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header) << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc) << FixItHint::CreateInsertion( - D.getDeclSpec().getSourceRange().getBegin(), - "template<> "); + D.getDeclSpec().getLocStart(), + "template<> "); isFunctionTemplateSpecialization = true; } else { // "friend void foo<>(int);" is an implicit specialization decl. @@ -5173,7 +5412,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (CurContext->isDependentContext() && CurContext->isRecord() && !isFriend) { isDependentClassScopeExplicitSpecialization = true; - Diag(NewFD->getLocation(), getLangOptions().MicrosoftExt ? + Diag(NewFD->getLocation(), getLangOpts().MicrosoftExt ? diag::ext_function_specialization_in_class : diag::err_function_specialization_in_class) << NewFD->getDeclName(); @@ -5224,10 +5463,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Previous.getResultKind() != LookupResult::FoundOverloaded) && "previous declaration set still overloaded"); - if (NewFD->isConstexpr() && !NewFD->isInvalidDecl() && - !CheckConstexprFunctionDecl(NewFD, CCK_Declaration)) - NewFD->setInvalidDecl(); - NamedDecl *PrincipalDecl = (FunctionTemplate ? cast<NamedDecl>(FunctionTemplate) : NewFD); @@ -5235,7 +5470,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (isFriend && D.isRedeclaration()) { AccessSpecifier Access = AS_public; if (!NewFD->isInvalidDecl()) - Access = NewFD->getPreviousDeclaration()->getAccess(); + Access = NewFD->getPreviousDecl()->getAccess(); NewFD->setAccess(Access); if (FunctionTemplate) FunctionTemplate->setAccess(Access); @@ -5250,9 +5485,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // If we have a function template, check the template parameter // list. This will check and merge default template arguments. if (FunctionTemplate) { - FunctionTemplateDecl *PrevTemplate = FunctionTemplate->getPreviousDeclaration(); + FunctionTemplateDecl *PrevTemplate = + FunctionTemplate->getPreviousDecl(); CheckTemplateParameterList(FunctionTemplate->getTemplateParameters(), - PrevTemplate? PrevTemplate->getTemplateParameters() : 0, + PrevTemplate ? PrevTemplate->getTemplateParameters() : 0, D.getDeclSpec().isFriendSpecified() ? (D.isFunctionDefinition() ? TPC_FriendFunctionTemplateDefinition @@ -5331,8 +5567,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // definition (C++ [dcl.meaning]p1). // 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 extension - // for compatibility with old SWIG code which likes to generate them. + // C++ [temp.expl.spec]p2. We also allow these declarations as an + // extension for compatibility with old SWIG code which likes to + // generate them. Diag(NewFD->getLocation(), diag::ext_out_of_line_declaration) << D.getCXXScopeSpec().getRange(); } @@ -5393,7 +5630,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Set this FunctionDecl's range up to the right paren. NewFD->setRangeEnd(D.getSourceRange().getEnd()); - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { if (FunctionTemplate) { if (NewFD->isInvalidDecl()) FunctionTemplate->setInvalidDecl(); @@ -5403,7 +5640,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, MarkUnusedFileScopedDecl(NewFD); - if (getLangOptions().CUDA) + if (getLangOpts().CUDA) if (IdentifierInfo *II = NewFD->getIdentifier()) if (!NewFD->isInvalidDecl() && NewFD->getDeclContext()->getRedeclContext()->isTranslationUnit()) { @@ -5493,7 +5730,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, break; } - if (!getLangOptions().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) { + if (!getLangOpts().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) { // If a function name is overloadable in C, then every function // with that name must be marked "overloadable". Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing) @@ -5514,7 +5751,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, if (Redeclaration) { // NewFD and OldDecl represent declarations that need to be // merged. - if (MergeFunctionDecl(NewFD, OldDecl)) { + if (MergeFunctionDecl(NewFD, OldDecl, S)) { NewFD->setInvalidDecl(); return Redeclaration; } @@ -5524,7 +5761,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, if (FunctionTemplateDecl *OldTemplateDecl = dyn_cast<FunctionTemplateDecl>(OldDecl)) { - NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl()); + NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl()); FunctionTemplateDecl *NewTemplateDecl = NewFD->getDescribedFunctionTemplate(); assert(NewTemplateDecl && "Template/non-template mismatch"); @@ -5542,9 +5779,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, assert(OldTemplateDecl->isMemberSpecialization()); } - if (OldTemplateDecl->isModulePrivate()) - NewTemplateDecl->setModulePrivate(); - } else { if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions NewFD->setAccess(OldDecl->getAccess()); @@ -5554,7 +5788,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } // Semantic checking for this function declaration (in isolation). - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { // C++-specific checks. if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) { CheckConstructor(Constructor); @@ -5633,29 +5867,59 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, Context.BuiltinInfo.ForgetBuiltin(BuiltinID, Context.Idents); } } + + // If this function is declared as being extern "C", then check to see if + // the function returns a UDT (class, struct, or union type) that is not C + // compatible, and if it does, warn the user. + if (NewFD->isExternC()) { + QualType R = NewFD->getResultType(); + if (!R.isPODType(Context) && + !R->isVoidType()) + Diag( NewFD->getLocation(), diag::warn_return_value_udt ) + << NewFD << R; + } } return Redeclaration; } void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { - // C++ [basic.start.main]p3: A program that declares main to be inline - // or static is ill-formed. + // C++11 [basic.start.main]p3: A program that declares main to be inline, + // static or constexpr is ill-formed. // C99 6.7.4p4: In a hosted environment, the inline function specifier // shall not appear in a declaration of main. // static main is not an error under C99, but we should warn about it. if (FD->getStorageClass() == SC_Static) - Diag(DS.getStorageClassSpecLoc(), getLangOptions().CPlusPlus + Diag(DS.getStorageClassSpecLoc(), getLangOpts().CPlusPlus ? diag::err_static_main : diag::warn_static_main) << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc()); if (FD->isInlineSpecified()) Diag(DS.getInlineSpecLoc(), diag::err_inline_main) << FixItHint::CreateRemoval(DS.getInlineSpecLoc()); + if (FD->isConstexpr()) { + Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_main) + << FixItHint::CreateRemoval(DS.getConstexprSpecLoc()); + FD->setConstexpr(false); + } QualType T = FD->getType(); assert(T->isFunctionType() && "function decl is not of function type"); - const FunctionType* FT = T->getAs<FunctionType>(); - - if (!Context.hasSameUnqualifiedType(FT->getResultType(), Context.IntTy)) { + const FunctionType* FT = T->castAs<FunctionType>(); + + // All the standards say that main() should should return 'int'. + if (Context.hasSameUnqualifiedType(FT->getResultType(), Context.IntTy)) { + // 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); + + // Otherwise, this is just a flat-out error. + } else { Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint); FD->setInvalidDecl(true); } @@ -5786,7 +6050,8 @@ namespace { void VisitMemberExpr(MemberExpr *E) { if (E->getType()->canDecayToPointerType()) return; - if (isa<FieldDecl>(E->getMemberDecl())) + ValueDecl *VD = E->getMemberDecl(); + if (isa<FieldDecl>(VD) || isa<CXXMethodDecl>(VD)) if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->getBase()->IgnoreParenImpCasts())) { HandleDeclRefExpr(DRE); @@ -5844,17 +6109,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, if (RealDecl == 0 || RealDecl->isInvalidDecl()) return; - // Check for self-references within variable initializers. - if (VarDecl *vd = dyn_cast<VarDecl>(RealDecl)) { - // Variables declared within a function/method body are handled - // by a dataflow analysis. - if (!vd->hasLocalStorage() && !vd->isStaticLocal()) - CheckSelfReference(RealDecl, Init); - } - else { - CheckSelfReference(RealDecl, Init); - } - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) { // With declarators parsed the way they are, the parser cannot // distinguish between a normal initializer and a pure-specifier. @@ -5879,48 +6133,88 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, return; } - // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. + // Check for self-references within variable initializers. + // Variables declared within a function/method body are handled + // by a dataflow analysis. + if (!VDecl->hasLocalStorage() && !VDecl->isStaticLocal()) + CheckSelfReference(RealDecl, Init); + + ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); + + // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) { + Expr *DeduceInit = Init; + // Initializer could be a C++ direct-initializer. Deduction only works if it + // contains exactly one expression. + if (CXXDirectInit) { + if (CXXDirectInit->getNumExprs() == 0) { + // It isn't possible to write this directly, but it is possible to + // end up in this situation with "auto x(some_pack...);" + Diag(CXXDirectInit->getLocStart(), + diag::err_auto_var_init_no_expression) + << VDecl->getDeclName() << VDecl->getType() + << VDecl->getSourceRange(); + RealDecl->setInvalidDecl(); + return; + } else if (CXXDirectInit->getNumExprs() > 1) { + Diag(CXXDirectInit->getExpr(1)->getLocStart(), + diag::err_auto_var_init_multiple_expressions) + << VDecl->getDeclName() << VDecl->getType() + << VDecl->getSourceRange(); + RealDecl->setInvalidDecl(); + return; + } else { + DeduceInit = CXXDirectInit->getExpr(0); + } + } TypeSourceInfo *DeducedType = 0; - if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType)) - Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure) - << VDecl->getDeclName() << VDecl->getType() << Init->getType() - << Init->getSourceRange(); + if (DeduceAutoType(VDecl->getTypeSourceInfo(), DeduceInit, DeducedType) == + DAR_Failed) + DiagnoseAutoDeductionFailure(VDecl, DeduceInit); if (!DeducedType) { RealDecl->setInvalidDecl(); return; } VDecl->setTypeSourceInfo(DeducedType); VDecl->setType(DeducedType->getType()); - + VDecl->ClearLinkageCache(); + // In ARC, infer lifetime. - if (getLangOptions().ObjCAutoRefCount && inferObjCARCLifetime(VDecl)) + if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl)) VDecl->setInvalidDecl(); // If this is a redeclaration, check that the type we just deduced matches // the previously declared type. - if (VarDecl *Old = VDecl->getPreviousDeclaration()) + if (VarDecl *Old = VDecl->getPreviousDecl()) MergeVarDeclTypes(VDecl, Old); } - - // A definition must end up with a complete type, which means it must be - // complete with the restriction that an array type might be completed by the - // initializer; note that later code assumes this restriction. - QualType BaseDeclType = VDecl->getType(); - if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType)) - BaseDeclType = Array->getElementType(); - if (RequireCompleteType(VDecl->getLocation(), BaseDeclType, - diag::err_typecheck_decl_incomplete_type)) { - RealDecl->setInvalidDecl(); + 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); + VDecl->setInvalidDecl(); return; } - // The variable can not have an abstract class type. - if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(), - diag::err_abstract_type_in_decl, - AbstractVariableType)) - VDecl->setInvalidDecl(); + if (!VDecl->getType()->isDependentType()) { + // A definition must end up with a complete type, which means it must be + // complete with the restriction that an array type might be completed by + // the initializer; note that later code assumes this restriction. + QualType BaseDeclType = VDecl->getType(); + if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType)) + BaseDeclType = Array->getElementType(); + if (RequireCompleteType(VDecl->getLocation(), BaseDeclType, + diag::err_typecheck_decl_incomplete_type)) { + RealDecl->setInvalidDecl(); + return; + } + + // The variable can not have an abstract class type. + if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(), + diag::err_abstract_type_in_decl, + AbstractVariableType)) + VDecl->setInvalidDecl(); + } const VarDecl *Def; if ((Def = VDecl->getDefinition()) && Def != VDecl) { @@ -5932,7 +6226,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, } const VarDecl* PrevInit = 0; - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { // C++ [class.static.data]p4 // If a static data member is of const integral or const // enumeration type, its declaration in the class definition can @@ -5946,7 +6240,8 @@ 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(VDecl->getLocation(), diag::err_redefinition) + << VDecl->getDeclName(); Diag(PrevInit->getLocation(), diag::note_previous_definition); return; } @@ -5968,44 +6263,77 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, return; } - // Capture the variable that is being initialized and the style of - // initialization. - InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); - - // FIXME: Poor source location information. - InitializationKind Kind - = DirectInit? InitializationKind::CreateDirect(VDecl->getLocation(), - Init->getLocStart(), - Init->getLocEnd()) - : InitializationKind::CreateCopy(VDecl->getLocation(), - Init->getLocStart()); - // Get the decls type and save a reference for later, since // CheckInitializerTypes may change it. QualType DclT = VDecl->getType(), SavT = DclT; - if (VDecl->isLocalVarDecl()) { - if (VDecl->hasExternalStorage()) { // C99 6.7.8p5 - Diag(VDecl->getLocation(), diag::err_block_extern_cant_init); - VDecl->setInvalidDecl(); - } else if (!VDecl->isInvalidDecl()) { - InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1); - ExprResult Result = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, &Init, 1), - &DclT); + + // Top-level message sends default to 'id' when we're in a debugger + // and we are assigning it to a variable of 'id' type. + if (getLangOpts().DebuggerCastResultToId && DclT->isObjCIdType()) + if (Init->getType() == Context.UnknownAnyTy && isa<ObjCMessageExpr>(Init)) { + ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType()); if (Result.isInvalid()) { VDecl->setInvalidDecl(); return; } + Init = Result.take(); + } - Init = Result.takeAs<Expr>(); - - // C++ 3.6.2p2, allow dynamic initialization of static initializers. - // Don't check invalid declarations to avoid emitting useless diagnostics. - if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) { - if (VDecl->getStorageClass() == SC_Static) // C99 6.7.8p4. - CheckForConstantInitializer(Init, DclT); - } + // Perform the initialization. + if (!VDecl->isInvalidDecl()) { + InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); + InitializationKind Kind + = DirectInit ? + CXXDirectInit ? InitializationKind::CreateDirect(VDecl->getLocation(), + Init->getLocStart(), + Init->getLocEnd()) + : InitializationKind::CreateDirectList( + VDecl->getLocation()) + : InitializationKind::CreateCopy(VDecl->getLocation(), + Init->getLocStart()); + + Expr **Args = &Init; + unsigned NumArgs = 1; + if (CXXDirectInit) { + Args = CXXDirectInit->getExprs(); + NumArgs = CXXDirectInit->getNumExprs(); + } + InitializationSequence InitSeq(*this, Entity, Kind, Args, NumArgs); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, Args,NumArgs), + &DclT); + if (Result.isInvalid()) { + VDecl->setInvalidDecl(); + return; } + + Init = Result.takeAs<Expr>(); + } + + // If the type changed, it means we had an incomplete type that was + // completed by the initializer. For example: + // int ary[] = { 1, 3, 5 }; + // "ary" transitions from an IncompleteArrayType to a ConstantArrayType. + if (!VDecl->isInvalidDecl() && (DclT != SavT)) + VDecl->setType(DclT); + + // Check any implicit conversions within the expression. + CheckImplicitConversions(Init, VDecl->getLocation()); + + if (!VDecl->isInvalidDecl()) + checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init); + + Init = MaybeCreateExprWithCleanups(Init); + // Attach the initializer to the decl. + VDecl->setInit(Init); + + if (VDecl->isLocalVarDecl()) { + // C99 6.7.8p4: All the expressions in an initializer for an object that has + // static storage duration shall be constant expressions or string literals. + // C++ does not have this restriction. + if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl() && + VDecl->getStorageClass() == SC_Static) + CheckForConstantInitializer(Init, DclT); } else if (VDecl->isStaticDataMember() && VDecl->getLexicalDeclContext()->isRecord()) { // This is an in-class initialization for a static data member, e.g., @@ -6014,26 +6342,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // static const int value = 17; // }; - // Try to perform the initialization regardless. - if (!VDecl->isInvalidDecl()) { - InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1); - ExprResult Result = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, &Init, 1), - &DclT); - if (Result.isInvalid()) { - VDecl->setInvalidDecl(); - return; - } - - Init = Result.takeAs<Expr>(); - } - // C++ [class.mem]p4: // A member-declarator can contain a constant-initializer only // if it declares a static member (9.4) of const integral or // const enumeration type, see 9.4.2. // - // C++0x [class.static.data]p3: + // C++11 [class.static.data]p3: // If a non-volatile const static data member is of integral or // enumeration type, its declaration in the class definition can // specify a brace-or-equal-initializer in which every initalizer-clause @@ -6042,28 +6356,27 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // with the constexpr specifier; if so, its declaration shall specify a // brace-or-equal-initializer in which every initializer-clause that is // an assignment-expression is a constant expression. - QualType T = VDecl->getType(); // Do nothing on dependent types. - if (T->isDependentType()) { + if (DclT->isDependentType()) { // Allow any 'static constexpr' members, whether or not they are of literal - // type. We separately check that the initializer is a constant expression, - // which implicitly requires the member to be of literal type. + // type. We separately check that every constexpr variable is of literal + // type. } else if (VDecl->isConstexpr()) { // Require constness. - } else if (!T.isConstQualified()) { + } else if (!DclT.isConstQualified()) { Diag(VDecl->getLocation(), diag::err_in_class_initializer_non_const) << Init->getSourceRange(); VDecl->setInvalidDecl(); // We allow integer constant expressions in all cases. - } else if (T->isIntegralOrEnumerationType()) { + } else if (DclT->isIntegralOrEnumerationType()) { // Check whether the expression is a constant expression. SourceLocation Loc; - if (getLangOptions().CPlusPlus0x && T.isVolatileQualified()) - // In C++0x, a non-constexpr const static data member with an + if (getLangOpts().CPlusPlus0x && DclT.isVolatileQualified()) + // In C++11, a non-constexpr const static data member with an // in-class initializer cannot be volatile. Diag(VDecl->getLocation(), diag::err_in_class_initializer_volatile); else if (Init->isValueDependent()) @@ -6083,88 +6396,65 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, VDecl->setInvalidDecl(); } - // We allow floating-point constants as an extension. - } else if (T->isFloatingType()) { // also permits complex, which is ok + // We allow foldable floating-point constants as an extension. + } else if (DclT->isFloatingType()) { // also permits complex, which is ok Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type) - << T << Init->getSourceRange(); - if (getLangOptions().CPlusPlus0x) + << DclT << Init->getSourceRange(); + if (getLangOpts().CPlusPlus0x) Diag(VDecl->getLocation(), diag::note_in_class_initializer_float_type_constexpr) << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr "); - if (!Init->isValueDependent() && - !Init->isConstantInitializer(Context, false)) { + if (!Init->isValueDependent() && !Init->isEvaluatable(Context)) { Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant) << Init->getSourceRange(); VDecl->setInvalidDecl(); } - // Suggest adding 'constexpr' in C++0x for literal types. - } else if (getLangOptions().CPlusPlus0x && T->isLiteralType()) { + // Suggest adding 'constexpr' in C++11 for literal types. + } else if (getLangOpts().CPlusPlus0x && DclT->isLiteralType()) { Diag(VDecl->getLocation(), diag::err_in_class_initializer_literal_type) - << T << Init->getSourceRange() + << DclT << Init->getSourceRange() << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr "); VDecl->setConstexpr(true); } else { Diag(VDecl->getLocation(), diag::err_in_class_initializer_bad_type) - << T << Init->getSourceRange(); + << DclT << Init->getSourceRange(); VDecl->setInvalidDecl(); } } else if (VDecl->isFileVarDecl()) { - if (VDecl->getStorageClassAsWritten() == SC_Extern && - (!getLangOptions().CPlusPlus || + if (VDecl->getStorageClassAsWritten() == SC_Extern && + (!getLangOpts().CPlusPlus || !Context.getBaseElementType(VDecl->getType()).isConstQualified())) Diag(VDecl->getLocation(), diag::warn_extern_init); - if (!VDecl->isInvalidDecl()) { - InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1); - ExprResult Result = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, &Init, 1), - &DclT); - if (Result.isInvalid()) { - VDecl->setInvalidDecl(); - return; - } - Init = Result.takeAs<Expr>(); - } - - // C++ 3.6.2p2, allow dynamic initialization of static initializers. - // Don't check invalid declarations to avoid emitting useless diagnostics. - if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) { - // C99 6.7.8p4. All file scoped initializers need to be constant. + // C99 6.7.8p4. All file scoped initializers need to be constant. + if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl()) CheckForConstantInitializer(Init, DclT); - } - } - // If the type changed, it means we had an incomplete type that was - // completed by the initializer. For example: - // int ary[] = { 1, 3, 5 }; - // "ary" transitions from a VariableArrayType to a ConstantArrayType. - if (!VDecl->isInvalidDecl() && (DclT != SavT)) { - VDecl->setType(DclT); - Init->setType(DclT); } - - // Check any implicit conversions within the expression. - CheckImplicitConversions(Init, VDecl->getLocation()); - - if (!VDecl->isInvalidDecl()) - checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init); - if (VDecl->isConstexpr() && !VDecl->isInvalidDecl() && - !VDecl->getType()->isDependentType() && - !Init->isTypeDependent() && !Init->isValueDependent() && - !Init->isConstantInitializer(Context, - VDecl->getType()->isReferenceType())) { - // FIXME: Improve this diagnostic to explain why the initializer is not - // a constant expression. - Diag(VDecl->getLocation(), diag::err_constexpr_var_requires_const_init) - << VDecl << Init->getSourceRange(); + // We will represent direct-initialization similarly to copy-initialization: + // int x(1); -as-> int x = 1; + // ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c); + // + // Clients that want to distinguish between the two forms, can check for + // direct initializer using VarDecl::getInitStyle(). + // A major benefit is that clients that don't particularly care about which + // exactly form was it (like the CodeGen) can handle both cases without + // special case code. + + // C++ 8.5p11: + // The form of initialization (using parentheses or '=') is generally + // insignificant, but does matter when the entity being initialized has a + // class type. + if (CXXDirectInit) { + assert(DirectInit && "Call-style initializer must be direct init."); + VDecl->setInitStyle(VarDecl::CallInit); + } else if (DirectInit) { + // This must be list-initialization. No other way is direct-initialization. + VDecl->setInitStyle(VarDecl::ListInit); } - - Init = MaybeCreateExprWithCleanups(Init); - // Attach the initializer to the decl. - VDecl->setInit(Init); CheckCompleteVariableDeclaration(VDecl); } @@ -6218,7 +6508,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) { QualType Type = Var->getType(); - // C++0x [dcl.spec.auto]p3 + // C++11 [dcl.spec.auto]p3 if (TypeMayContainAuto && Type->getContainedAutoType()) { Diag(Var->getLocation(), diag::err_auto_var_requires_init) << Var->getDeclName() << Type; @@ -6226,17 +6516,19 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, return; } - // C++0x [dcl.constexpr]p9: An object or reference declared constexpr must - // have an initializer. - // C++0x [class.static.data]p3: A static data member can be declared with + // C++11 [class.static.data]p3: A static data member can be declared with // the constexpr specifier; if so, its declaration shall specify // a brace-or-equal-initializer. - // - // A static data member's definition may inherit an initializer from an - // in-class declaration. - if (Var->isConstexpr() && !Var->getAnyInitializer()) { - Diag(Var->getLocation(), diag::err_constexpr_var_requires_init) - << Var->getDeclName(); + // C++11 [dcl.constexpr]p1: The constexpr specifier shall be applied only to + // the definition of a variable [...] or the declaration of a static data + // member. + if (Var->isConstexpr() && !Var->isThisDeclarationADefinition()) { + if (Var->isStaticDataMember()) + Diag(Var->getLocation(), + diag::err_constexpr_static_mem_var_requires_init) + << Var->getDeclName(); + else + Diag(Var->getLocation(), diag::err_invalid_constexpr_var_decl); Var->setInvalidDecl(); return; } @@ -6295,7 +6587,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, // is accepted by gcc. Hence here we issue a warning instead of // an error and we do not invalidate the static declaration. // NOTE: to avoid multiple warnings, only check the first declaration. - if (Var->getPreviousDeclaration() == 0) + if (Var->getPreviousDecl() == 0) RequireCompleteType(Var->getLocation(), Type, diag::ext_typecheck_decl_incomplete_type); } @@ -6352,21 +6644,21 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, // Check for jumps past the implicit initializer. C++0x // clarifies that this applies to a "variable with automatic // storage duration", not a "local variable". - // C++0x [stmt.dcl]p3 + // 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 is // ill-formed unless the variable has scalar type, class type with a // trivial default constructor and a trivial destructor, a cv-qualified // version of one of these types, or an array of one of the preceding // types and is declared without an initializer. - if (getLangOptions().CPlusPlus && Var->hasLocalStorage()) { + if (getLangOpts().CPlusPlus && Var->hasLocalStorage()) { if (const RecordType *Record = Context.getBaseElementType(Type)->getAs<RecordType>()) { CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record->getDecl()); - if ((!getLangOptions().CPlusPlus0x && !CXXRecord->isPOD()) || - (getLangOptions().CPlusPlus0x && - (!CXXRecord->hasTrivialDefaultConstructor() || - !CXXRecord->hasTrivialDestructor()))) + // Mark the function for further checking even if the looser rules of + // C++11 do not require such checks, so that we can diagnose + // incompatibilities with C++98. + if (!CXXRecord->isPOD()) getCurFunction()->setHasBranchProtectedScope(); } } @@ -6394,8 +6686,11 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, MultiExprArg(*this, 0, 0)); if (Init.isInvalid()) Var->setInvalidDecl(); - else if (Init.get()) + else if (Init.get()) { Var->setInit(MaybeCreateExprWithCleanups(Init.get())); + // This is important for template substitution. + Var->setInitStyle(VarDecl::CallInit); + } CheckCompleteVariableDeclaration(Var); } @@ -6448,7 +6743,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { // In ARC, don't allow jumps past the implicit initialization of a // local retaining variable. - if (getLangOptions().ObjCAutoRefCount && + if (getLangOpts().ObjCAutoRefCount && var->hasLocalStorage()) { switch (var->getType().getObjCLifetime()) { case Qualifiers::OCL_None: @@ -6464,7 +6759,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { } // All the following checks are C++ only. - if (!getLangOptions().CPlusPlus) return; + if (!getLangOpts().CPlusPlus) return; QualType baseType = Context.getBaseElementType(var->getType()); if (baseType->isDependentType()) return; @@ -6480,7 +6775,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { if (type->isStructureOrClassType()) { SourceLocation poi = var->getLocation(); - Expr *varRef = new (Context) DeclRefExpr(var, type, VK_LValue, poi); + Expr *varRef =new (Context) DeclRefExpr(var, false, type, VK_LValue, poi); ExprResult result = PerformCopyInitialization( InitializedEntity::InitializeBlock(poi, type, false), @@ -6493,15 +6788,41 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { } } - // Check for global constructors. - if (!var->getDeclContext()->isDependentContext() && - var->hasGlobalStorage() && - !var->isStaticLocal() && - var->getInit() && - !var->getInit()->isConstantInitializer(Context, - baseType->isReferenceType())) - Diag(var->getLocation(), diag::warn_global_constructor) - << var->getInit()->getSourceRange(); + Expr *Init = var->getInit(); + bool IsGlobal = var->hasGlobalStorage() && !var->isStaticLocal(); + + if (!var->getDeclContext()->isDependentContext() && Init) { + if (IsGlobal && !var->isConstexpr() && + getDiagnostics().getDiagnosticLevel(diag::warn_global_constructor, + var->getLocation()) + != DiagnosticsEngine::Ignored && + !Init->isConstantInitializer(Context, baseType->isReferenceType())) + Diag(var->getLocation(), diag::warn_global_constructor) + << Init->getSourceRange(); + + if (var->isConstexpr()) { + llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + if (!var->evaluateValue(Notes) || !var->isInitICE()) { + SourceLocation DiagLoc = var->getLocation(); + // If the note doesn't add any useful information other than a source + // location, fold it into the primary diagnostic. + if (Notes.size() == 1 && Notes[0].second.getDiagID() == + diag::note_invalid_subexpr_in_const_expr) { + DiagLoc = Notes[0].first; + Notes.clear(); + } + Diag(DiagLoc, diag::err_constexpr_var_requires_const_init) + << var << Init->getSourceRange(); + for (unsigned I = 0, N = Notes.size(); I != N; ++I) + Diag(Notes[I].first, Notes[I].second); + } + } else if (var->isUsableInConstantExpressions(Context)) { + // Check whether the initializer of a const variable of integral or + // enumeration type is an ICE now, since we can't tell whether it was + // initialized by a constant expression if we check later. + var->checkInitIsICE(); + } + } // Require the destructor. if (const RecordType *recordType = baseType->getAs<RecordType>()) @@ -6586,11 +6907,16 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { const DeclSpec &DS = D.getDeclSpec(); // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'. + // C++03 [dcl.stc]p2 also permits 'auto'. VarDecl::StorageClass StorageClass = SC_None; VarDecl::StorageClass StorageClassAsWritten = SC_None; if (DS.getStorageClassSpec() == DeclSpec::SCS_register) { StorageClass = SC_Register; StorageClassAsWritten = SC_Register; + } else if (getLangOpts().CPlusPlus && + DS.getStorageClassSpec() == DeclSpec::SCS_auto) { + StorageClass = SC_Auto; + StorageClassAsWritten = SC_Auto; } else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) { Diag(DS.getStorageClassSpecLoc(), diag::err_invalid_storage_class_in_func_decl); @@ -6608,7 +6934,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType parmDeclType = TInfo->getType(); - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { // Check that there are no default arguments inside the type of this // parameter. CheckExtraCXXDefaultArguments(D); @@ -6660,7 +6986,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { // the enclosing context. This prevents them from accidentally // looking like class members in C++. ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(), - D.getSourceRange().getBegin(), + D.getLocStart(), D.getIdentifierLoc(), II, parmDeclType, TInfo, StorageClass, StorageClassAsWritten); @@ -6715,7 +7041,7 @@ void Sema::DiagnoseUnusedParameters(ParmVarDecl * const *Param, return; for (; Param != ParamEnd; ++Param) { - if (!(*Param)->isUsed() && (*Param)->getDeclName() && + if (!(*Param)->isReferenced() && (*Param)->getDeclName() && !(*Param)->hasAttr<UnusedAttr>()) { Diag((*Param)->getLocation(), diag::warn_unused_parameter) << (*Param)->getDeclName(); @@ -6732,7 +7058,7 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param, // Warn if the return value is pass-by-value and larger than the specified // threshold. - if (ReturnTy.isPODType(Context)) { + if (!ReturnTy->isDependentType() && ReturnTy.isPODType(Context)) { unsigned Size = Context.getTypeSizeInChars(ReturnTy).getQuantity(); if (Size > LangOpts.NumLargeByValueCopy) Diag(D->getLocation(), diag::warn_return_value_size) @@ -6743,7 +7069,7 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param, // threshold. for (; Param != ParamEnd; ++Param) { QualType T = (*Param)->getType(); - if (!T.isPODType(Context)) + if (T->isDependentType() || !T.isPODType(Context)) continue; unsigned Size = Context.getTypeSizeInChars(T).getQuantity(); if (Size > LangOpts.NumLargeByValueCopy) @@ -6758,7 +7084,7 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, VarDecl::StorageClass StorageClass, VarDecl::StorageClass StorageClassAsWritten) { // In ARC, infer a lifetime qualifier for appropriate parameter types. - if (getLangOptions().ObjCAutoRefCount && + if (getLangOpts().ObjCAutoRefCount && T.getObjCLifetime() == Qualifiers::OCL_None && T->isObjCLifetimeType()) { @@ -6826,7 +7152,7 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, for (int i = FTI.NumArgs; i != 0; /* decrement in loop */) { --i; if (FTI.ArgInfo[i].Param == 0) { - llvm::SmallString<256> Code; + SmallString<256> Code; llvm::raw_svector_ostream(Code) << " int " << FTI.ArgInfo[i].Ident->getName() << ";\n"; @@ -6856,7 +7182,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, assert(D.isFunctionDeclarator() && "Not a function declarator!"); Scope *ParentScope = FnBodyScope->getParent(); - D.setFunctionDefinition(true); + D.setFunctionDefinitionKind(FDK_Definition); Decl *DP = HandleDeclarator(ParentScope, D, MultiTemplateParamsArg(*this)); return ActOnStartOfFunctionDef(FnBodyScope, DP); @@ -6892,8 +7218,8 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) { return false; bool MissingPrototype = true; - for (const FunctionDecl *Prev = FD->getPreviousDeclaration(); - Prev; Prev = Prev->getPreviousDeclaration()) { + for (const FunctionDecl *Prev = FD->getPreviousDecl(); + Prev; Prev = Prev->getPreviousDecl()) { // Ignore any declarations that occur in function or method // scope, because they aren't visible from the header. if (Prev->getDeclContext()->isFunctionOrMethod()) @@ -6911,11 +7237,11 @@ void Sema::CheckForFunctionRedefinition(FunctionDecl *FD) { // was an extern inline function. const FunctionDecl *Definition; if (FD->isDefined(Definition) && - !canRedefineFunction(Definition, getLangOptions())) { - if (getLangOptions().GNUMode && Definition->isInlineSpecified() && + !canRedefineFunction(Definition, getLangOpts())) { + if (getLangOpts().GNUMode && Definition->isInlineSpecified() && Definition->getStorageClass() == SC_Extern) Diag(FD->getLocation(), diag::err_redefinition_extern_inline) - << FD->getDeclName() << getLangOptions().CPlusPlus; + << FD->getDeclName() << getLangOpts().CPlusPlus; else Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); Diag(Definition->getLocation(), diag::note_previous_definition); @@ -6987,6 +7313,43 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { } } + // If we had any tags defined in the function prototype, + // introduce them into the function scope. + if (FnBodyScope) { + for (llvm::ArrayRef<NamedDecl*>::iterator I = FD->getDeclsInPrototypeScope().begin(), + E = FD->getDeclsInPrototypeScope().end(); I != E; ++I) { + NamedDecl *D = *I; + + // Some of these decls (like enums) may have been pinned to the translation unit + // for lack of a real context earlier. If so, remove from the translation unit + // 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) { + Context.getTranslationUnitDecl()->removeDecl(D); + break; + } + } + // Either way, reassign the lexical decl context to our FunctionDecl. + D->setLexicalDeclContext(CurContext); + } + + // If the decl has a non-null name, make accessible in the current scope. + if (!D->getName().empty()) + PushOnScopeChains(D, FnBodyScope, /*AddToContext=*/false); + + // 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); + } + } + } + // Checking attributes of current function definition // dllimport attribute. DLLImportAttr *DA = FD->getAttr<DLLImportAttr>(); @@ -7068,20 +7431,15 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (FD) { FD->setBody(Body); - if (FD->isMain()) { - // C and C++ allow for main to automagically return 0. - // Implements C++ [basic.start.main]p5 and C99 5.1.2.2.3. - FD->setHasImplicitReturnZero(true); - WP.disableCheckFallThrough(); - } else if (FD->hasAttr<NakedAttr>()) { - // If the function is marked 'naked', don't complain about missing return - // statements. + + // If the function implicitly returns zero (like 'main') or is naked, + // don't complain about missing return statements. + if (FD->hasImplicitReturnZero() || FD->hasAttr<NakedAttr>()) WP.disableCheckFallThrough(); - } // MSVC permits the use of pure specifier (=0) on function definition, // defined at class scope, warn about this non standard construct. - if (getLangOptions().MicrosoftExt && FD->isPure()) + if (getLangOpts().MicrosoftExt && FD->isPure()) Diag(FD->getLocation(), diag::warn_pure_function_definition); if (!FD->isInvalidDecl()) { @@ -7096,7 +7454,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, computeNRVO(Body, getCurFunction()); } - assert(FD == getCurFunctionDecl() && "Function parsing confused"); + assert((FD == getCurFunctionDecl() || getCurLambda()->CallOperator == FD) && + "Function parsing confused"); } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) { assert(MD == getCurMethodDecl() && "Method parsing confused"); MD->setBody(Body); @@ -7154,33 +7513,34 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, // deletion in some later function. if (PP.getDiagnostics().hasErrorOccurred() || PP.getDiagnostics().getSuppressAllDiagnostics()) { - ExprTemporaries.clear(); - ExprNeedsCleanups = false; + DiscardCleanupsInEvaluationContext(); } else if (!isa<FunctionTemplateDecl>(dcl)) { // Since the body is valid, issue any analysis-based warnings that are // enabled. ActivePolicy = &WP; } - if (FD && FD->isConstexpr() && !FD->isInvalidDecl() && - !CheckConstexprFunctionBody(FD, Body)) + if (!IsInstantiation && FD && FD->isConstexpr() && !FD->isInvalidDecl() && + (!CheckConstexprFunctionDecl(FD) || + !CheckConstexprFunctionBody(FD, Body))) FD->setInvalidDecl(); - assert(ExprTemporaries.empty() && "Leftover temporaries in function"); + assert(ExprCleanupObjects.empty() && "Leftover temporaries in function"); assert(!ExprNeedsCleanups && "Unaccounted cleanups in function"); + assert(MaybeODRUseExprs.empty() && + "Leftover expressions for odr-use checking"); } if (!IsInstantiation) PopDeclContext(); - PopFunctionOrBlockScope(ActivePolicy, dcl); + PopFunctionScopeInfo(ActivePolicy, dcl); // 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 (getDiagnostics().hasErrorOccurred()) { - ExprTemporaries.clear(); - ExprNeedsCleanups = false; + DiscardCleanupsInEvaluationContext(); } return dcl; @@ -7191,6 +7551,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, /// relevant Decl. void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D, ParsedAttributes &Attrs) { + // Always attach attributes to the underlying decl. + if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) + D = TD->getTemplatedDecl(); ProcessDeclAttributeList(S, D, Attrs.getList()); } @@ -7212,12 +7575,35 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, } // Extension in C99. Legal in C90, but warn about it. + unsigned diag_id; if (II.getName().startswith("__builtin_")) - Diag(Loc, diag::warn_builtin_unknown) << &II; - else if (getLangOptions().C99) - Diag(Loc, diag::ext_implicit_function_decl) << &II; + diag_id = diag::warn_builtin_unknown; + else if (getLangOpts().C99) + diag_id = diag::ext_implicit_function_decl; else - Diag(Loc, diag::warn_implicit_function_decl) << &II; + diag_id = diag::warn_implicit_function_decl; + Diag(Loc, diag_id) << &II; + + // Because typo correction is expensive, only do it if the implicit + // function declaration is going to be treated as an error. + if (Diags.getDiagnosticLevel(diag_id, Loc) >= DiagnosticsEngine::Error) { + TypoCorrection Corrected; + DeclFilterCCC<FunctionDecl> Validator; + if (S && (Corrected = CorrectTypo(DeclarationNameInfo(&II, Loc), + LookupOrdinaryName, S, 0, Validator))) { + std::string CorrectedStr = Corrected.getAsString(getLangOpts()); + std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOpts()); + FunctionDecl *Func = Corrected.getCorrectionDeclAs<FunctionDecl>(); + + Diag(Loc, diag::note_function_suggestion) << CorrectedQuotedStr + << FixItHint::CreateReplacement(Loc, CorrectedStr); + + if (Func->getLocation().isValid() + && !II.getName().startswith("__builtin_")) + Diag(Func->getLocation(), diag::note_previous_decl) + << CorrectedQuotedStr; + } + } // Set a Declarator for the implicit definition: int foo(); const char *Dummy; @@ -7230,6 +7616,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, Declarator D(DS, Declarator::BlockContext); D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(), 0, 0, 0, true, SourceLocation(), + SourceLocation(), SourceLocation(), SourceLocation(), EST_None, SourceLocation(), 0, 0, 0, 0, Loc, Loc, D), @@ -7272,10 +7659,16 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { unsigned FormatIdx; bool HasVAListArg; if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) { - if (!FD->getAttr<FormatAttr>()) + if (!FD->getAttr<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, - "printf", FormatIdx+1, + fmt, FormatIdx+1, HasVAListArg ? 0 : FormatIdx+2)); + } } if (Context.BuiltinInfo.isScanfLike(BuiltinID, FormatIdx, HasVAListArg)) { @@ -7288,7 +7681,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { // Mark const if we don't care about errno and that is the only // thing preventing the function from being const. This allows // IRgen to use LLVM intrinsics for such functions. - if (!getLangOptions().MathErrno && + if (!getLangOpts().MathErrno && Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) { if (!FD->getAttr<ConstAttr>()) FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context)); @@ -7306,7 +7699,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { IdentifierInfo *Name = FD->getIdentifier(); if (!Name) return; - if ((!getLangOptions().CPlusPlus && + if ((!getLangOpts().CPlusPlus && FD->getDeclContext()->isTranslationUnit()) || (isa<LinkageSpecDecl>(FD->getDeclContext()) && cast<LinkageSpecDecl>(FD->getDeclContext())->getLanguage() == @@ -7316,16 +7709,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { } else return; - if (Name->isStr("NSLog") || Name->isStr("NSLogv")) { - // FIXME: NSLog and NSLogv should be target specific - if (const FormatAttr *Format = FD->getAttr<FormatAttr>()) { - // FIXME: We known better than our headers. - const_cast<FormatAttr *>(Format)->setType(Context, "printf"); - } else - FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context, - "printf", 1, - Name->isStr("NSLogv") ? 0 : 2)); - } else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) { + 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>()) @@ -7347,7 +7731,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, // Scope manipulation handled by caller. TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext, - D.getSourceRange().getBegin(), + D.getLocStart(), D.getIdentifierLoc(), D.getIdentifier(), TInfo); @@ -7406,6 +7790,52 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, } +/// \brief Check that this is a valid underlying type for an enum declaration. +bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) { + SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); + QualType T = TI->getType(); + + if (T->isDependentType() || T->isIntegralType(Context)) + return false; + + Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) << T; + return true; +} + +/// Check whether this is a valid redeclaration of a previous enumeration. +/// \return true if the redeclaration was invalid. +bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped, + QualType EnumUnderlyingTy, + const EnumDecl *Prev) { + bool IsFixed = !EnumUnderlyingTy.isNull(); + + if (IsScoped != Prev->isScoped()) { + Diag(EnumLoc, diag::err_enum_redeclare_scoped_mismatch) + << Prev->isScoped(); + Diag(Prev->getLocation(), diag::note_previous_use); + return true; + } + + if (IsFixed && Prev->isFixed()) { + if (!EnumUnderlyingTy->isDependentType() && + !Prev->getIntegerType()->isDependentType() && + !Context.hasSameUnqualifiedType(EnumUnderlyingTy, + Prev->getIntegerType())) { + Diag(EnumLoc, diag::err_enum_redeclare_type_mismatch) + << EnumUnderlyingTy << Prev->getIntegerType(); + Diag(Prev->getLocation(), diag::note_previous_use); + return true; + } + } else if (IsFixed != Prev->isFixed()) { + Diag(EnumLoc, diag::err_enum_redeclare_fixed_mismatch) + << Prev->isFixed(); + Diag(Prev->getLocation(), diag::note_previous_use); + return true; + } + + return false; +} + /// \brief Determine whether a tag with a given kind is acceptable /// as a redeclaration of the given tag declaration. /// @@ -7512,15 +7942,18 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation ModulePrivateLoc, MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl, bool &IsDependent, - bool ScopedEnum, bool ScopedEnumUsesClassTag, + SourceLocation ScopedEnumKWLoc, + bool ScopedEnumUsesClassTag, TypeResult UnderlyingType) { // If this is not a definition, it must have a name. + IdentifierInfo *OrigName = Name; assert((Name != 0 || TUK == TUK_Definition) && "Nameless record must be a definition!"); assert(TemplateParameterLists.size() == 0 || TUK != TUK_Reference); OwnedDecl = false; TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); + bool ScopedEnum = ScopedEnumKWLoc.isValid(); // FIXME: Check explicit specializations more carefully. bool isExplicitSpecialization = false; @@ -7576,23 +8009,18 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // 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; - QualType T = GetTypeFromParser(UnderlyingType.get(), &TI); + GetTypeFromParser(UnderlyingType.get(), &TI); EnumUnderlying = TI; - SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); - - if (!T->isDependentType() && !T->isIntegralType(Context)) { - Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) - << T; + if (CheckEnumUnderlyingType(TI)) // Recover by falling back to int. EnumUnderlying = Context.IntTy.getTypePtr(); - } - if (DiagnoseUnexpandedParameterPack(UnderlyingLoc, TI, + if (DiagnoseUnexpandedParameterPack(TI->getTypeLoc().getBeginLoc(), TI, UPPC_FixedUnderlyingType)) EnumUnderlying = Context.IntTy.getTypePtr(); - } else if (getLangOptions().MicrosoftExt) + } else if (getLangOpts().MicrosoftMode) // Microsoft enums are always of int type. EnumUnderlying = Context.IntTy.getTypePtr(); } @@ -7686,7 +8114,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, if (Previous.isAmbiguous()) return 0; - if (!getLangOptions().CPlusPlus && TUK != TUK_Reference) { + if (!getLangOpts().CPlusPlus && TUK != TUK_Reference) { // FIXME: This makes sure that we ignore the contexts associated // with C structs, unions, and enums when looking for a matching // tag declaration or definition. See the similar lookup tweak @@ -7697,6 +8125,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, } 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(); } @@ -7708,7 +8137,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, Previous.clear(); } - if (getLangOptions().CPlusPlus && Name && DC && StdNamespace && + if (getLangOpts().CPlusPlus && Name && DC && StdNamespace && DC->Equals(getStdNamespace()) && Name->isStr("bad_alloc")) { // This is a declaration of or a reference to "std::bad_alloc". isStdBadAlloc = true; @@ -7759,12 +8188,12 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // Find the context where we'll be declaring the tag. // FIXME: We would like to maintain the current DeclContext as the // lexical context, - while (SearchDC->isRecord() || SearchDC->isTransparentContext()) + while (!SearchDC->isFileContext() && !SearchDC->isFunctionOrMethod()) SearchDC = SearchDC->getParent(); // Find the scope where we'll be declaring the tag. while (S->isClassScope() || - (getLangOptions().CPlusPlus && + (getLangOpts().CPlusPlus && S->isFunctionPrototypeScope()) || ((S->getFlags() & Scope::DeclScope) == 0) || (S->getEntity() && @@ -7781,7 +8210,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // In C++, we need to do a redeclaration lookup to properly // diagnose some problems. - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { Previous.setRedeclarationKind(ForRedeclaration); LookupQualifiedName(Previous, SearchDC); } @@ -7799,7 +8228,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // technically forbidden by the current standard but which is // okay according to the likely resolution of an open issue; // see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407 - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(PrevDecl)) { if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) { TagDecl *Tag = TT->getDecl(); @@ -7851,36 +8280,28 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, if (Kind == TTK_Enum && PrevTagDecl->getTagKind() == TTK_Enum) { const EnumDecl *PrevEnum = cast<EnumDecl>(PrevTagDecl); - // All conflicts with previous declarations are recovered by - // returning the previous declaration. - if (ScopedEnum != PrevEnum->isScoped()) { - Diag(KWLoc, diag::err_enum_redeclare_scoped_mismatch) - << PrevEnum->isScoped(); - Diag(PrevTagDecl->getLocation(), diag::note_previous_use); - return PrevTagDecl; - } - else if (EnumUnderlying && PrevEnum->isFixed()) { - QualType T; - if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo*>()) - T = TI->getType(); - else - T = QualType(EnumUnderlying.get<const Type*>(), 0); - - if (!Context.hasSameUnqualifiedType(T, PrevEnum->getIntegerType())) { - Diag(NameLoc.isValid() ? NameLoc : KWLoc, - diag::err_enum_redeclare_type_mismatch) - << T - << PrevEnum->getIntegerType(); - Diag(PrevTagDecl->getLocation(), diag::note_previous_use); - return PrevTagDecl; - } - } - else if (!EnumUnderlying.isNull() != PrevEnum->isFixed()) { - Diag(KWLoc, diag::err_enum_redeclare_fixed_mismatch) - << PrevEnum->isFixed(); - Diag(PrevTagDecl->getLocation(), diag::note_previous_use); + // If this is an elaborated-type-specifier for a scoped enumeration, + // the 'class' keyword is not necessary and not permitted. + if (TUK == TUK_Reference || TUK == TUK_Friend) { + if (ScopedEnum) + Diag(ScopedEnumKWLoc, diag::err_enum_class_reference) + << PrevEnum->isScoped() + << FixItHint::CreateRemoval(ScopedEnumKWLoc); return PrevTagDecl; } + + QualType EnumUnderlyingTy; + if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo*>()) + EnumUnderlyingTy = TI->getType(); + else if (const Type *T = EnumUnderlying.dyn_cast<const Type*>()) + EnumUnderlyingTy = QualType(T, 0); + + // All conflicts with previous declarations are recovered by + // returning the previous declaration, unless this is a definition, + // 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; } if (!Invalid) { @@ -7891,7 +8312,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // For our current ASTs this shouldn't be a problem, but will // need to be changed with DeclGroups. if ((TUK == TUK_Reference && (!PrevTagDecl->getFriendObjectKind() || - getLangOptions().MicrosoftExt)) || TUK == TUK_Friend) + getLangOpts().MicrosoftExt)) || TUK == TUK_Friend) return PrevTagDecl; // Diagnose attempts to redefine a tag. @@ -7900,11 +8321,25 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // If we're defining a specialization and the previous definition // is from an implicit instantiation, don't emit an error // here; we'll catch this in the general case below. - if (!isExplicitSpecialization || - !isa<CXXRecordDecl>(Def) || - cast<CXXRecordDecl>(Def)->getTemplateSpecializationKind() - == TSK_ExplicitSpecialization) { - Diag(NameLoc, diag::err_redefinition) << Name; + bool IsExplicitSpecializationAfterInstantiation = false; + if (isExplicitSpecialization) { + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Def)) + IsExplicitSpecializationAfterInstantiation = + RD->getTemplateSpecializationKind() != + TSK_ExplicitSpecialization; + else if (EnumDecl *ED = dyn_cast<EnumDecl>(Def)) + IsExplicitSpecializationAfterInstantiation = + ED->getTemplateSpecializationKind() != + TSK_ExplicitSpecialization; + } + + if (!IsExplicitSpecializationAfterInstantiation) { + // A redeclaration in function prototype scope in C isn't + // visible elsewhere, so merely issue a warning. + if (!getLangOpts().CPlusPlus && S->containedInPrototypeScope()) + Diag(NameLoc, diag::warn_redefinition_in_param_list) << Name; + else + Diag(NameLoc, diag::err_redefinition) << Name; Diag(Def->getLocation(), diag::note_previous_definition); // If this is a redefinition, recover by making this // struct be anonymous, which will make any later @@ -7951,8 +8386,6 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // lookup. This is only actually possible in C++, where a few // things like templates still live in the tag namespace. } else { - assert(getLangOptions().CPlusPlus); - // Use a better diagnostic if an elaborated-type-specifier // found the wrong kind of type on the first // (non-redeclaration) lookup. @@ -8033,7 +8466,7 @@ CreateNewDecl: // If this is an undefined enum, warn. if (TUK != TUK_Definition && !Invalid) { TagDecl *Def; - if (getLangOptions().CPlusPlus0x && cast<EnumDecl>(New)->isFixed()) { + if (getLangOpts().CPlusPlus0x && cast<EnumDecl>(New)->isFixed()) { // C++0x: 7.2p2: opaque-enum-declaration. // Conflicts are diagnosed above. Do nothing. } @@ -8043,9 +8476,9 @@ CreateNewDecl: Diag(Def->getLocation(), diag::note_previous_definition); } else { unsigned DiagID = diag::ext_forward_ref_enum; - if (getLangOptions().MicrosoftExt) + if (getLangOpts().MicrosoftMode) DiagID = diag::ext_ms_forward_ref_enum; - else if (getLangOptions().CPlusPlus) + else if (getLangOpts().CPlusPlus) DiagID = diag::err_forward_ref_enum; Diag(Loc, DiagID); @@ -8071,7 +8504,7 @@ CreateNewDecl: // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: // struct X { int A; } D; D should chain to X. - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { // FIXME: Look for a way to use RecordDecl for simple structs. New = CXXRecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, cast_or_null<CXXRecordDecl>(PrevDecl)); @@ -8086,6 +8519,16 @@ CreateNewDecl: // Maybe add qualifier info. if (SS.isNotEmpty()) { if (SS.isSet()) { + // If this is either a declaration or a definition, check the + // nested-name-specifier against the current context. We don't do this + // for explicit specializations, because they have similar checking + // (with more specific diagnostics) in the call to + // CheckMemberSpecialization, below. + if (!isExplicitSpecialization && + (TUK == TUK_Definition || TUK == TUK_Declaration) && + diagnoseQualifiedDeclaration(SS, DC, OrigName, NameLoc)) + Invalid = true; + New->setQualifierInfo(SS.getWithLocInContext(Context)); if (TemplateParameterLists.size() > 0) { New->setTemplateParameterListsInfo(Context, @@ -8112,19 +8555,14 @@ CreateNewDecl: AddMsStructLayoutForRecord(RD); } - if (PrevDecl && PrevDecl->isModulePrivate()) - New->setModulePrivate(); - else if (ModulePrivateLoc.isValid()) { + if (ModulePrivateLoc.isValid()) { if (isExplicitSpecialization) Diag(New->getLocation(), diag::err_module_private_specialization) << 2 << FixItHint::CreateRemoval(ModulePrivateLoc); - else if (PrevDecl && !PrevDecl->isModulePrivate()) - diagnoseModulePrivateRedeclaration(New, PrevDecl, ModulePrivateLoc); // __module_private__ does not apply to local classes. However, we only // diagnose this as an error when the declaration specifiers are // freestanding. Here, we just ignore the __module_private__. - // foobar else if (!SearchDC->isFunctionOrMethod()) New->setModulePrivate(); } @@ -8133,7 +8571,7 @@ CreateNewDecl: // check the specialization. if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous)) Invalid = true; - + if (Invalid) New->setInvalidDecl(); @@ -8142,7 +8580,7 @@ CreateNewDecl: // 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() && !getLangOptions().CPlusPlus) + 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 @@ -8155,7 +8593,7 @@ CreateNewDecl: // the tag name visible. if (TUK == TUK_Friend) New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty() || - getLangOptions().MicrosoftExt); + getLangOpts().MicrosoftExt); // Set the access specifier. if (!Invalid && SearchDC->isRecord()) @@ -8172,7 +8610,7 @@ CreateNewDecl: New->setAccess(PrevDecl->getAccess()); DeclContext *DC = New->getDeclContext()->getRedeclContext(); - DC->makeDeclVisibleInContext(New, /* Recoverable = */ false); + DC->makeDeclVisibleInContext(New); if (Name) // can be null along some error paths if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false); @@ -8180,7 +8618,7 @@ CreateNewDecl: S = getNonFieldDeclScope(S); PushOnScopeChains(New, S, !IsForwardReference); if (IsForwardReference) - SearchDC->makeDeclVisibleInContext(New, /* Recoverable = */ false); + SearchDC->makeDeclVisibleInContext(New); } else { CurContext->addDecl(New); @@ -8193,6 +8631,12 @@ 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); + OwnedDecl = true; return New; } @@ -8256,6 +8700,13 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, TagDecl *Tag = cast<TagDecl>(TagD); Tag->setRBraceLoc(RBraceLoc); + // Make sure we "complete" the definition even it is invalid. + if (Tag->isBeingDefined()) { + assert(Tag->isInvalidDecl() && "We should already have completed it"); + if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag)) + RD->completeDefinition(); + } + if (isa<CXXRecordDecl>(Tag)) FieldCollector->FinishClass(); @@ -8271,13 +8722,14 @@ void Sema::ActOnObjCContainerFinishDefinition() { PopDeclContext(); } -void Sema::ActOnObjCTemporaryExitContainerContext() { - OriginalLexicalContext = CurContext; +void Sema::ActOnObjCTemporaryExitContainerContext(DeclContext *DC) { + assert(DC == CurContext && "Mismatch of container contexts"); + OriginalLexicalContext = DC; ActOnObjCContainerFinishDefinition(); } -void Sema::ActOnObjCReenterContainerContext() { - ActOnObjCContainerStartDefinition(cast<Decl>(OriginalLexicalContext)); +void Sema::ActOnObjCReenterContainerContext(DeclContext *DC) { + ActOnObjCContainerStartDefinition(cast<Decl>(DC)); OriginalLexicalContext = 0; } @@ -8286,6 +8738,12 @@ void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) { TagDecl *Tag = cast<TagDecl>(TagD); Tag->setInvalidDecl(); + // Make sure we "complete" the definition even it is invalid. + if (Tag->isBeingDefined()) { + if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag)) + RD->completeDefinition(); + } + // We're undoing ActOnTagStartDefinition here, not // ActOnStartCXXMemberDeclarations, so we don't have to mess with // the FieldCollector. @@ -8294,9 +8752,10 @@ void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) { } // Note that FieldName may be null for anonymous bitfields. -bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, - QualType FieldTy, const Expr *BitWidth, - bool *ZeroWidth) { +ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, + IdentifierInfo *FieldName, + QualType FieldTy, Expr *BitWidth, + bool *ZeroWidth) { // Default to true; that shouldn't confuse checks for emptiness if (ZeroWidth) *ZeroWidth = true; @@ -8306,7 +8765,7 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, if (!FieldTy->isDependentType() && !FieldTy->isIntegralOrEnumerationType()) { // Handle incomplete types with specific error. if (RequireCompleteType(FieldLoc, FieldTy, diag::err_field_incomplete)) - return true; + return ExprError(); if (FieldName) return Diag(FieldLoc, diag::err_not_integral_type_bitfield) << FieldName << FieldTy << BitWidth->getSourceRange(); @@ -8314,16 +8773,18 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, << FieldTy << BitWidth->getSourceRange(); } else if (DiagnoseUnexpandedParameterPack(const_cast<Expr *>(BitWidth), UPPC_BitFieldWidth)) - return true; + return ExprError(); // If the bit-width is type- or value-dependent, don't try to check // it now. if (BitWidth->isValueDependent() || BitWidth->isTypeDependent()) - return false; + return Owned(BitWidth); llvm::APSInt Value; - if (VerifyIntegerConstantExpression(BitWidth, &Value)) - return true; + ExprResult ICE = VerifyIntegerConstantExpression(BitWidth, &Value); + if (ICE.isInvalid()) + return ICE; + BitWidth = ICE.take(); if (Value != 0 && ZeroWidth) *ZeroWidth = false; @@ -8343,7 +8804,7 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, if (!FieldTy->isDependentType()) { uint64_t TypeSize = Context.getTypeSize(FieldTy); if (Value.getZExtValue() > TypeSize) { - if (!getLangOptions().CPlusPlus) { + if (!getLangOpts().CPlusPlus) { if (FieldName) return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size) << FieldName << (unsigned)Value.getZExtValue() @@ -8363,7 +8824,7 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, } } - return false; + return Owned(BitWidth); } /// ActOnField - Each field of a C struct/union is passed into this in order @@ -8388,7 +8849,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType T = TInfo->getType(); - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { CheckExtraCXXDefaultArguments(D); if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, @@ -8408,15 +8869,25 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, << 2; // Check to see if this name was declared as a member previously + NamedDecl *PrevDecl = 0; LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration); LookupName(Previous, S); - assert((Previous.empty() || Previous.isOverloadedResult() || - Previous.isSingleResult()) - && "Lookup of member name should be either overloaded, single or null"); - - // If the name is overloaded then get any declaration else get the single result - NamedDecl *PrevDecl = Previous.isOverloadedResult() ? - Previous.getRepresentativeDecl() : Previous.getAsSingle<NamedDecl>(); + switch (Previous.getResultKind()) { + case LookupResult::Found: + case LookupResult::FoundUnresolvedValue: + PrevDecl = Previous.getAsSingle<NamedDecl>(); + break; + + case LookupResult::FoundOverloaded: + PrevDecl = Previous.getRepresentativeDecl(); + break; + + case LookupResult::NotFound: + case LookupResult::NotFoundInCurrentInstantiation: + case LookupResult::Ambiguous: + break; + } + Previous.suppressDiagnostics(); if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. @@ -8430,7 +8901,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, bool Mutable = (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable); - SourceLocation TSSL = D.getSourceRange().getBegin(); + SourceLocation TSSL = D.getLocStart(); FieldDecl *NewFD = CheckFieldDecl(II, T, TInfo, Record, Loc, Mutable, BitWidth, HasInit, TSSL, AS, PrevDecl, &D); @@ -8481,11 +8952,19 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, } QualType EltTy = Context.getBaseElementType(T); - if (!EltTy->isDependentType() && - RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) { - // Fields of incomplete type force their record to be invalid. - Record->setInvalidDecl(); - InvalidDecl = true; + if (!EltTy->isDependentType()) { + if (RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) { + // Fields of incomplete type force their record to be invalid. + Record->setInvalidDecl(); + InvalidDecl = true; + } else { + NamedDecl *Def; + EltTy->isIncompleteType(&Def); + if (Def && Def->isInvalidDecl()) { + Record->setInvalidDecl(); + InvalidDecl = true; + } + } } // C99 6.7.2.1p8: A member of a structure or union may have any type other @@ -8519,11 +8998,13 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, bool ZeroWidth = false; // If this is declared as a bit-field, check the bit-field. - if (!InvalidDecl && BitWidth && - VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth)) { - InvalidDecl = true; - BitWidth = 0; - ZeroWidth = false; + if (!InvalidDecl && BitWidth) { + BitWidth = VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth).take(); + if (!BitWidth) { + InvalidDecl = true; + BitWidth = 0; + ZeroWidth = false; + } } // Check that 'mutable' is consistent with the type of the declaration. @@ -8555,7 +9036,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, NewFD->setInvalidDecl(); } - if (!InvalidDecl && getLangOptions().CPlusPlus) { + if (!InvalidDecl && getLangOpts().CPlusPlus) { if (Record->isUnion()) { if (const RecordType *RT = EltTy->getAs<RecordType>()) { CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl()); @@ -8565,7 +9046,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, // destructor, or a non-trivial copy assignment operator // cannot be a member of a union, nor can an array of such // objects. - if (!getLangOptions().CPlusPlus0x && CheckNontrivialField(NewFD)) + if (CheckNontrivialField(NewFD)) NewFD->setInvalidDecl(); } } @@ -8588,7 +9069,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, // In auto-retain/release, infer strong retension for fields of // retainable type. - if (getLangOptions().ObjCAutoRefCount && inferObjCARCLifetime(NewFD)) + if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewFD)) NewFD->setInvalidDecl(); if (T.isObjCGCWeak()) @@ -8600,7 +9081,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, bool Sema::CheckNontrivialField(FieldDecl *FD) { assert(FD); - assert(getLangOptions().CPlusPlus && "valid check only for C++"); + assert(getLangOpts().CPlusPlus && "valid check only for C++"); if (FD->isInvalidDecl()) return true; @@ -8624,7 +9105,8 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { member = CXXDestructor; if (member != CXXInvalid) { - if (getLangOptions().ObjCAutoRefCount && RDecl->hasObjectMember()) { + if (!getLangOpts().CPlusPlus0x && + getLangOpts().ObjCAutoRefCount && RDecl->hasObjectMember()) { // Objective-C++ ARC: it is an error to have a non-trivial field of // a union. However, system headers in Objective-C programs // occasionally have Objective-C lifetime objects within unions, @@ -8638,11 +9120,13 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { return false; } } - - Diag(FD->getLocation(), diag::err_illegal_union_or_anon_struct_member) - << (int)FD->getParent()->isUnion() << FD->getDeclName() << member; + + Diag(FD->getLocation(), getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member : + diag::err_illegal_union_or_anon_struct_member) + << (int)FD->getParent()->isUnion() << FD->getDeclName() << member; DiagnoseNontrivial(RT, member); - return true; + return !getLangOpts().CPlusPlus0x; } } } @@ -8650,6 +9134,19 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { return false; } +/// If the given constructor is user-provided, produce a diagnostic explaining +/// that it makes the class non-trivial. +static bool DiagnoseNontrivialUserProvidedCtor(Sema &S, QualType QT, + CXXConstructorDecl *CD, + Sema::CXXSpecialMember CSM) { + if (!CD->isUserProvided()) + return false; + + SourceLocation CtorLoc = CD->getLocation(); + S.Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << CSM; + return true; +} + /// DiagnoseNontrivial - Given that a class has a non-trivial /// special member, figure out why. void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { @@ -8664,17 +9161,20 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { case CXXDefaultConstructor: if (RD->hasUserDeclaredConstructor()) { typedef CXXRecordDecl::ctor_iterator ctor_iter; - for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce;++ci){ - const FunctionDecl *body = 0; - ci->hasBody(body); - if (!body || !cast<CXXConstructorDecl>(body)->isImplicitlyDefined()) { - SourceLocation CtorLoc = ci->getLocation(); - Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member; + for (ctor_iter CI = RD->ctor_begin(), CE = RD->ctor_end(); CI != CE; ++CI) + if (DiagnoseNontrivialUserProvidedCtor(*this, QT, *CI, member)) return; - } - } - llvm_unreachable("found no user-declared constructors"); + // No user-provided constructors; look for constructor templates. + typedef CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl> + tmpl_iter; + for (tmpl_iter TI(RD->decls_begin()), TE(RD->decls_end()); + TI != TE; ++TI) { + CXXConstructorDecl *CD = + dyn_cast<CXXConstructorDecl>(TI->getTemplatedDecl()); + if (CD && DiagnoseNontrivialUserProvidedCtor(*this, QT, CD, member)) + return; + } } break; @@ -8699,7 +9199,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { if (RD->hasUserDeclaredCopyAssignment()) { // FIXME: this should use the location of the copy // assignment, not the type. - SourceLocation TyLoc = RD->getSourceRange().getBegin(); + SourceLocation TyLoc = RD->getLocStart(); Diag(TyLoc, diag::note_nontrivial_user_defined) << QT << member; return; } @@ -8731,7 +9231,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { // so we just iterate through the direct bases. for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi) if (bi->isVirtual()) { - SourceLocation BaseLoc = bi->getSourceRange().getBegin(); + SourceLocation BaseLoc = bi->getLocStart(); Diag(BaseLoc, diag::note_nontrivial_has_virtual) << QT << 1; return; } @@ -8741,7 +9241,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; ++mi) { if (mi->isVirtual()) { - SourceLocation MLoc = mi->getSourceRange().getBegin(); + SourceLocation MLoc = mi->getLocStart(); Diag(MLoc, diag::note_nontrivial_has_virtual) << QT << 0; return; } @@ -8768,7 +9268,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { assert(BaseRT && "Don't know how to handle dependent bases"); CXXRecordDecl *BaseRecTy = cast<CXXRecordDecl>(BaseRT->getDecl()); if (!(BaseRecTy->*hasTrivial)()) { - SourceLocation BaseLoc = bi->getSourceRange().getBegin(); + SourceLocation BaseLoc = bi->getLocStart(); Diag(BaseLoc, diag::note_nontrivial_has_nontrivial) << QT << 1 << member; DiagnoseNontrivial(BaseRT, member); return; @@ -8843,10 +9343,9 @@ Decl *Sema::ActOnIvar(Scope *S, if (BitWidth) { // 6.7.2.1p3, 6.7.2.1p4 - if (VerifyBitField(Loc, II, T, BitWidth)) { + BitWidth = VerifyBitField(Loc, II, T, BitWidth).take(); + if (!BitWidth) D.setInvalidType(); - BitWidth = 0; - } } else { // Not a bitfield. @@ -8870,6 +9369,8 @@ Decl *Sema::ActOnIvar(Scope *S, : ObjCIvarDecl::None; // Must set ivar's DeclContext to its enclosing interface. ObjCContainerDecl *EnclosingDecl = cast<ObjCContainerDecl>(CurContext); + if (!EnclosingDecl || EnclosingDecl->isInvalidDecl()) + return 0; ObjCContainerDecl *EnclosingContext; if (ObjCImplementationDecl *IMPDecl = dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) { @@ -8914,7 +9415,7 @@ Decl *Sema::ActOnIvar(Scope *S, NewID->setInvalidDecl(); // In ARC, infer 'retaining' for ivars of retainable type. - if (getLangOptions().ObjCAutoRefCount && inferObjCARCLifetime(NewID)) + if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewID)) NewID->setInvalidDecl(); if (D.getDeclSpec().isModulePrivateSpecified()) @@ -8980,11 +9481,23 @@ void Sema::ActOnFields(Scope* S, if (EnclosingDecl->isInvalidDecl()) return; - // Verify that all the fields are okay. + RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl); + + // Start counting up the number of named members; make sure to include + // 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)) + if (IFD->getDeclName()) + ++NumNamedMembers; + } + } + + // Verify that all the fields are okay. SmallVector<FieldDecl*, 32> RecFields; - RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl); bool ARCErrReported = false; for (llvm::ArrayRef<Decl *>::iterator i = Fields.begin(), end = Fields.end(); i != end; ++i) { @@ -9024,27 +9537,34 @@ void Sema::ActOnFields(Scope* S, continue; } else if (FDTy->isIncompleteArrayType() && Record && ((i + 1 == Fields.end() && !Record->isUnion()) || - ((getLangOptions().MicrosoftExt || - getLangOptions().CPlusPlus) && + ((getLangOpts().MicrosoftExt || + getLangOpts().CPlusPlus) && (i + 1 == Fields.end() || Record->isUnion())))) { // Flexible array member. // Microsoft and g++ is more permissive regarding flexible array. // It will accept flexible array in union and also // as the sole element of a struct/class. - if (getLangOptions().MicrosoftExt) { + if (getLangOpts().MicrosoftExt) { if (Record->isUnion()) Diag(FD->getLocation(), diag::ext_flexible_array_union_ms) << FD->getDeclName(); else if (Fields.size() == 1) Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_ms) << FD->getDeclName() << Record->getTagKind(); - } else if (getLangOptions().CPlusPlus) { + } else if (getLangOpts().CPlusPlus) { if (Record->isUnion()) Diag(FD->getLocation(), diag::ext_flexible_array_union_gnu) << FD->getDeclName(); else if (Fields.size() == 1) Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_gnu) << FD->getDeclName() << Record->getTagKind(); + } else if (!getLangOpts().C99) { + if (Record->isUnion()) + Diag(FD->getLocation(), diag::ext_flexible_array_union_gnu) + << FD->getDeclName(); + else + Diag(FD->getLocation(), diag::ext_c99_flexible_array_member) + << FD->getDeclName() << Record->getTagKind(); } else if (NumNamedMembers < 1) { Diag(FD->getLocation(), diag::err_flexible_array_empty_struct) << FD->getDeclName(); @@ -9101,8 +9621,8 @@ void Sema::ActOnFields(Scope* S, QualType T = Context.getObjCObjectPointerType(FD->getType()); FD->setType(T); } - else if (!getLangOptions().CPlusPlus) { - if (getLangOptions().ObjCAutoRefCount && Record && !ARCErrReported) { + else if (!getLangOpts().CPlusPlus) { + if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported) { // It's an error in ARC if a field has lifetime. // We don't want to report this in a system header, though, // so we just make the field unavailable. @@ -9118,13 +9638,14 @@ void Sema::ActOnFields(Scope* S, "this system field has retaining ownership")); } } else { - Diag(FD->getLocation(), diag::err_arc_objc_object_in_struct); + Diag(FD->getLocation(), diag::err_arc_objc_object_in_struct) + << T->isBlockPointerType(); } ARCErrReported = true; } } - else if (getLangOptions().ObjC1 && - getLangOptions().getGC() != LangOptions::NonGC && + else if (getLangOpts().ObjC1 && + getLangOpts().getGC() != LangOptions::NonGC && Record && !Record->hasObjectMember()) { if (FD->getType()->isObjCObjectPointerType() || FD->getType().isObjCGCStrong()) @@ -9168,7 +9689,7 @@ void Sema::ActOnFields(Scope* S, // non-POD because of the presence of an Objective-C pointer member. // If so, objects of this type cannot be shared between code compiled // with instant objects and code compiled with manual retain/release. - if (getLangOptions().ObjCAutoRefCount && + if (getLangOpts().ObjCAutoRefCount && CXXRecord->hasObjectMember() && CXXRecord->getLinkage() == ExternalLinkage) { if (CXXRecord->isPOD()) { @@ -9194,7 +9715,7 @@ void Sema::ActOnFields(Scope* S, } // Adjust user-defined destructor exception spec. - if (getLangOptions().CPlusPlus0x && + if (getLangOpts().CPlusPlus0x && CXXRecord->hasUserDeclaredDestructor()) AdjustDestructorExceptionSpec(CXXRecord,CXXRecord->getDestructor()); @@ -9266,7 +9787,7 @@ void Sema::ActOnFields(Scope* S, ObjCIvarDecl **ClsFields = reinterpret_cast<ObjCIvarDecl**>(RecFields.data()); if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl)) { - ID->setLocEnd(RBrac); + ID->setEndOfDefinitionLoc(RBrac); // Add ivar's to class's DeclContext. for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { ClsFields[i]->setLexicalDeclContext(ID); @@ -9284,6 +9805,8 @@ void Sema::ActOnFields(Scope* S, // Only it is in implementation's lexical context. ClsFields[I]->setLexicalDeclContext(IMPDecl); CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), RBrac); + IMPDecl->setIvarLBraceLoc(LBrac); + IMPDecl->setIvarRBraceLoc(RBrac); } else if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) { // case of ivars in class extension; all other cases have been @@ -9291,10 +9814,34 @@ void Sema::ActOnFields(Scope* S, // FIXME. Class extension does not have a LocEnd field. // CDecl->setLocEnd(RBrac); // Add ivar's to class extension's DeclContext. + // Diagnose redeclaration of private ivars. + ObjCInterfaceDecl *IDecl = CDecl->getClassInterface(); for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { + if (IDecl) { + if (const ObjCIvarDecl *ClsIvar = + IDecl->getIvarDecl(ClsFields[i]->getIdentifier())) { + Diag(ClsFields[i]->getLocation(), + diag::err_duplicate_ivar_declaration); + Diag(ClsIvar->getLocation(), diag::note_previous_definition); + continue; + } + for (const ObjCCategoryDecl *ClsExtDecl = + IDecl->getFirstClassExtension(); + ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { + if (const ObjCIvarDecl *ClsExtIvar = + ClsExtDecl->getIvarDecl(ClsFields[i]->getIdentifier())) { + Diag(ClsFields[i]->getLocation(), + diag::err_duplicate_ivar_declaration); + Diag(ClsExtIvar->getLocation(), diag::note_previous_definition); + continue; + } + } + } ClsFields[i]->setLexicalDeclContext(CDecl); CDecl->addDecl(ClsFields[i]); } + CDecl->setIvarLBraceLoc(LBrac); + CDecl->setIvarRBraceLoc(RBrac); } } @@ -9360,56 +9907,70 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, if (Val && DiagnoseUnexpandedParameterPack(Val, UPPC_EnumeratorValue)) Val = 0; + if (Val) + Val = DefaultLvalueConversion(Val).take(); + if (Val) { if (Enum->isDependentType() || Val->isTypeDependent()) EltTy = Context.DependentTy; else { - // C99 6.7.2.2p2: Make sure we have an integer constant expression. SourceLocation ExpLoc; - if (!Val->isValueDependent() && - VerifyIntegerConstantExpression(Val, &EnumVal)) { - Val = 0; - } else { - if (!getLangOptions().CPlusPlus) { - // C99 6.7.2.2p2: - // The expression that defines the value of an enumeration constant - // shall be an integer constant expression that has a value - // representable as an int. - - // Complain if the value is not representable in an int. - if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy)) - Diag(IdLoc, diag::ext_enum_value_not_int) - << EnumVal.toString(10) << Val->getSourceRange() - << (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(); - } - } - + if (getLangOpts().CPlusPlus0x && Enum->isFixed() && + !getLangOpts().MicrosoftMode) { + // 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. + EltTy = Enum->getIntegerType(); + ExprResult Converted = + CheckConvertedConstantExpression(Val, EltTy, EnumVal, + CCEK_Enumerator); + if (Converted.isInvalid()) + Val = 0; + else + Val = Converted.take(); + } else if (!Val->isValueDependent() && + !(Val = VerifyIntegerConstantExpression(Val, + &EnumVal).take())) { + // C99 6.7.2.2p2: Make sure we have an integer constant expression. + } else { if (Enum->isFixed()) { EltTy = Enum->getIntegerType(); - // C++0x [dcl.enum]p5: - // ... if the initializing value of an enumerator cannot be - // represented by the underlying type, the program is ill-formed. + // In Obj-C and Microsoft mode, require the enumeration value to be + // representable in the underlying type of the enumeration. In C++11, + // we perform a non-narrowing conversion as part of converted constant + // expression checking. if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) { - if (getLangOptions().MicrosoftExt) { + if (getLangOpts().MicrosoftMode) { Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy; Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take(); - } else - Diag(IdLoc, diag::err_enumerator_too_large) - << EltTy; + } else + Diag(IdLoc, diag::err_enumerator_too_large) << EltTy; } else Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take(); - } - else { - // C++0x [dcl.enum]p5: + } else if (getLangOpts().CPlusPlus) { + // C++11 [dcl.enum]p5: // If the underlying type is not fixed, the type of each enumerator // is the type of its initializing value: // - If an initializer is specified for an enumerator, the // initializing value has the same type as the expression. EltTy = Val->getType(); + } else { + // C99 6.7.2.2p2: + // The expression that defines the value of an enumeration constant + // shall be an integer constant expression that has a value + // representable as an int. + + // Complain if the value is not representable in an int. + if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy)) + Diag(IdLoc, diag::ext_enum_value_not_int) + << EnumVal.toString(10) << Val->getSourceRange() + << (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(); + } + EltTy = Val->getType(); } } } @@ -9483,9 +10044,9 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, // an int (C99 6.7.2.2p2). However, we support GCC's extension that // permits enumerator values that are representable in some larger // integral type. - if (!getLangOptions().CPlusPlus && !T.isNull()) + if (!getLangOpts().CPlusPlus && !T.isNull()) Diag(IdLoc, diag::warn_enum_value_overflow); - } else if (!getLangOptions().CPlusPlus && + } else if (!getLangOpts().CPlusPlus && !isRepresentableIntegerValue(Context, EnumVal, EltTy)) { // Enforce C99 6.7.2.2p2 even when we compute the next value. Diag(IdLoc, diag::ext_enum_value_not_int) @@ -9497,7 +10058,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, if (!EltTy->isDependentType()) { // Make the enumerator value match the signedness and size of the // enumerator's type. - EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy)); + EnumVal = EnumVal.extOrTrunc(Context.getIntWidth(EltTy)); EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType()); } @@ -9509,11 +10070,10 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, SourceLocation IdLoc, IdentifierInfo *Id, AttributeList *Attr, - SourceLocation EqualLoc, Expr *val) { + SourceLocation EqualLoc, Expr *Val) { EnumDecl *TheEnumDecl = cast<EnumDecl>(theEnumDecl); EnumConstantDecl *LastEnumConst = cast_or_null<EnumConstantDecl>(lastEnumConst); - Expr *Val = static_cast<Expr*>(val); // The scope passed in may not be a decl scope. Zip up the scope tree until // we find one that is. @@ -9533,7 +10093,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, if (PrevDecl) { // When in C++, we may get a TagDecl with the same name; in this case the // enum constant will 'hide' the tag. - assert((getLangOptions().CPlusPlus || !isa<TagDecl>(PrevDecl)) && + assert((getLangOpts().CPlusPlus || !isa<TagDecl>(PrevDecl)) && "Received TagDecl when not in C++!"); if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S)) { if (isa<EnumConstantDecl>(PrevDecl)) @@ -9651,7 +10211,11 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, Packed = true; if (Enum->isFixed()) { - BestType = BestPromotionType = Enum->getIntegerType(); + BestType = Enum->getIntegerType(); + if (BestType->isPromotableIntegerType()) + BestPromotionType = Context.getPromotedIntegerType(BestType); + else + BestPromotionType = BestType; // We don't need to set BestWidth, because BestType is going to be the type // of the enumerators, but we do anyway because otherwise some compilers // warn that it might be used uninitialized. @@ -9701,13 +10265,13 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, BestType = Context.UnsignedIntTy; BestWidth = IntWidth; BestPromotionType - = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus) + = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) ? Context.UnsignedIntTy : Context.IntTy; } else if (NumPositiveBits <= (BestWidth = Context.getTargetInfo().getLongWidth())) { BestType = Context.UnsignedLongTy; BestPromotionType - = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus) + = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) ? Context.UnsignedLongTy : Context.LongTy; } else { BestWidth = Context.getTargetInfo().getLongLongWidth(); @@ -9715,7 +10279,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, "How could an initializer get larger than ULL?"); BestType = Context.UnsignedLongLongTy; BestPromotionType - = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus) + = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) ? Context.UnsignedLongLongTy : Context.LongLongTy; } } @@ -9740,14 +10304,15 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, QualType NewTy; unsigned NewWidth; bool NewSign; - if (!getLangOptions().CPlusPlus && + if (!getLangOpts().CPlusPlus && + !Enum->isFixed() && isRepresentableIntegerValue(Context, InitVal, Context.IntTy)) { NewTy = Context.IntTy; NewWidth = IntWidth; NewSign = true; } else if (ECD->getType() == BestType) { // Already the right type! - if (getLangOptions().CPlusPlus) + if (getLangOpts().CPlusPlus) // C++ [dcl.enum]p4: Following the closing brace of an // enum-specifier, each enumerator has the type of its // enumeration. @@ -9772,7 +10337,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, ECD->getInitExpr(), /*base paths*/ 0, VK_RValue)); - if (getLangOptions().CPlusPlus) + if (getLangOpts().CPlusPlus) // C++ [dcl.enum]p4: Following the closing brace of an // enum-specifier, each enumerator has the type of its // enumeration. @@ -9783,6 +10348,12 @@ 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); + } Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, @@ -9797,31 +10368,50 @@ Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, return New; } -DeclResult Sema::ActOnModuleImport(SourceLocation ImportLoc, - IdentifierInfo &ModuleName, - SourceLocation ModuleNameLoc) { - ModuleKey Module = PP.getModuleLoader().loadModule(ImportLoc, - ModuleName, ModuleNameLoc); - if (!Module) +DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc, + SourceLocation ImportLoc, + ModuleIdPath Path) { + Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path, + Module::AllVisible, + /*IsIncludeDirective=*/false); + if (!Mod) return true; - // FIXME: Actually create a declaration to describe the module import. - (void)Module; - return DeclResult((Decl *)0); + llvm::SmallVector<SourceLocation, 2> IdentifierLocs; + Module *ModCheck = Mod; + for (unsigned I = 0, N = Path.size(); I != N; ++I) { + // If we've run out of module parents, just drop the remaining identifiers. + // We need the length to be consistent. + if (!ModCheck) + break; + ModCheck = ModCheck->Parent; + + IdentifierLocs.push_back(Path[I].second); + } + + ImportDecl *Import = ImportDecl::Create(Context, + Context.getTranslationUnitDecl(), + AtLoc.isValid()? AtLoc : ImportLoc, + Mod, IdentifierLocs); + Context.getTranslationUnitDecl()->addDecl(Import); + return Import; } -void -Sema::diagnoseModulePrivateRedeclaration(NamedDecl *New, NamedDecl *Old, - SourceLocation ModulePrivateKeyword) { - assert(!Old->isModulePrivate() && "Old is module-private!"); - - Diag(New->getLocation(), diag::err_module_private_follows_public) - << New->getDeclName() << SourceRange(ModulePrivateKeyword); - Diag(Old->getLocation(), diag::note_previous_declaration) - << Old->getDeclName(); - - // Drop the __module_private__ from the new declaration, since it's invalid. - New->setModulePrivate(false); +void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name, + IdentifierInfo* AliasName, + SourceLocation PragmaLoc, + SourceLocation NameLoc, + SourceLocation AliasNameLoc) { + Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, + LookupOrdinaryName); + AsmLabelAttr *Attr = + ::new (Context) AsmLabelAttr(AliasNameLoc, Context, AliasName->getName()); + + if (PrevDecl) + PrevDecl->addAttr(Attr); + else + (void)ExtnameUndeclaredIdentifiers.insert( + std::pair<IdentifierInfo*,AsmLabelAttr*>(Name, Attr)); } void Sema::ActOnPragmaWeakID(IdentifierInfo* Name, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp index 69baf79..5c6ddd2 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -35,17 +35,14 @@ enum AttributeDeclKind { ExpectedVariableOrFunction, ExpectedFunctionOrMethod, ExpectedParameter, - ExpectedParameterOrMethod, ExpectedFunctionMethodOrBlock, - ExpectedClassOrVirtualMethod, ExpectedFunctionMethodOrParameter, ExpectedClass, - ExpectedVirtualMethod, - ExpectedClassMember, ExpectedVariable, ExpectedMethod, ExpectedVariableFunctionOrLabel, - ExpectedFieldOrGlobalVar + ExpectedFieldOrGlobalVar, + ExpectedStruct }; //===----------------------------------------------------------------------===// @@ -275,21 +272,25 @@ static const RecordType *getRecordType(QualType QT) { /// \brief Thread Safety Analysis: Checks that the passed in RecordType /// resolves to a lockable object. May flag an error. -static bool checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr, - const RecordType *RT) { - // Flag error if could not get record type for this argument. +static void checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr, + QualType Ty) { + const RecordType *RT = getRecordType(Ty); + + // Warn if could not get record type for this argument. if (!RT) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_class) - << Attr.getName(); - return false; + S.Diag(Attr.getLoc(), diag::warn_attribute_argument_not_class) + << Attr.getName() << Ty.getAsString(); + return; } - // Flag error if the type is not lockable. + // Don't check for lockable if the class hasn't been defined yet. + if (RT->isIncompleteType()) + return; + // Warn if the type is not lockable. if (!RT->getDecl()->getAttr<LockableAttr>()) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_lockable) - << Attr.getName(); - return false; + S.Diag(Attr.getLoc(), diag::warn_attribute_argument_not_lockable) + << Attr.getName() << Ty.getAsString(); + return; } - return true; } /// \brief Thread Safety Analysis: Checks that all attribute arguments, starting @@ -331,12 +332,10 @@ static bool checkAttrArgsAreLockableObjs(Sema &S, Decl *D, return false; } ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType(); - RT = getRecordType(ArgTy); } } - if (!checkForLockableRecord(S, D, Attr, RT)) - return false; + checkForLockableRecord(S, D, Attr, ArgTy); Args.push_back(ArgExp); } @@ -393,13 +392,9 @@ static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr, if (pointer && !checkIsPointer(S, D, Attr)) return; - if (Arg->isTypeDependent()) - // FIXME: handle attributes with dependent types - return; - - // check that the argument is lockable object - if (!checkForLockableRecord(S, D, Attr, getRecordType(Arg->getType()))) - return; + if (!Arg->isTypeDependent()) { + checkForLockableRecord(S, D, Attr, Arg->getType()); + } if (pointer) D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(), @@ -446,6 +441,23 @@ static void handleNoThreadSafetyAttr(Sema &S, Decl *D, S.Context)); } +static void handleNoAddressSafetyAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + D->addAttr(::new (S.Context) NoAddressSafetyAnalysisAttr(Attr.getRange(), + S.Context)); +} + static void handleAcquireOrderAttr(Sema &S, Decl *D, const AttributeList &Attr, bool before) { assert(!Attr.isInvalid()); @@ -466,7 +478,7 @@ static void handleAcquireOrderAttr(Sema &S, Decl *D, const AttributeList &Attr, if (!QT->isDependentType()) { const RecordType *RT = getRecordType(QT); if (!RT || !RT->getDecl()->getAttr<LockableAttr>()) { - S.Diag(Attr.getLoc(), diag::err_attribute_decl_not_lockable) + S.Diag(Attr.getLoc(), diag::warn_attribute_decl_not_lockable) << Attr.getName(); return; } @@ -636,8 +648,7 @@ static void handleLockReturnedAttr(Sema &S, Decl *D, return; // check that the argument is lockable object - if (!checkForLockableRecord(S, D, Attr, getRecordType(Arg->getType()))) - return; + checkForLockableRecord(S, D, Attr, Arg->getType()); D->addAttr(::new (S.Context) LockReturnedAttr(Attr.getRange(), S.Context, Arg)); } @@ -684,10 +695,12 @@ static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D, // Special case where the argument is a template id. if (Attr.getParameterName()) { CXXScopeSpec SS; + SourceLocation TemplateKWLoc; UnqualifiedId id; id.setIdentifier(Attr.getParameterName(), Attr.getLoc()); - ExprResult Size = S.ActOnIdExpression(scope, SS, id, false, false); + ExprResult Size = S.ActOnIdExpression(scope, SS, TemplateKWLoc, id, + false, false); if (Size.isInvalid()) return; @@ -760,14 +773,14 @@ static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) { // have an object reference type. if (const ObjCIvarDecl *VD = dyn_cast<ObjCIvarDecl>(D)) { if (!VD->getType()->getAs<ObjCObjectPointerType>()) { - S.Diag(Attr.getLoc(), diag::err_iboutlet_object_type) + S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type) << Attr.getName() << VD->getType() << 0; return false; } } else if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) { if (!PD->getType()->getAs<ObjCObjectPointerType>()) { - S.Diag(Attr.getLoc(), diag::err_iboutlet_object_type) + S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type) << Attr.getName() << PD->getType() << 1; return false; } @@ -776,7 +789,7 @@ static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) { S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName(); return false; } - + return true; } @@ -805,7 +818,7 @@ static void handleIBOutletCollection(Sema &S, Decl *D, IdentifierInfo *II = Attr.getParameterName(); if (!II) - II = &S.Context.Idents.get("id"); + II = &S.Context.Idents.get("NSObject"); ParsedType TypeRep = S.getTypeName(*II, Attr.getLoc(), S.getScopeForContext(D->getDeclContext()->getParent())); @@ -818,8 +831,7 @@ static void handleIBOutletCollection(Sema &S, Decl *D, // FIXME. Gnu attribute extension ignores use of builtin types in // attributes. So, __attribute__((iboutletcollection(char))) will be // treated as __attribute__((iboutletcollection())). - if (!QT->isObjCIdType() && !QT->isObjCClassType() && - !QT->isObjCObjectType()) { + if (!QT->isObjCIdType() && !QT->isObjCObjectType()) { S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; return; } @@ -1056,8 +1068,6 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { } break; } - default: - llvm_unreachable("Unknown ownership attribute"); } // switch // Check we don't have a conflict with another ownership attribute. @@ -1108,7 +1118,6 @@ static bool hasEffectivelyInternalLinkage(NamedDecl *D) { return false; } llvm_unreachable("unknown linkage kind!"); - return false; } static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1580,6 +1589,39 @@ static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D, Attr.getRange(), S.Context)); } +static void handleObjCRootClassAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!isa<ObjCInterfaceDecl>(D)) { + S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface); + return; + } + + unsigned NumArgs = Attr.getNumArgs(); + if (NumArgs > 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0; + return; + } + + D->addAttr(::new (S.Context) ObjCRootClassAttr(Attr.getRange(), S.Context)); +} + +static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!isa<ObjCInterfaceDecl>(D)) { + S.Diag(Attr.getLoc(), diag::err_suppress_autosynthesis); + return; + } + + unsigned NumArgs = Attr.getNumArgs(); + if (NumArgs > 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0; + return; + } + + D->addAttr(::new (S.Context) ObjCRequiresPropertyDefsAttr( + Attr.getRange(), S.Context)); +} + static void handleAvailabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { IdentifierInfo *Platform = Attr.getParameterName(); @@ -1625,12 +1667,19 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, return; } + StringRef Str; + const StringLiteral *SE = + dyn_cast_or_null<const StringLiteral>(Attr.getMessageExpr()); + if (SE) + Str = SE->getString(); + D->addAttr(::new (S.Context) AvailabilityAttr(Attr.getRange(), S.Context, Platform, Introduced.Version, Deprecated.Version, Obsoleted.Version, - IsUnavailable)); + IsUnavailable, + Str)); } static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1657,9 +1706,16 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { type = VisibilityAttr::Hidden; else if (TypeStr == "internal") type = VisibilityAttr::Hidden; // FIXME - else if (TypeStr == "protected") - type = VisibilityAttr::Protected; - else { + else if (TypeStr == "protected") { + // Complain about attempts to use protected visibility on targets + // (like Darwin) that don't support it. + if (!S.Context.getTargetInfo().hasProtectedVisibility()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_protected_visibility); + type = VisibilityAttr::Default; + } else { + type = VisibilityAttr::Protected; + } + } else { S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr; return; } @@ -1747,6 +1803,15 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) { return; } } + else if (!isa<ObjCPropertyDecl>(D)) { + // It is okay to include this attribute on properties, e.g.: + // + // @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject)); + // + // In this case it follows tradition and suppresses an error in the above + // case. + S.Diag(D->getLocation(), diag::warn_nsobject_attribute); + } D->addAttr(::new (S.Context) ObjCNSObjectAttr(Attr.getRange(), S.Context)); } @@ -1853,10 +1918,11 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) { S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; return; } - } else if (isa<BlockDecl>(D)) { - // Note! BlockDecl is typeless. Variadic diagnostics will be issued by the - // caller. - ; + } else if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) { + if (!BD->isVariadic()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1; + return; + } } else if (const VarDecl *V = dyn_cast<VarDecl>(D)) { QualType Ty = V->getType(); if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) { @@ -1915,6 +1981,10 @@ 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; @@ -1946,7 +2016,7 @@ static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { << "weak_import" << 2 /*variable and function*/; else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) || (S.Context.getTargetInfo().getTriple().isOSDarwin() && - isa<ObjCInterfaceDecl>(D))) { + (isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) { // Nothing to warn about here. } else S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) @@ -2109,7 +2179,7 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { } D->addAttr(::new (S.Context) CleanupAttr(Attr.getRange(), S.Context, FD)); - S.MarkDeclarationReferenced(Attr.getParameterLoc(), FD); + S.MarkFunctionReferenced(Attr.getParameterLoc(), FD); } /// Handle __attribute__((format_arg((idx)))) attribute based on @@ -2209,8 +2279,7 @@ static FormatAttrKind getFormatAttrKind(StringRef Format) { // Otherwise, check for supported formats. if (Format == "scanf" || Format == "printf" || Format == "printf0" || - Format == "strfmon" || Format == "cmn_err" || Format == "strftime" || - Format == "NSString" || Format == "CFString" || Format == "vcmn_err" || + Format == "strfmon" || Format == "cmn_err" || Format == "vcmn_err" || Format == "zcmn_err" || Format == "kprintf") // OpenBSD. return SupportedFormat; @@ -2226,7 +2295,7 @@ static FormatAttrKind getFormatAttrKind(StringRef Format) { /// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html static void handleInitPriorityAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (!S.getLangOptions().CPlusPlus) { + if (!S.getLangOpts().CPlusPlus) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); return; } @@ -2541,6 +2610,10 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { } void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E) { + // FIXME: Handle pack-expansions here. + if (DiagnoseUnexpandedParameterPack(E)) + return; + if (E->isTypeDependent() || E->isValueDependent()) { // Save dependent expressions in the AST to be instantiated. D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, E)); @@ -2550,18 +2623,19 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E) { SourceLocation AttrLoc = AttrRange.getBegin(); // FIXME: Cache the number on the Attr object? llvm::APSInt Alignment(32); - if (!E->isIntegerConstantExpr(Alignment, Context)) { - Diag(AttrLoc, diag::err_attribute_argument_not_int) - << "aligned" << E->getSourceRange(); + ExprResult ICE = + VerifyIntegerConstantExpression(E, &Alignment, + PDiag(diag::err_attribute_argument_not_int) << "aligned", + /*AllowFold*/ false); + if (ICE.isInvalid()) return; - } if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) { Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two) << E->getSourceRange(); return; } - D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, E)); + D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, ICE.take())); } void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS) { @@ -2975,7 +3049,6 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { } default: llvm_unreachable("unexpected attribute kind"); - return; } } @@ -3024,7 +3097,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { } // FALLS THROUGH } - default: llvm_unreachable("unexpected attribute kind"); return true; + default: llvm_unreachable("unexpected attribute kind"); } return false; @@ -3195,7 +3268,7 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, returnType = MD->getResultType(); else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) returnType = PD->getType(); - else if (S.getLangOptions().ObjCAutoRefCount && hasDeclarator(D) && + else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) && (Attr.getKind() == AttributeList::AT_ns_returns_retained)) return; // ignore: was handled as a type attribute else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) @@ -3210,7 +3283,7 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, bool typeOK; bool cf; switch (Attr.getKind()) { - default: llvm_unreachable("invalid ownership attribute"); return; + default: llvm_unreachable("invalid ownership attribute"); case AttributeList::AT_ns_returns_autoreleased: case AttributeList::AT_ns_returns_retained: case AttributeList::AT_ns_returns_not_retained: @@ -3265,7 +3338,7 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, if (!isa<ObjCMethodDecl>(method)) { S.Diag(method->getLocStart(), diag::err_attribute_wrong_decl_type) - << SourceRange(loc, loc) << attr.getName() << 13 /* methods */; + << SourceRange(loc, loc) << attr.getName() << ExpectedMethod; return; } @@ -3290,7 +3363,7 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, 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() << 0 /*function*/; + << A.getRange() << A.getName() << ExpectedFunction; return; } @@ -3326,7 +3399,7 @@ static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D, RecordDecl *RD = dyn_cast<RecordDecl>(D); if (!RD || RD->isUnion()) { S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) - << Attr.getRange() << Attr.getName() << 14 /*struct */; + << Attr.getRange() << Attr.getName() << ExpectedStruct; } IdentifierInfo *ParmName = Attr.getParameterName(); @@ -3334,7 +3407,7 @@ static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D, // 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 (ParmName && S.getLangOptions().ObjC1) { + if (ParmName && S.getLangOpts().ObjC1) { // Check for an existing type with this name. LookupResult R(S, DeclarationName(ParmName), Attr.getParameterLoc(), Sema::LookupOrdinaryName); @@ -3356,14 +3429,14 @@ static void handleObjCOwnershipAttr(Sema &S, Decl *D, if (hasDeclarator(D)) return; S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) - << Attr.getRange() << Attr.getName() << 12 /* variable */; + << Attr.getRange() << Attr.getName() << ExpectedVariable; } 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() << 12 /* variable */; + << Attr.getRange() << Attr.getName() << ExpectedVariable; return; } @@ -3406,9 +3479,19 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, } static bool isKnownDeclSpecAttr(const AttributeList &Attr) { - return Attr.getKind() == AttributeList::AT_dllimport || - Attr.getKind() == AttributeList::AT_dllexport || - Attr.getKind() == AttributeList::AT_uuid; + switch (Attr.getKind()) { + default: + return false; + case AttributeList::AT_dllimport: + case AttributeList::AT_dllexport: + case AttributeList::AT_uuid: + case AttributeList::AT_deprecated: + case AttributeList::AT_noreturn: + case AttributeList::AT_nothrow: + case AttributeList::AT_naked: + case AttributeList::AT_noinline: + return true; + } } //===----------------------------------------------------------------------===// @@ -3433,7 +3516,7 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { bool IsCurly = StrRef.size() > 1 && StrRef.front() == '{' && StrRef.back() == '}'; - + // Validate GUID length. if (IsCurly && StrRef.size() != 38) { S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); @@ -3444,7 +3527,7 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or + // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" StringRef::iterator I = StrRef.begin(); if (IsCurly) // Skip the optional '{' @@ -3487,9 +3570,9 @@ static void ProcessNonInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, const AttributeList &Attr) { switch (Attr.getKind()) { - case AttributeList::AT_IBAction: handleIBAction(S, D, Attr); break; - case AttributeList::AT_IBOutlet: handleIBOutlet(S, D, Attr); break; - case AttributeList::AT_IBOutletCollection: + case AttributeList::AT_ibaction: handleIBAction(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_address_space: case AttributeList::AT_opencl_image_access: @@ -3574,19 +3657,25 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_cf_returns_retained: handleNSReturnsRetainedAttr(S, D, Attr); break; - case AttributeList::AT_reqd_wg_size: + case AttributeList::AT_reqd_work_group_size: handleReqdWorkGroupSize(S, D, Attr); break; case AttributeList::AT_init_priority: handleInitPriorityAttr(S, D, Attr); break; case AttributeList::AT_packed: handlePackedAttr (S, D, Attr); break; - case AttributeList::AT_MsStruct: handleMsStructAttr (S, D, Attr); break; + case AttributeList::AT_ms_struct: handleMsStructAttr (S, D, Attr); break; case AttributeList::AT_section: handleSectionAttr (S, D, Attr); break; case AttributeList::AT_unavailable: handleUnavailableAttr (S, D, Attr); break; - case AttributeList::AT_arc_weakref_unavailable: + case AttributeList::AT_objc_arc_weak_reference_unavailable: handleArcWeakrefUnavailableAttr (S, D, Attr); break; + case AttributeList::AT_objc_root_class: + handleObjCRootClassAttr(S, D, Attr); + break; + case AttributeList::AT_objc_requires_property_definitions: + handleObjCRequiresPropertyDefsAttr (S, D, Attr); + break; case AttributeList::AT_unused: handleUnusedAttr (S, D, Attr); break; case AttributeList::AT_returns_twice: handleReturnsTwiceAttr(S, D, Attr); @@ -3607,7 +3696,7 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_objc_method_family: handleObjCMethodFamilyAttr(S, D, Attr); break; - case AttributeList::AT_nsobject: handleObjCNSObject (S, D, Attr); break; + case AttributeList::AT_NSObject: 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; @@ -3647,6 +3736,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_scoped_lockable: handleLockableAttr(S, D, Attr, /*scoped = */true); break; + case AttributeList::AT_no_address_safety_analysis: + handleNoAddressSafetyAttr(S, D, Attr); + break; case AttributeList::AT_no_thread_safety_analysis: handleNoThreadSafetyAttr(S, D, Attr); break; @@ -3924,7 +4016,7 @@ static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag, "this system declaration uses an unsupported type")); return; } - if (S.getLangOptions().ObjCAutoRefCount) + if (S.getLangOpts().ObjCAutoRefCount) if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(decl)) { // FIXME. we may want to supress diagnostics for all // kind of forbidden type messages on unavailable functions. @@ -3982,7 +4074,7 @@ void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state, // We only want to actually emit delayed diagnostics when we // successfully parsed a decl. - if (decl && !decl->isInvalidDecl()) { + if (decl) { // We emit all the active diagnostics, not just those starting // from the saved state. The idea is this: we get one push for a // decl spec and another for each declarator; in a decl group like: @@ -3997,7 +4089,9 @@ void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state, switch (diag.Kind) { case DelayedDiagnostic::Deprecation: - S.HandleDelayedDeprecationCheck(diag, decl); + // Don't bother giving deprecation diagnostics if the decl is invalid. + if (!decl->isInvalidDecl()) + S.HandleDelayedDeprecationCheck(diag, decl); break; case DelayedDiagnostic::Access: @@ -4039,6 +4133,11 @@ void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, Diag(DD.Loc, diag::warn_deprecated_message) << DD.getDeprecationDecl()->getDeclName() << DD.getDeprecationMessage(); + else if (DD.getUnknownObjCClass()) { + Diag(DD.Loc, diag::warn_deprecated_fwdclass_message) + << DD.getDeprecationDecl()->getDeclName(); + Diag(DD.getUnknownObjCClass()->getLocation(), diag::note_forward_class); + } else Diag(DD.Loc, diag::warn_deprecated) << DD.getDeprecationDecl()->getDeclName(); @@ -4049,7 +4148,9 @@ void Sema::EmitDeprecationWarning(NamedDecl *D, StringRef Message, const ObjCInterfaceDecl *UnknownObjCClass) { // Delay if we're currently parsing a declaration. if (DelayedDiagnostics.shouldDelayDiagnostics()) { - DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D, Message)); + DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D, + UnknownObjCClass, + Message)); return; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp index a39584a..847f03c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp @@ -16,6 +16,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/ScopeInfo.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" @@ -31,7 +32,7 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" #include <map> #include <set> @@ -60,6 +61,7 @@ namespace { bool VisitExpr(Expr *Node); bool VisitDeclRefExpr(DeclRefExpr *DRE); bool VisitCXXThisExpr(CXXThisExpr *ThisE); + bool VisitLambdaExpr(LambdaExpr *Lambda); }; /// VisitExpr - Visit all of the children of this expression. @@ -84,7 +86,7 @@ namespace { // evaluated. Parameters of a function declared before a default // argument expression are in scope and can hide namespace and // class member names. - return S->Diag(DRE->getSourceRange().getBegin(), + return S->Diag(DRE->getLocStart(), diag::err_param_default_argument_references_param) << Param->getDeclName() << DefaultArg->getSourceRange(); } else if (VarDecl *VDecl = dyn_cast<VarDecl>(Decl)) { @@ -92,7 +94,7 @@ namespace { // Local variables shall not be used in default argument // expressions. if (VDecl->isLocalVarDecl()) - return S->Diag(DRE->getSourceRange().getBegin(), + return S->Diag(DRE->getLocStart(), diag::err_param_default_argument_references_local) << VDecl->getDeclName() << DefaultArg->getSourceRange(); } @@ -105,10 +107,21 @@ namespace { // C++ [dcl.fct.default]p8: // The keyword this shall not be used in a default argument of a // member function. - return S->Diag(ThisE->getSourceRange().getBegin(), + return S->Diag(ThisE->getLocStart(), diag::err_param_default_argument_references_this) << ThisE->getSourceRange(); } + + bool CheckDefaultArgumentVisitor::VisitLambdaExpr(LambdaExpr *Lambda) { + // C++11 [expr.lambda.prim]p13: + // A lambda-expression appearing in a default argument shall not + // implicitly or explicitly capture any entity. + if (Lambda->capture_begin() == Lambda->capture_end()) + return false; + + return S->Diag(Lambda->getLocStart(), + diag::err_lambda_capture_default_arg); + } } void Sema::ImplicitExceptionSpecification::CalledDecl(CXXMethodDecl *Method) { @@ -267,7 +280,7 @@ Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, UnparsedDefaultArgLocs.erase(Param); // Default arguments are only permitted in C++ - if (!getLangOptions().CPlusPlus) { + if (!getLangOpts().CPlusPlus) { Diag(EqualLoc, diag::err_param_default_argument) << DefaultArg->getSourceRange(); Param->setInvalidDecl(); @@ -359,7 +372,8 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { // function, once we already know that they have the same // type. Subroutine of MergeFunctionDecl. Returns true if there was an // error, false otherwise. -bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { +bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, + Scope *S) { bool Invalid = false; // C++ [dcl.fct.default]p4: @@ -384,7 +398,16 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { ParmVarDecl *OldParam = Old->getParamDecl(p); ParmVarDecl *NewParam = New->getParamDecl(p); - if (OldParam->hasDefaultArg() && NewParam->hasDefaultArg()) { + bool OldParamHasDfl = OldParam->hasDefaultArg(); + bool NewParamHasDfl = NewParam->hasDefaultArg(); + + NamedDecl *ND = Old; + if (S && !isDeclInScope(ND, New->getDeclContext(), S)) + // Ignore default parameters of old decl if they are not in + // the same scope. + OldParamHasDfl = false; + + if (OldParamHasDfl && NewParamHasDfl) { unsigned DiagDefaultParamID = diag::err_param_default_argument_redefinition; @@ -392,7 +415,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { // MSVC accepts that default parameters be redefined for member functions // of template class. The new default parameter's value is ignored. Invalid = true; - if (getLangOptions().MicrosoftExt) { + if (getLangOpts().MicrosoftExt) { CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(New); if (MD && MD->getParent()->getDescribedClassTemplate()) { // Merge the old default argument into the new parameter. @@ -420,8 +443,8 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { // Look for the function declaration where the default argument was // actually written, which may be a declaration prior to Old. - for (FunctionDecl *Older = Old->getPreviousDeclaration(); - Older; Older = Older->getPreviousDeclaration()) { + for (FunctionDecl *Older = Old->getPreviousDecl(); + Older; Older = Older->getPreviousDecl()) { if (!Older->getParamDecl(p)->hasDefaultArg()) break; @@ -430,7 +453,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { Diag(OldParam->getLocation(), diag::note_previous_definition) << OldParam->getDefaultArgRange(); - } else if (OldParam->hasDefaultArg()) { + } else if (OldParamHasDfl) { // Merge the old default argument into the new parameter. // It's important to use getInit() here; getDefaultArg() // strips off any top-level ExprWithCleanups. @@ -440,7 +463,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { OldParam->getUninstantiatedDefaultArg()); else NewParam->setDefaultArg(OldParam->getInit()); - } else if (NewParam->hasDefaultArg()) { + } else if (NewParamHasDfl) { if (New->getDescribedFunctionTemplate()) { // Paragraph 4, quoted above, only applies to non-template functions. Diag(NewParam->getLocation(), @@ -502,13 +525,9 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { } } - // C++0x [dcl.constexpr]p1: If any declaration of a function or function + // 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. [Note: An explicit specialization can - // differ from the template declaration with respect to the constexpr - // specifier. -- end note] - // - // FIXME: Don't reject changes in constexpr in explicit specializations. + // contain the constexpr specifier. if (New->isConstexpr() != Old->isConstexpr()) { Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch) << New << New->isConstexpr(); @@ -529,7 +548,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { /// validates compatibility and merges the specs if necessary. void Sema::MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old) { // Shortcut if exceptions are disabled. - if (!getLangOptions().CXXExceptions) + if (!getLangOpts().CXXExceptions) return; assert(Context.hasSameType(New->getType(), Old->getType()) && @@ -571,11 +590,25 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { unsigned NumParams = FD->getNumParams(); unsigned p; + bool IsLambda = FD->getOverloadedOperator() == OO_Call && + isa<CXXMethodDecl>(FD) && + cast<CXXMethodDecl>(FD)->getParent()->isLambda(); + // Find first parameter with a default argument for (p = 0; p < NumParams; ++p) { ParmVarDecl *Param = FD->getParamDecl(p); - if (Param->hasDefaultArg()) + if (Param->hasDefaultArg()) { + // C++11 [expr.prim.lambda]p5: + // [...] Default arguments (8.3.6) shall not be specified in the + // parameter-declaration-clause of a lambda-declarator. + // + // FIXME: Core issue 974 strikes this sentence, we only provide an + // extension warning. + if (IsLambda) + Diag(Param->getLocation(), diag::ext_lambda_default_arguments) + << Param->getDefaultArgRange(); break; + } } // C++ [dcl.fct.default]p4: @@ -618,9 +651,9 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { // CheckConstexprParameterTypes - Check whether a function's parameter types // are all literal types. If so, return true. If not, produce a suitable -// diagnostic depending on @p CCK and return false. -static bool CheckConstexprParameterTypes(Sema &SemaRef, const FunctionDecl *FD, - Sema::CheckConstexprKind CCK) { +// diagnostic and return false. +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(), @@ -628,107 +661,73 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef, const FunctionDecl *FD, const ParmVarDecl *PD = FD->getParamDecl(ArgIndex); SourceLocation ParamLoc = PD->getLocation(); if (!(*i)->isDependentType() && - SemaRef.RequireLiteralType(ParamLoc, *i, CCK == Sema::CCK_Declaration ? + SemaRef.RequireLiteralType(ParamLoc, *i, SemaRef.PDiag(diag::err_constexpr_non_literal_param) << ArgIndex+1 << PD->getSourceRange() - << isa<CXXConstructorDecl>(FD) : - SemaRef.PDiag(), - /*AllowIncompleteType*/ true)) { - if (CCK == Sema::CCK_NoteNonConstexprInstantiation) - SemaRef.Diag(ParamLoc, diag::note_constexpr_tmpl_non_literal_param) - << ArgIndex+1 << PD->getSourceRange() - << isa<CXXConstructorDecl>(FD) << *i; + << isa<CXXConstructorDecl>(FD))) return false; - } } return true; } // CheckConstexprFunctionDecl - Check whether a function declaration satisfies -// the requirements of a constexpr function declaration or a constexpr -// constructor declaration. Return true if it does, false if not. -// -// This implements C++0x [dcl.constexpr]p3,4, as amended by N3308. +// the requirements of a constexpr function definition or a constexpr +// constructor definition. If so, return true. If not, produce appropriate +// diagnostics and return false. // -// \param CCK Specifies whether to produce diagnostics if the function does not -// satisfy the requirements. -bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD, - CheckConstexprKind CCK) { - assert((CCK != CCK_NoteNonConstexprInstantiation || - (NewFD->getTemplateInstantiationPattern() && - NewFD->getTemplateInstantiationPattern()->isConstexpr())) && - "only constexpr templates can be instantiated non-constexpr"); - - if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(NewFD)) { - // C++0x [dcl.constexpr]p4: - // In the definition of a constexpr constructor, each of the parameter - // types shall be a literal type. - if (!CheckConstexprParameterTypes(*this, NewFD, CCK)) - return false; - - // In addition, either its function-body shall be = delete or = default or - // it shall satisfy the following constraints: +// This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360. +bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) { + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD); + if (MD && MD->isInstance()) { + // C++11 [dcl.constexpr]p4: + // The definition of a constexpr constructor shall satisfy the following + // constraints: // - the class shall not have any virtual base classes; - const CXXRecordDecl *RD = CD->getParent(); + const CXXRecordDecl *RD = MD->getParent(); if (RD->getNumVBases()) { - // Note, this is still illegal if the body is = default, since the - // implicit body does not satisfy the requirements of a constexpr - // constructor. We also reject cases where the body is = delete, as - // required by N3308. - if (CCK != CCK_Instantiation) { - Diag(NewFD->getLocation(), - CCK == CCK_Declaration ? diag::err_constexpr_virtual_base - : diag::note_constexpr_tmpl_virtual_base) - << RD->isStruct() << RD->getNumVBases(); - for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), - E = RD->vbases_end(); I != E; ++I) - Diag(I->getSourceRange().getBegin(), - diag::note_constexpr_virtual_base_here) << I->getSourceRange(); - } + Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base) + << isa<CXXConstructorDecl>(NewFD) << RD->isStruct() + << 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(); return false; } - } else { - // C++0x [dcl.constexpr]p3: + } + + if (!isa<CXXConstructorDecl>(NewFD)) { + // C++11 [dcl.constexpr]p3: // The definition of a constexpr function shall satisfy the following // constraints: // - it shall not be virtual; const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD); if (Method && Method->isVirtual()) { - if (CCK != CCK_Instantiation) { - Diag(NewFD->getLocation(), - CCK == CCK_Declaration ? diag::err_constexpr_virtual - : diag::note_constexpr_tmpl_virtual); - - // If it's not obvious why this function is virtual, find an overridden - // function which uses the 'virtual' keyword. - const CXXMethodDecl *WrittenVirtual = Method; - while (!WrittenVirtual->isVirtualAsWritten()) - WrittenVirtual = *WrittenVirtual->begin_overridden_methods(); - if (WrittenVirtual != Method) - Diag(WrittenVirtual->getLocation(), - diag::note_overridden_virtual_function); - } + Diag(NewFD->getLocation(), diag::err_constexpr_virtual); + + // If it's not obvious why this function is virtual, find an overridden + // function which uses the 'virtual' keyword. + const CXXMethodDecl *WrittenVirtual = Method; + while (!WrittenVirtual->isVirtualAsWritten()) + WrittenVirtual = *WrittenVirtual->begin_overridden_methods(); + if (WrittenVirtual != Method) + Diag(WrittenVirtual->getLocation(), + diag::note_overridden_virtual_function); return false; } // - its return type shall be a literal type; QualType RT = NewFD->getResultType(); if (!RT->isDependentType() && - RequireLiteralType(NewFD->getLocation(), RT, CCK == CCK_Declaration ? - PDiag(diag::err_constexpr_non_literal_return) : - PDiag(), - /*AllowIncompleteType*/ true)) { - if (CCK == CCK_NoteNonConstexprInstantiation) - Diag(NewFD->getLocation(), - diag::note_constexpr_tmpl_non_literal_return) << RT; - return false; - } - - // - each of its parameter types shall be a literal type; - if (!CheckConstexprParameterTypes(*this, NewFD, CCK)) + RequireLiteralType(NewFD->getLocation(), RT, + PDiag(diag::err_constexpr_non_literal_return))) return false; } + // - each of its parameter types shall be a literal type; + if (!CheckConstexprParameterTypes(*this, NewFD)) + return false; + return true; } @@ -812,7 +811,11 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef, bool &Diagnosed) { if (Field->isUnnamedBitfield()) return; - + + if (Field->isAnonymousStructOrUnion() && + Field->getType()->getAsCXXRecordDecl()->isEmpty()) + return; + if (!Inits.count(Field)) { if (!Diagnosed) { SemaRef.Diag(Dcl->getLocation(), diag::err_constexpr_ctor_missing_init); @@ -836,13 +839,13 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef, /// \return true if the body is OK, false if we have diagnosed a problem. bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { if (isa<CXXTryStmt>(Body)) { - // C++0x [dcl.constexpr]p3: + // C++11 [dcl.constexpr]p3: // The definition of a constexpr function shall satisfy the following // constraints: [...] // - its function-body shall be = delete, = default, or a // compound-statement // - // C++0x [dcl.constexpr]p4: + // C++11 [dcl.constexpr]p4: // In the definition of a constexpr constructor, [...] // - its function-body shall not be a function-try-block; Diag(Body->getLocStart(), diag::err_constexpr_function_try_block) @@ -877,12 +880,6 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { break; ReturnStmts.push_back((*BodyIt)->getLocStart()); - // FIXME - // - every constructor call and implicit conversion used in initializing - // the return value shall be one of those allowed in a constant - // expression. - // Deal with this as part of a general check that the function can produce - // a constant expression (for [dcl.constexpr]p5). continue; default: @@ -897,11 +894,14 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { if (const CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Dcl)) { const CXXRecordDecl *RD = Constructor->getParent(); - // - every non-static data member and base class sub-object shall be - // initialized; + // 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 + // shall be initialized; if (RD->isUnion()) { - // DR1359: Exactly one member of a union shall be initialized. - if (Constructor->getNumCtorInitializers() == 0) { + if (Constructor->getNumCtorInitializers() == 0 && !RD->isEmpty()) { Diag(Dcl->getLocation(), diag::err_constexpr_union_ctor_no_init); return false; } @@ -943,20 +943,6 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { return false; } } - - // FIXME - // - every constructor involved in initializing non-static data members - // and base class sub-objects shall be a constexpr constructor; - // - every assignment-expression that is an initializer-clause appearing - // directly or indirectly within a brace-or-equal-initializer for - // a non-static data member that is not named by a mem-initializer-id - // shall be a constant expression; and - // - every implicit conversion used in converting a constructor argument - // to the corresponding parameter type and converting - // a full-expression to the corresponding member type shall be one of - // those allowed in a constant expression. - // Deal with these as part of a general check that the function can produce - // a constant expression (for [dcl.constexpr]p5). } else { if (ReturnStmts.empty()) { Diag(Dcl->getLocation(), diag::err_constexpr_body_no_return); @@ -970,6 +956,25 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { } } + // C++11 [dcl.constexpr]p5: + // if no function argument values exist such that the function invocation + // substitution would produce a constant expression, the program is + // ill-formed; no diagnostic required. + // C++11 [dcl.constexpr]p3: + // - every constructor call and implicit conversion used in initializing the + // return value shall be one of those allowed in a constant expression. + // C++11 [dcl.constexpr]p4: + // - every constructor involved in initializing non-static data members and + // base class sub-objects shall be a constexpr constructor. + llvm::SmallVector<PartialDiagnosticAt, 8> Diags; + if (!Expr::isPotentialConstantExpr(Dcl, Diags)) { + Diag(Dcl->getLocation(), diag::err_constexpr_function_never_constant_expr) + << isa<CXXConstructorDecl>(Dcl); + for (size_t I = 0, N = Diags.size(); I != N; ++I) + Diag(Diags[I].first, Diags[I].second); + return false; + } + return true; } @@ -979,7 +984,7 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { /// the innermost class. bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *, const CXXScopeSpec *SS) { - assert(getLangOptions().CPlusPlus && "No class names in C!"); + assert(getLangOpts().CPlusPlus && "No class names in C!"); CXXRecordDecl *CurDecl; if (SS && SS->isSet() && !SS->isInvalid()) { @@ -1133,13 +1138,15 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, QualType NewBaseType = Context.getCanonicalType(Bases[idx]->getType()); NewBaseType = NewBaseType.getLocalUnqualifiedType(); - if (KnownBaseTypes[NewBaseType]) { + + CXXBaseSpecifier *&KnownBase = KnownBaseTypes[NewBaseType]; + if (KnownBase) { // C++ [class.mi]p3: // A class shall not be specified as a direct base class of a // derived class more than once. - Diag(Bases[idx]->getSourceRange().getBegin(), + Diag(Bases[idx]->getLocStart(), diag::err_duplicate_base_class) - << KnownBaseTypes[NewBaseType]->getType() + << KnownBase->getType() << Bases[idx]->getSourceRange(); // Delete the duplicate base class specifier; we're going to @@ -1149,8 +1156,12 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, Invalid = true; } else { // Okay, add this new base class. - KnownBaseTypes[NewBaseType] = Bases[idx]; + KnownBase = Bases[idx]; Bases[NumGoodBases++] = Bases[idx]; + if (const RecordType *Record = NewBaseType->getAs<RecordType>()) + if (const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl())) + if (RD->hasAttr<WeakAttr>()) + Class->addAttr(::new (Context) WeakAttr(SourceRange(), Context)); } } @@ -1190,7 +1201,7 @@ static CXXRecordDecl *GetClassForType(QualType T) { /// \brief Determine whether the type \p Derived is a C++ class that is /// derived from the type \p Base. bool Sema::IsDerivedFrom(QualType Derived, QualType Base) { - if (!getLangOptions().CPlusPlus) + if (!getLangOpts().CPlusPlus) return false; CXXRecordDecl *DerivedRD = GetClassForType(Derived); @@ -1208,7 +1219,7 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base) { /// \brief Determine whether the type \p Derived is a C++ class that is /// derived from the type \p Base. bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) { - if (!getLangOptions().CPlusPlus) + if (!getLangOpts().CPlusPlus) return false; CXXRecordDecl *DerivedRD = GetClassForType(Derived); @@ -1441,7 +1452,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, // For anonymous bitfields, the location should point to the type. if (Loc.isInvalid()) - Loc = D.getSourceRange().getBegin(); + Loc = D.getLocStart(); Expr *BitWidth = static_cast<Expr*>(BW); @@ -1527,14 +1538,12 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, // class X { // int X::member; // }; - DeclContext *DC = 0; - if ((DC = computeDeclContext(SS, false)) && DC->Equals(CurContext)) - Diag(D.getIdentifierLoc(), diag::warn_member_extra_qualification) - << Name << FixItHint::CreateRemoval(SS.getRange()); + if (DeclContext *DC = computeDeclContext(SS, false)) + diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc()); else Diag(D.getIdentifierLoc(), diag::err_member_qualification) << Name << SS.getRange(); - + SS.clear(); } @@ -1631,11 +1640,26 @@ Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation EqualLoc, return; } + if (DiagnoseUnexpandedParameterPack(InitExpr, UPPC_Initializer)) { + FD->setInvalidDecl(); + FD->removeInClassInitializer(); + return; + } + ExprResult Init = InitExpr; if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { - // FIXME: if there is no EqualLoc, this is list-initialization. - Init = PerformCopyInitialization( - InitializedEntity::InitializeMember(FD), EqualLoc, InitExpr); + if (isa<InitListExpr>(InitExpr) && isStdInitializerList(FD->getType(), 0)) { + Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list) + << /*at end of ctor*/1 << InitExpr->getSourceRange(); + } + Expr **Inits = &InitExpr; + unsigned NumInits = 1; + InitializedEntity Entity = InitializedEntity::InitializeMember(FD); + InitializationKind Kind = EqualLoc.isInvalid() + ? InitializationKind::CreateDirectList(InitExpr->getLocStart()) + : InitializationKind::CreateCopy(InitExpr->getLocStart(), EqualLoc); + InitializationSequence Seq(*this, Entity, Kind, Inits, NumInits); + Init = Seq.Perform(*this, Entity, Kind, MultiExprArg(Inits, NumInits)); if (Init.isInvalid()) { FD->setInvalidDecl(); return; @@ -1710,11 +1734,13 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, ParsedType TemplateTypeTy, + const DeclSpec &DS, SourceLocation IdLoc, Expr *InitList, SourceLocation EllipsisLoc) { return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, - IdLoc, MultiInitializer(InitList), EllipsisLoc); + DS, IdLoc, InitList, + EllipsisLoc); } /// \brief Handle a C++ member initializer using parentheses syntax. @@ -1724,15 +1750,41 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, ParsedType TemplateTypeTy, + const DeclSpec &DS, SourceLocation IdLoc, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc, SourceLocation EllipsisLoc) { + Expr *List = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, + RParenLoc); return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, - IdLoc, MultiInitializer(LParenLoc, Args, NumArgs, - RParenLoc), - EllipsisLoc); + DS, IdLoc, List, EllipsisLoc); +} + +namespace { + +// Callback to only accept typo corrections that can be a valid C++ member +// intializer: either a non-static field member or a base class. +class MemInitializerValidatorCCC : public CorrectionCandidateCallback { + public: + explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl) + : ClassDecl(ClassDecl) {} + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + if (NamedDecl *ND = candidate.getCorrectionDecl()) { + if (FieldDecl *Member = dyn_cast<FieldDecl>(ND)) + return Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl); + else + return isa<TypeDecl>(ND); + } + return false; + } + + private: + CXXRecordDecl *ClassDecl; +}; + } /// \brief Handle a C++ member initializer. @@ -1742,8 +1794,9 @@ Sema::BuildMemInitializer(Decl *ConstructorD, CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, ParsedType TemplateTypeTy, + const DeclSpec &DS, SourceLocation IdLoc, - const MultiInitializer &Args, + Expr *Init, SourceLocation EllipsisLoc) { if (!ConstructorD) return true; @@ -1774,28 +1827,18 @@ Sema::BuildMemInitializer(Decl *ConstructorD, // using a qualified name. ] if (!SS.getScopeRep() && !TemplateTypeTy) { // Look for a member, first. - FieldDecl *Member = 0; DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase); if (Result.first != Result.second) { - Member = dyn_cast<FieldDecl>(*Result.first); - - if (Member) { - if (EllipsisLoc.isValid()) - Diag(EllipsisLoc, diag::err_pack_expansion_member_init) - << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc()); - - return BuildMemberInitializer(Member, Args, IdLoc); - } - - // Handle anonymous union case. - if (IndirectFieldDecl* IndirectField - = dyn_cast<IndirectFieldDecl>(*Result.first)) { + ValueDecl *Member; + if ((Member = dyn_cast<FieldDecl>(*Result.first)) || + (Member = dyn_cast<IndirectFieldDecl>(*Result.first))) { if (EllipsisLoc.isValid()) Diag(EllipsisLoc, diag::err_pack_expansion_member_init) - << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc()); + << MemberOrBase + << SourceRange(IdLoc, Init->getSourceRange().getEnd()); - return BuildMemberInitializer(IndirectField, Args, IdLoc); + return BuildMemberInitializer(Member, Init, IdLoc); } } } @@ -1805,6 +1848,8 @@ Sema::BuildMemInitializer(Decl *ConstructorD, if (TemplateTypeTy) { BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo); + } else if (DS.getTypeSpecType() == TST_decltype) { + BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); } else { LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName); LookupParsedName(R, S, &SS); @@ -1838,24 +1883,23 @@ Sema::BuildMemInitializer(Decl *ConstructorD, // If no results were found, try to correct typos. TypoCorrection Corr; + MemInitializerValidatorCCC Validator(ClassDecl); if (R.empty() && BaseType.isNull() && (Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS, - ClassDecl, false, CTC_NoKeywords))) { - std::string CorrectedStr(Corr.getAsString(getLangOptions())); - std::string CorrectedQuotedStr(Corr.getQuoted(getLangOptions())); + Validator, ClassDecl))) { + std::string CorrectedStr(Corr.getAsString(getLangOpts())); + std::string CorrectedQuotedStr(Corr.getQuoted(getLangOpts())); if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) { - if (Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl)) { - // We have found a non-static data member with a similar - // name to what was typed; complain and initialize that - // member. - Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest) - << MemberOrBase << true << CorrectedQuotedStr - << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); - Diag(Member->getLocation(), diag::note_previous_decl) - << CorrectedQuotedStr; - - return BuildMemberInitializer(Member, Args, IdLoc); - } + // We have found a non-static data member with a similar + // name to what was typed; complain and initialize that + // member. + Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest) + << MemberOrBase << true << CorrectedQuotedStr + << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); + Diag(Member->getLocation(), diag::note_previous_decl) + << CorrectedQuotedStr; + + return BuildMemberInitializer(Member, Init, IdLoc); } else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) { const CXXBaseSpecifier *DirectBaseSpec; const CXXBaseSpecifier *VirtualBaseSpec; @@ -1871,7 +1915,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD, const CXXBaseSpecifier *BaseSpec = DirectBaseSpec? DirectBaseSpec : VirtualBaseSpec; - Diag(BaseSpec->getSourceRange().getBegin(), + Diag(BaseSpec->getLocStart(), diag::note_base_class_specified_here) << BaseSpec->getType() << BaseSpec->getSourceRange(); @@ -1883,7 +1927,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD, if (!TyD && BaseType.isNull()) { Diag(IdLoc, diag::err_mem_init_not_member_or_class) - << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc()); + << MemberOrBase << SourceRange(IdLoc,Init->getSourceRange().getEnd()); return true; } } @@ -1903,7 +1947,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD, if (!TInfo) TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc); - return BuildBaseInitializer(BaseType, TInfo, Args, ClassDecl, EllipsisLoc); + return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc); } /// Checks a member initializer expression for cases where reference (or @@ -2030,14 +2074,16 @@ static bool InitExprContainsUninitializedFields(const Stmt *S, } MemInitResult -Sema::BuildMemberInitializer(ValueDecl *Member, - const MultiInitializer &Args, +Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, SourceLocation IdLoc) { FieldDecl *DirectMember = dyn_cast<FieldDecl>(Member); IndirectFieldDecl *IndirectMember = dyn_cast<IndirectFieldDecl>(Member); assert((DirectMember || IndirectMember) && "Member must be a FieldDecl or IndirectFieldDecl"); + if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) + return true; + if (Member->isInvalidDecl()) return true; @@ -2045,13 +2091,19 @@ Sema::BuildMemberInitializer(ValueDecl *Member, // foo(foo) // where foo is not also a parameter to the constructor. // TODO: implement -Wuninitialized and fold this into that framework. - for (MultiInitializer::iterator I = Args.begin(), E = Args.end(); - I != E; ++I) { + Expr **Args; + unsigned NumArgs; + if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { + Args = ParenList->getExprs(); + NumArgs = ParenList->getNumExprs(); + } else { + InitListExpr *InitList = cast<InitListExpr>(Init); + Args = InitList->getInits(); + NumArgs = InitList->getNumInits(); + } + for (unsigned i = 0; i < NumArgs; ++i) { SourceLocation L; - Expr *Arg = *I; - if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Arg)) - Arg = DIE->getInit(); - if (InitExprContainsUninitializedFields(Arg, Member, &L)) { + if (InitExprContainsUninitializedFields(Args[i], Member, &L)) { // FIXME: Return true in the case when other fields are used before being // uninitialized. For example, let this field be the i'th field. When // initializing the i'th field, throw a warning if any of the >= i'th @@ -2062,29 +2114,43 @@ Sema::BuildMemberInitializer(ValueDecl *Member, } } - bool HasDependentArg = Args.isTypeDependent(); + SourceRange InitRange = Init->getSourceRange(); - Expr *Init; - if (Member->getType()->isDependentType() || HasDependentArg) { + if (Member->getType()->isDependentType() || Init->isTypeDependent()) { // Can't check initialization for a member of dependent type or when // any of the arguments are type-dependent expressions. - Init = Args.CreateInitExpr(Context,Member->getType().getNonReferenceType()); - DiscardCleanupsInEvaluationContext(); } else { + bool InitList = false; + if (isa<InitListExpr>(Init)) { + InitList = true; + Args = &Init; + NumArgs = 1; + + if (isStdInitializerList(Member->getType(), 0)) { + Diag(IdLoc, diag::warn_dangling_std_initializer_list) + << /*at end of ctor*/1 << InitRange; + } + } + // Initialize the member. InitializedEntity MemberEntity = DirectMember ? InitializedEntity::InitializeMember(DirectMember, 0) : InitializedEntity::InitializeMember(IndirectMember, 0); InitializationKind Kind = - InitializationKind::CreateDirect(IdLoc, Args.getStartLoc(), - Args.getEndLoc()); - - ExprResult MemberInit = Args.PerformInit(*this, MemberEntity, Kind); + InitList ? InitializationKind::CreateDirectList(IdLoc) + : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(), + InitRange.getEnd()); + + InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs); + ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, + MultiExprArg(*this, Args, NumArgs), + 0); if (MemberInit.isInvalid()) return true; - CheckImplicitConversions(MemberInit.get(), Args.getStartLoc()); + CheckImplicitConversions(MemberInit.get(), + InitRange.getBegin()); // C++0x [class.base.init]p7: // The initialization of each base and member constitutes a @@ -2095,14 +2161,13 @@ Sema::BuildMemberInitializer(ValueDecl *Member, // If we are in a dependent context, template instantiation will // perform this type-checking again. Just save the arguments that we - // received in a ParenListExpr. + // received. // FIXME: This isn't quite ideal, since our ASTs don't capture all // of the information that we have about the member // 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()) { - Init = Args.CreateInitExpr(Context, - Member->getType().getNonReferenceType()); + // The existing Init will do fine. } else { Init = MemberInit.get(); CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc); @@ -2110,43 +2175,53 @@ Sema::BuildMemberInitializer(ValueDecl *Member, } if (DirectMember) { - return new (Context) CXXCtorInitializer(Context, DirectMember, - IdLoc, Args.getStartLoc(), - Init, Args.getEndLoc()); + return new (Context) CXXCtorInitializer(Context, DirectMember, IdLoc, + InitRange.getBegin(), Init, + InitRange.getEnd()); } else { - return new (Context) CXXCtorInitializer(Context, IndirectMember, - IdLoc, Args.getStartLoc(), - Init, Args.getEndLoc()); + return new (Context) CXXCtorInitializer(Context, IndirectMember, IdLoc, + InitRange.getBegin(), Init, + InitRange.getEnd()); } } MemInitResult -Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, - const MultiInitializer &Args, - SourceLocation NameLoc, +Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, CXXRecordDecl *ClassDecl) { - SourceLocation Loc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); + SourceLocation NameLoc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); if (!LangOpts.CPlusPlus0x) - return Diag(Loc, diag::err_delegation_0x_only) + return Diag(NameLoc, diag::err_delegating_ctor) << TInfo->getTypeLoc().getLocalSourceRange(); + Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor); + bool InitList = true; + Expr **Args = &Init; + unsigned NumArgs = 1; + if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { + InitList = false; + Args = ParenList->getExprs(); + NumArgs = ParenList->getNumExprs(); + } + + SourceRange InitRange = Init->getSourceRange(); // Initialize the object. InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( QualType(ClassDecl->getTypeForDecl(), 0)); InitializationKind Kind = - InitializationKind::CreateDirect(NameLoc, Args.getStartLoc(), - Args.getEndLoc()); - - ExprResult DelegationInit = Args.PerformInit(*this, DelegationEntity, Kind); + InitList ? InitializationKind::CreateDirectList(NameLoc) + : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(), + InitRange.getEnd()); + InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs); + ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind, + MultiExprArg(*this, Args,NumArgs), + 0); if (DelegationInit.isInvalid()) return true; - CXXConstructExpr *ConExpr = cast<CXXConstructExpr>(DelegationInit.get()); - CXXConstructorDecl *Constructor - = ConExpr->getConstructor(); - assert(Constructor && "Delegating constructor with no target?"); + assert(cast<CXXConstructExpr>(DelegationInit.get())->getConstructor() && + "Delegating constructor with no target?"); - CheckImplicitConversions(DelegationInit.get(), Args.getStartLoc()); + CheckImplicitConversions(DelegationInit.get(), InitRange.getBegin()); // C++0x [class.base.init]p7: // The initialization of each base and member constitutes a @@ -2155,20 +2230,15 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, if (DelegationInit.isInvalid()) return true; - assert(!CurContext->isDependentContext()); - return new (Context) CXXCtorInitializer(Context, Loc, Args.getStartLoc(), - Constructor, + return new (Context) CXXCtorInitializer(Context, TInfo, InitRange.getBegin(), DelegationInit.takeAs<Expr>(), - Args.getEndLoc()); + InitRange.getEnd()); } MemInitResult Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, - const MultiInitializer &Args, - CXXRecordDecl *ClassDecl, + Expr *Init, CXXRecordDecl *ClassDecl, SourceLocation EllipsisLoc) { - bool HasDependentArg = Args.isTypeDependent(); - SourceLocation BaseLoc = BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin(); @@ -2182,13 +2252,14 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, // of that class, the mem-initializer is ill-formed. A // mem-initializer-list can initialize a base class using any // name that denotes that base class type. - bool Dependent = BaseType->isDependentType() || HasDependentArg; + bool Dependent = BaseType->isDependentType() || Init->isTypeDependent(); + SourceRange InitRange = Init->getSourceRange(); if (EllipsisLoc.isValid()) { // This is a pack expansion. if (!BaseType->containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) - << SourceRange(BaseLoc, Args.getEndLoc()); + << SourceRange(BaseLoc, InitRange.getEnd()); EllipsisLoc = SourceLocation(); } @@ -2197,7 +2268,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, if (DiagnoseUnexpandedParameterPack(BaseLoc, BaseTInfo, UPPC_Initializer)) return true; - if (Args.DiagnoseUnexpandedParameterPack(*this)) + if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) return true; } @@ -2207,7 +2278,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, if (!Dependent) { if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0), BaseType)) - return BuildDelegatingInitializer(BaseTInfo, Args, BaseLoc, ClassDecl); + return BuildDelegatingInitializer(BaseTInfo, Init, ClassDecl); FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, VirtualBaseSpec); @@ -2232,16 +2303,12 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, } if (Dependent) { - // Can't check initialization for a base of dependent type or when - // any of the arguments are type-dependent expressions. - Expr *BaseInit = Args.CreateInitExpr(Context, BaseType); - DiscardCleanupsInEvaluationContext(); return new (Context) CXXCtorInitializer(Context, BaseTInfo, /*IsVirtual=*/false, - Args.getStartLoc(), BaseInit, - Args.getEndLoc(), EllipsisLoc); + InitRange.getBegin(), Init, + InitRange.getEnd(), EllipsisLoc); } // C++ [base.class.init]p2: @@ -2252,23 +2319,34 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, return Diag(BaseLoc, diag::err_base_init_direct_and_virtual) << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange(); - CXXBaseSpecifier *BaseSpec - = const_cast<CXXBaseSpecifier *>(DirectBaseSpec); + CXXBaseSpecifier *BaseSpec = const_cast<CXXBaseSpecifier *>(DirectBaseSpec); if (!BaseSpec) BaseSpec = const_cast<CXXBaseSpecifier *>(VirtualBaseSpec); // Initialize the base. + bool InitList = true; + Expr **Args = &Init; + unsigned NumArgs = 1; + if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { + InitList = false; + Args = ParenList->getExprs(); + NumArgs = ParenList->getNumExprs(); + } + InitializedEntity BaseEntity = InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec); - InitializationKind Kind = - InitializationKind::CreateDirect(BaseLoc, Args.getStartLoc(), - Args.getEndLoc()); - - ExprResult BaseInit = Args.PerformInit(*this, BaseEntity, Kind); + InitializationKind Kind = + InitList ? InitializationKind::CreateDirectList(BaseLoc) + : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(), + InitRange.getEnd()); + InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs); + ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, + MultiExprArg(*this, Args, NumArgs), + 0); if (BaseInit.isInvalid()) return true; - CheckImplicitConversions(BaseInit.get(), Args.getStartLoc()); + CheckImplicitConversions(BaseInit.get(), InitRange.getBegin()); // C++0x [class.base.init]p7: // The initialization of each base and member constitutes a @@ -2285,13 +2363,13 @@ 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(Args.CreateInitExpr(Context, BaseType)); + BaseInit = Owned(Init); return new (Context) CXXCtorInitializer(Context, BaseTInfo, BaseSpec->isVirtual(), - Args.getStartLoc(), + InitRange.getBegin(), BaseInit.takeAs<Expr>(), - Args.getEndLoc(), EllipsisLoc); + InitRange.getEnd(), EllipsisLoc); } // Create a static_cast\<T&&>(expr). @@ -2342,12 +2420,15 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, bool Moving = ImplicitInitKind == IIK_Move; ParmVarDecl *Param = Constructor->getParamDecl(0); QualType ParamType = Param->getType().getNonReferenceType(); - + Expr *CopyCtorArg = - DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param, + DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), + SourceLocation(), Param, false, Constructor->getLocation(), ParamType, VK_LValue, 0); + SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(CopyCtorArg)); + // Cast to the base class to avoid ambiguities. QualType ArgTy = SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(), @@ -2415,11 +2496,14 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, // Suppress copying zero-width bitfields. if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0) return false; - + Expr *MemberExprBase = - DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param, + DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), + SourceLocation(), Param, false, Loc, ParamType, VK_LValue, 0); + SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(MemberExprBase)); + if (Moving) { MemberExprBase = CastForMoving(SemaRef, MemberExprBase); } @@ -2436,6 +2520,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, ParamType, Loc, /*IsArrow=*/false, SS, + /*TemplateKWLoc=*/SourceLocation(), /*FirstQualifierInScope=*/0, MemberLookup, /*TemplateArgs=*/0); @@ -2463,7 +2548,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, // Create the iteration variable for this array index. IdentifierInfo *IterationVarName = 0; { - llvm::SmallString<8> Str; + SmallString<8> Str; llvm::raw_svector_ostream OS(Str); OS << "__i" << IndexVariables.size(); IterationVarName = &SemaRef.Context.Idents.get(OS.str()); @@ -2477,9 +2562,12 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, // Create a reference to the iteration variable. ExprResult IterationVarRef - = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, VK_RValue, Loc); + = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc); assert(!IterationVarRef.isInvalid() && "Reference to invented variable cannot fail!"); + IterationVarRef = SemaRef.DefaultLvalueConversion(IterationVarRef.take()); + assert(!IterationVarRef.isInvalid() && + "Conversion of invented variable cannot fail!"); // Subscript the array with this iteration variable. CtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(CtorArg.take(), Loc, @@ -2597,7 +2685,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, } } - if (SemaRef.getLangOptions().ObjCAutoRefCount && + if (SemaRef.getLangOpts().ObjCAutoRefCount && FieldBaseElementType->isObjCRetainableType() && FieldBaseElementType.getObjCLifetime() != Qualifiers::OCL_None && FieldBaseElementType.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) { @@ -2635,6 +2723,19 @@ struct BaseAndFieldInfo { else IIK = IIK_Default; } + + bool isImplicitCopyOrMove() const { + switch (IIK) { + case IIK_Copy: + case IIK_Move: + return true; + + case IIK_Default: + return false; + } + + llvm_unreachable("Invalid ImplicitInitializerKind!"); + } }; } @@ -2651,6 +2752,22 @@ static bool isWithinAnonymousUnion(IndirectFieldDecl *F) { return false; } +/// \brief Determine whether the given type is an incomplete or zero-lenfgth +/// array type. +static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) { + if (T->isIncompleteArrayType()) + return true; + + while (const ConstantArrayType *ArrayT = Context.getAsConstantArrayType(T)) { + if (!ArrayT->getSize()) + return true; + + T = ArrayT->getElementType(); + } + + return false; +} + static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info, FieldDecl *Field, IndirectFieldDecl *Indirect = 0) { @@ -2664,7 +2781,7 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info, // C++0x [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]. - if (Field->hasInClassInitializer()) { + if (Field->hasInClassInitializer() && !Info.isImplicitCopyOrMove()) { CXXCtorInitializer *Init; if (Indirect) Init = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Indirect, @@ -2686,6 +2803,10 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info, (Indirect && isWithinAnonymousUnion(Indirect))) return false; + // Don't initialize incomplete or zero-length arrays. + if (isIncompleteOrZeroLengthArrayType(SemaRef.Context, Field->getType())) + return false; + // Don't try to build an implicit initializer if there were semantic // errors in any of the initializers (and therefore we might be // missing some that the user actually wrote). @@ -2714,7 +2835,7 @@ Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor, Constructor->setCtorInitializers(initializer); if (CXXDestructorDecl *Dtor = LookupDestructor(Constructor->getParent())) { - MarkDeclarationReferenced(Initializer->getSourceLocation(), Dtor); + MarkFunctionReferenced(Initializer->getSourceLocation(), Dtor); DiagnoseUseOfDecl(Dtor, Initializer->getSourceLocation()); } @@ -2824,13 +2945,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, // initialized. if (F->isUnnamedBitfield()) continue; - - if (F->getType()->isIncompleteArrayType()) { - assert(ClassDecl->hasFlexibleArrayMember() && - "Incomplete array type is not valid"); - continue; - } - + // If we're not generating the implicit copy/move constructor, then we'll // handle anonymous struct/union fields based on their individual // indirect fields. @@ -2997,12 +3112,12 @@ DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef, if (PrevInit->isAnyMemberInitializer()) D << 0 << PrevInit->getAnyMember()->getDeclName(); else - D << 1 << PrevInit->getBaseClassInfo()->getType(); + D << 1 << PrevInit->getTypeSourceInfo()->getType(); if (Init->isAnyMemberInitializer()) D << 0 << Init->getAnyMember()->getDeclName(); else - D << 1 << Init->getBaseClassInfo()->getType(); + D << 1 << Init->getTypeSourceInfo()->getType(); // Move back to the initializer's location in the ideal list. for (IdealIndex = 0; IdealIndex != NumIdealInits; ++IdealIndex) @@ -3053,11 +3168,9 @@ bool CheckRedundantUnionInit(Sema &S, RedundantUnionMap &Unions) { FieldDecl *Field = Init->getAnyMember(); RecordDecl *Parent = Field->getParent(); - if (!Parent->isAnonymousStructOrUnion()) - return false; - NamedDecl *Child = Field; - do { + + while (Parent->isAnonymousStructOrUnion() || Parent->isUnion()) { if (Parent->isUnion()) { UnionEntry &En = Unions[Parent]; if (En.first && En.first != Child) { @@ -3068,15 +3181,18 @@ bool CheckRedundantUnionInit(Sema &S, S.Diag(En.second->getSourceLocation(), diag::note_previous_initializer) << 0 << En.second->getSourceRange(); return true; - } else if (!En.first) { + } + if (!En.first) { En.first = Child; En.second = Init; } + if (!Parent->isAnonymousStructOrUnion()) + return false; } Child = Parent; Parent = cast<RecordDecl>(Parent->getDeclContext()); - } while (Parent->isAnonymousStructOrUnion()); + } return false; } @@ -3171,6 +3287,11 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, FieldDecl *Field = *I; if (Field->isInvalidDecl()) continue; + + // Don't destroy incomplete or zero-length arrays. + if (isIncompleteOrZeroLengthArrayType(Context, Field->getType())) + continue; + QualType FieldType = Context.getBaseElementType(Field->getType()); const RecordType* RT = FieldType->getAs<RecordType>(); @@ -3180,7 +3301,10 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); if (FieldClassDecl->isInvalidDecl()) continue; - if (FieldClassDecl->hasTrivialDestructor()) + if (FieldClassDecl->hasIrrelevantDestructor()) + continue; + // The destructor for an implicit anonymous union member is never invoked. + if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion()) continue; CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl); @@ -3190,7 +3314,8 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, << Field->getDeclName() << FieldType); - MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + DiagnoseUseOfDecl(Dtor, Location); } llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases; @@ -3209,20 +3334,21 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, // If our base class is invalid, we probably can't get its dtor anyway. if (BaseClassDecl->isInvalidDecl()) continue; - // Ignore trivial destructors. - if (BaseClassDecl->hasTrivialDestructor()) + if (BaseClassDecl->hasIrrelevantDestructor()) continue; CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); assert(Dtor && "No dtor found for BaseClassDecl!"); // FIXME: caret should be on the start of the class name - CheckDestructorAccess(Base->getSourceRange().getBegin(), Dtor, + CheckDestructorAccess(Base->getLocStart(), Dtor, PDiag(diag::err_access_dtor_base) << Base->getType() - << Base->getSourceRange()); + << Base->getSourceRange(), + Context.getTypeDeclType(ClassDecl)); - MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + DiagnoseUseOfDecl(Dtor, Location); } // Virtual bases. @@ -3230,7 +3356,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, E = ClassDecl->vbases_end(); VBase != E; ++VBase) { // Bases are always records in a well-formed non-dependent class. - const RecordType *RT = VBase->getType()->getAs<RecordType>(); + const RecordType *RT = VBase->getType()->castAs<RecordType>(); // Ignore direct virtual bases. if (DirectVirtualBases.count(RT)) @@ -3240,17 +3366,18 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, // If our base class is invalid, we probably can't get its dtor anyway. if (BaseClassDecl->isInvalidDecl()) continue; - // Ignore trivial destructors. - if (BaseClassDecl->hasTrivialDestructor()) + if (BaseClassDecl->hasIrrelevantDestructor()) continue; CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); assert(Dtor && "No dtor found for BaseClassDecl!"); CheckDestructorAccess(ClassDecl->getLocation(), Dtor, PDiag(diag::err_access_dtor_vbase) - << VBase->getType()); + << VBase->getType(), + Context.getTypeDeclType(ClassDecl)); - MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + DiagnoseUseOfDecl(Dtor, Location); } } @@ -3273,7 +3400,7 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, const PartialDiagnostic &PD) { - if (!getLangOptions().CPlusPlus) + if (!getLangOpts().CPlusPlus) return false; if (const ArrayType *AT = Context.getAsArrayType(T)) @@ -3538,7 +3665,8 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { // complain about any non-static data members of reference or const scalar // type, since they will never get initializers. if (!Record->isInvalidDecl() && !Record->isDependentType() && - !Record->isAggregate() && !Record->hasUserDeclaredConstructor()) { + !Record->isAggregate() && !Record->hasUserDeclaredConstructor() && + !Record->isLambda()) { bool Complained = false; for (RecordDecl::field_iterator F = Record->field_begin(), FEnd = Record->field_end(); @@ -3609,9 +3737,6 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { // const. [...] The class of which that function is a member shall be // a literal type. // - // It's fine to diagnose constructors here too: such constructors cannot - // produce a constant expression, so are ill-formed (no diagnostic required). - // // If the class has virtual bases, any constexpr members will already have // been diagnosed by the checks performed on the member declaration, so // suppress this (less useful) diagnostic. @@ -3620,16 +3745,14 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { for (CXXRecordDecl::method_iterator M = Record->method_begin(), MEnd = Record->method_end(); M != MEnd; ++M) { - if ((*M)->isConstexpr()) { + if (M->isConstexpr() && M->isInstance() && !isa<CXXConstructorDecl>(*M)) { switch (Record->getTemplateSpecializationKind()) { case TSK_ImplicitInstantiation: case TSK_ExplicitInstantiationDeclaration: case TSK_ExplicitInstantiationDefinition: // If a template instantiates to a non-literal type, but its members // instantiate to constexpr functions, the template is technically - // ill-formed, but we allow it for sanity. Such members are treated as - // non-constexpr. - (*M)->setConstexpr(false); + // ill-formed, but we allow it for sanity. continue; case TSK_Undeclared: @@ -3725,6 +3848,21 @@ void Sema::CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *CD) { *ExceptionType = Context.getFunctionType( Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); + // C++11 [dcl.fct.def.default]p2: + // An explicitly-defaulted function may be declared constexpr only if it + // would have been implicitly declared as constexpr, + // Do not apply this rule to templates, since core issue 1358 makes such + // functions always instantiate to constexpr functions. + if (CD->isConstexpr() && + CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { + if (!CD->getParent()->defaultedDefaultConstructorIsConstexpr()) { + Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr) + << CXXDefaultConstructor; + HadError = true; + } + } + // and may have an explicit exception-specification only if it is compatible + // with the exception-specification on the implicit declaration. if (CtorType->hasExceptionSpec()) { if (CheckEquivalentExceptionSpec( PDiag(diag::err_incorrect_defaulted_exception_spec) @@ -3734,11 +3872,24 @@ void Sema::CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *CD) { CtorType, CD->getLocation())) { HadError = true; } - } else if (First) { - // We set the declaration to have the computed exception spec here. - // We know there are no parameters. + } + + // If a function is explicitly defaulted on its first declaration, + if (First) { + // -- it is implicitly considered to be constexpr if the implicit + // definition would be, + CD->setConstexpr(CD->getParent()->defaultedDefaultConstructorIsConstexpr()); + + // -- it is implicitly considered to have the same + // exception-specification as if it had been implicitly declared + // + // FIXME: a compatible, but different, explicit exception specification + // will be silently overridden. We should issue a warning if this happens. EPI.ExtInfo = CtorType->getExtInfo(); - CD->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + CD->setTrivial(CD->getParent()->hasTrivialDefaultConstructor()); } if (HadError) { @@ -3792,6 +3943,21 @@ void Sema::CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *CD) { HadError = true; } + // C++11 [dcl.fct.def.default]p2: + // An explicitly-defaulted function may be declared constexpr only if it + // would have been implicitly declared as constexpr, + // Do not apply this rule to templates, since core issue 1358 makes such + // functions always instantiate to constexpr functions. + if (CD->isConstexpr() && + CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { + if (!CD->getParent()->defaultedCopyConstructorIsConstexpr()) { + Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr) + << CXXCopyConstructor; + HadError = true; + } + } + // and may have an explicit exception-specification only if it is compatible + // with the exception-specification on the implicit declaration. if (CtorType->hasExceptionSpec()) { if (CheckEquivalentExceptionSpec( PDiag(diag::err_incorrect_defaulted_exception_spec) @@ -3801,11 +3967,28 @@ void Sema::CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *CD) { CtorType, CD->getLocation())) { HadError = true; } - } else if (First) { - // We set the declaration to have the computed exception spec here. - // We duplicate the one parameter type. + } + + // If a function is explicitly defaulted on its first declaration, + if (First) { + // -- it is implicitly considered to be constexpr if the implicit + // definition would be, + CD->setConstexpr(CD->getParent()->defaultedCopyConstructorIsConstexpr()); + + // -- it is implicitly considered to have the same + // exception-specification as if it had been implicitly declared, and + // + // FIXME: a compatible, but different, explicit exception specification + // will be silently overridden. We should issue a warning if this happens. EPI.ExtInfo = CtorType->getExtInfo(); + + // -- [...] it shall have the same parameter type as if it had been + // implicitly declared. CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + CD->setTrivial(CD->getParent()->hasTrivialCopyConstructor()); } if (HadError) { @@ -3886,12 +4069,17 @@ void Sema::CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *MD) { OperType, MD->getLocation())) { HadError = true; } - } else if (First) { + } + if (First) { // We set the declaration to have the computed exception spec here. // We duplicate the one parameter type. EPI.RefQualifier = OperType->getRefQualifier(); EPI.ExtInfo = OperType->getExtInfo(); MD->setType(Context.getFunctionType(ReturnType, &ArgType, 1, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + MD->setTrivial(MD->getParent()->hasTrivialCopyAssignment()); } if (HadError) { @@ -3899,7 +4087,7 @@ void Sema::CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *MD) { return; } - if (ShouldDeleteCopyAssignmentOperator(MD)) { + if (ShouldDeleteSpecialMember(MD, CXXCopyAssignment)) { if (First) { MD->setDeletedAsWritten(); } else { @@ -3943,6 +4131,21 @@ void Sema::CheckExplicitlyDefaultedMoveConstructor(CXXConstructorDecl *CD) { HadError = true; } + // C++11 [dcl.fct.def.default]p2: + // An explicitly-defaulted function may be declared constexpr only if it + // would have been implicitly declared as constexpr, + // Do not apply this rule to templates, since core issue 1358 makes such + // functions always instantiate to constexpr functions. + if (CD->isConstexpr() && + CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { + if (!CD->getParent()->defaultedMoveConstructorIsConstexpr()) { + Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr) + << CXXMoveConstructor; + HadError = true; + } + } + // and may have an explicit exception-specification only if it is compatible + // with the exception-specification on the implicit declaration. if (CtorType->hasExceptionSpec()) { if (CheckEquivalentExceptionSpec( PDiag(diag::err_incorrect_defaulted_exception_spec) @@ -3952,11 +4155,28 @@ void Sema::CheckExplicitlyDefaultedMoveConstructor(CXXConstructorDecl *CD) { CtorType, CD->getLocation())) { HadError = true; } - } else if (First) { - // We set the declaration to have the computed exception spec here. - // We duplicate the one parameter type. + } + + // If a function is explicitly defaulted on its first declaration, + if (First) { + // -- it is implicitly considered to be constexpr if the implicit + // definition would be, + CD->setConstexpr(CD->getParent()->defaultedMoveConstructorIsConstexpr()); + + // -- it is implicitly considered to have the same + // exception-specification as if it had been implicitly declared, and + // + // FIXME: a compatible, but different, explicit exception specification + // will be silently overridden. We should issue a warning if this happens. EPI.ExtInfo = CtorType->getExtInfo(); + + // -- [...] it shall have the same parameter type as if it had been + // implicitly declared. CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + CD->setTrivial(CD->getParent()->hasTrivialMoveConstructor()); } if (HadError) { @@ -4035,12 +4255,17 @@ void Sema::CheckExplicitlyDefaultedMoveAssignment(CXXMethodDecl *MD) { OperType, MD->getLocation())) { HadError = true; } - } else if (First) { + } + if (First) { // We set the declaration to have the computed exception spec here. // We duplicate the one parameter type. EPI.RefQualifier = OperType->getRefQualifier(); EPI.ExtInfo = OperType->getExtInfo(); MD->setType(Context.getFunctionType(ReturnType, &ArgType, 1, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + MD->setTrivial(MD->getParent()->hasTrivialMoveAssignment()); } if (HadError) { @@ -4048,7 +4273,7 @@ void Sema::CheckExplicitlyDefaultedMoveAssignment(CXXMethodDecl *MD) { return; } - if (ShouldDeleteMoveAssignmentOperator(MD)) { + if (ShouldDeleteSpecialMember(MD, CXXMoveAssignment)) { if (First) { MD->setDeletedAsWritten(); } else { @@ -4082,14 +4307,19 @@ void Sema::CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *DD) { DD->setInvalidDecl(); return; } - } else if (First) { + } + if (First) { // We set the declaration to have the computed exception spec here. // There are no parameters. EPI.ExtInfo = DtorType->getExtInfo(); DD->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + DD->setTrivial(DD->getParent()->hasTrivialDestructor()); } - if (ShouldDeleteDestructor(DD)) { + if (ShouldDeleteSpecialMember(DD, CXXDestructor)) { if (First) { DD->setDeletedAsWritten(); } else { @@ -4100,652 +4330,412 @@ void Sema::CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *DD) { } } -/// This function implements the following C++0x paragraphs: -/// - [class.ctor]/5 -/// - [class.copy]/11 -bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM) { - assert(!MD->isInvalidDecl()); - CXXRecordDecl *RD = MD->getParent(); - assert(!RD->isDependentType() && "do deletion after instantiation"); - if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl()) - return false; - - bool IsUnion = RD->isUnion(); - bool IsConstructor = false; - bool IsAssignment = false; - bool IsMove = false; - - bool ConstArg = false; +namespace { +struct SpecialMemberDeletionInfo { + Sema &S; + CXXMethodDecl *MD; + Sema::CXXSpecialMember CSM; + bool Diagnose; + + // Properties of the special member, computed for convenience. + bool IsConstructor, IsAssignment, IsMove, ConstArg, VolatileArg; + SourceLocation Loc; + + bool AllFieldsAreConst; + + SpecialMemberDeletionInfo(Sema &S, CXXMethodDecl *MD, + 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()), + AllFieldsAreConst(true) { + switch (CSM) { + case Sema::CXXDefaultConstructor: + case Sema::CXXCopyConstructor: + IsConstructor = true; + break; + case Sema::CXXMoveConstructor: + IsConstructor = true; + IsMove = true; + break; + case Sema::CXXCopyAssignment: + IsAssignment = true; + break; + case Sema::CXXMoveAssignment: + IsAssignment = true; + IsMove = true; + break; + case Sema::CXXDestructor: + break; + case Sema::CXXInvalid: + llvm_unreachable("invalid special member kind"); + } - switch (CSM) { - case CXXDefaultConstructor: - IsConstructor = true; - break; - case CXXCopyConstructor: - IsConstructor = true; - ConstArg = MD->getParamDecl(0)->getType().isConstQualified(); - break; - case CXXMoveConstructor: - IsConstructor = true; - IsMove = true; - break; - default: - llvm_unreachable("function only currently implemented for default ctors"); + if (MD->getNumParams()) { + ConstArg = MD->getParamDecl(0)->getType().isConstQualified(); + VolatileArg = MD->getParamDecl(0)->getType().isVolatileQualified(); + } } - SourceLocation Loc = MD->getLocation(); - - // Do access control from the special member function - ContextRAII MethodContext(*this, MD); - - bool AllConst = true; + bool inUnion() const { return MD->getParent()->isUnion(); } - // We do this because we should never actually use an anonymous - // union's constructor. - if (IsUnion && RD->isAnonymousStructOrUnion()) - return false; + /// Look up the corresponding special member in the given class. + Sema::SpecialMemberOverloadResult *lookupIn(CXXRecordDecl *Class) { + unsigned TQ = MD->getTypeQualifiers(); + return S.LookupSpecialMember(Class, CSM, ConstArg, VolatileArg, + MD->getRefQualifier() == RQ_RValue, + TQ & Qualifiers::Const, + TQ & Qualifiers::Volatile); + } - // FIXME: We should put some diagnostic logic right into this function. + typedef llvm::PointerUnion<CXXBaseSpecifier*, FieldDecl*> Subobject; - for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), - BE = RD->bases_end(); - BI != BE; ++BI) { - // We'll handle this one later - if (BI->isVirtual()) - continue; + bool shouldDeleteForBase(CXXBaseSpecifier *Base); + bool shouldDeleteForField(FieldDecl *FD); + bool shouldDeleteForAllConstMembers(); - CXXRecordDecl *BaseDecl = BI->getType()->getAsCXXRecordDecl(); - assert(BaseDecl && "base isn't a CXXRecordDecl"); + bool shouldDeleteForClassSubobject(CXXRecordDecl *Class, Subobject Subobj); + bool shouldDeleteForSubobjectCall(Subobject Subobj, + Sema::SpecialMemberOverloadResult *SMOR, + bool IsDtorCallInCtor); - // Unless we have an assignment operator, the base's destructor must - // be accessible and not deleted. - if (!IsAssignment) { - CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); - if (BaseDtor->isDeleted()) - return true; - if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != - AR_accessible) - return true; - } + bool isAccessible(Subobject Subobj, CXXMethodDecl *D); +}; +} - // Finding the corresponding member in the base should lead to a - // unique, accessible, non-deleted function. If we are doing - // a destructor, we have already checked this case. - if (CSM != CXXDestructor) { - SpecialMemberOverloadResult *SMOR = - LookupSpecialMember(BaseDecl, CSM, ConstArg, false, false, false, - false); - if (!SMOR->hasSuccess()) - return true; - CXXMethodDecl *BaseMember = SMOR->getMethod(); - if (IsConstructor) { - CXXConstructorDecl *BaseCtor = cast<CXXConstructorDecl>(BaseMember); - if (CheckConstructorAccess(Loc, BaseCtor, BaseCtor->getAccess(), - PDiag()) != AR_accessible) - return true; +/// Is the given special member inaccessible when used on the given +/// sub-object. +bool SpecialMemberDeletionInfo::isAccessible(Subobject Subobj, + CXXMethodDecl *target) { + /// If we're operating on a base class, the object type is the + /// type of this special member. + QualType objectTy; + AccessSpecifier access = target->getAccess();; + if (CXXBaseSpecifier *base = Subobj.dyn_cast<CXXBaseSpecifier*>()) { + objectTy = S.Context.getTypeDeclType(MD->getParent()); + access = CXXRecordDecl::MergeAccess(base->getAccessSpecifier(), access); - // For a move operation, the corresponding operation must actually - // be a move operation (and not a copy selected by overload - // resolution) unless we are working on a trivially copyable class. - if (IsMove && !BaseCtor->isMoveConstructor() && - !BaseDecl->isTriviallyCopyable()) - return true; - } - } + // If we're operating on a field, the object type is the type of the field. + } else { + objectTy = S.Context.getTypeDeclType(target->getParent()); } - for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), - BE = RD->vbases_end(); - BI != BE; ++BI) { - CXXRecordDecl *BaseDecl = BI->getType()->getAsCXXRecordDecl(); - assert(BaseDecl && "base isn't a CXXRecordDecl"); - - // Unless we have an assignment operator, the base's destructor must - // be accessible and not deleted. - if (!IsAssignment) { - CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); - if (BaseDtor->isDeleted()) - return true; - if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != - AR_accessible) - return true; - } + return S.isSpecialMemberAccessibleForDeletion(target, access, objectTy); +} - // Finding the corresponding member in the base should lead to a - // unique, accessible, non-deleted function. - if (CSM != CXXDestructor) { - SpecialMemberOverloadResult *SMOR = - LookupSpecialMember(BaseDecl, CSM, ConstArg, false, false, false, - false); - if (!SMOR->hasSuccess()) - return true; - CXXMethodDecl *BaseMember = SMOR->getMethod(); - if (IsConstructor) { - CXXConstructorDecl *BaseCtor = cast<CXXConstructorDecl>(BaseMember); - if (CheckConstructorAccess(Loc, BaseCtor, BaseCtor->getAccess(), - PDiag()) != AR_accessible) - return true; +/// Check whether we should delete a special member due to the implicit +/// definition containing a call to a special member of a subobject. +bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall( + Subobject Subobj, Sema::SpecialMemberOverloadResult *SMOR, + bool IsDtorCallInCtor) { + CXXMethodDecl *Decl = SMOR->getMethod(); + FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>(); - // For a move operation, the corresponding operation must actually - // be a move operation (and not a copy selected by overload - // resolution) unless we are working on a trivially copyable class. - if (IsMove && !BaseCtor->isMoveConstructor() && - !BaseDecl->isTriviallyCopyable()) - return true; - } - } - } + int DiagKind = -1; - for (CXXRecordDecl::field_iterator FI = RD->field_begin(), - FE = RD->field_end(); - FI != FE; ++FI) { - if (FI->isInvalidDecl() || FI->isUnnamedBitfield()) - continue; - - QualType FieldType = Context.getBaseElementType(FI->getType()); - CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); + if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) + DiagKind = !Decl ? 0 : 1; + else if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::Ambiguous) + DiagKind = 2; + else if (!isAccessible(Subobj, Decl)) + DiagKind = 3; + else if (!IsDtorCallInCtor && Field && Field->getParent()->isUnion() && + !Decl->isTrivial()) { + // A member of a union must have a trivial corresponding special member. + // As a weird special case, a destructor call from a union's constructor + // must be accessible and non-deleted, but need not be trivial. Such a + // destructor is never actually called, but is semantically checked as + // if it were. + DiagKind = 4; + } - // For a default constructor, all references must be initialized in-class - // and, if a union, it must have a non-const member. - if (CSM == CXXDefaultConstructor) { - if (FieldType->isReferenceType() && !FI->hasInClassInitializer()) - return true; + if (DiagKind == -1) + return false; - if (IsUnion && !FieldType.isConstQualified()) - AllConst = false; - // For a copy constructor, data members must not be of rvalue reference - // type. - } else if (CSM == CXXCopyConstructor) { - if (FieldType->isRValueReferenceType()) - return true; + if (Diagnose) { + if (Field) { + S.Diag(Field->getLocation(), + diag::note_deleted_special_member_class_subobject) + << CSM << MD->getParent() << /*IsField*/true + << Field << DiagKind << IsDtorCallInCtor; + } else { + CXXBaseSpecifier *Base = Subobj.get<CXXBaseSpecifier*>(); + S.Diag(Base->getLocStart(), + diag::note_deleted_special_member_class_subobject) + << CSM << MD->getParent() << /*IsField*/false + << Base->getType() << DiagKind << IsDtorCallInCtor; } - if (FieldRecord) { - // For a default constructor, a const member must have a user-provided - // default constructor or else be explicitly initialized. - if (CSM == CXXDefaultConstructor && FieldType.isConstQualified() && - !FI->hasInClassInitializer() && - !FieldRecord->hasUserProvidedDefaultConstructor()) - return true; - - // Some additional restrictions exist on the variant members. - if (!IsUnion && FieldRecord->isUnion() && - FieldRecord->isAnonymousStructOrUnion()) { - // We're okay to reuse AllConst here since we only care about the - // value otherwise if we're in a union. - AllConst = true; - - for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), - UE = FieldRecord->field_end(); - UI != UE; ++UI) { - QualType UnionFieldType = Context.getBaseElementType(UI->getType()); - CXXRecordDecl *UnionFieldRecord = - UnionFieldType->getAsCXXRecordDecl(); - - if (!UnionFieldType.isConstQualified()) - AllConst = false; - - if (UnionFieldRecord) { - // FIXME: Checking for accessibility and validity of this - // destructor is technically going beyond the - // standard, but this is believed to be a defect. - if (!IsAssignment) { - CXXDestructorDecl *FieldDtor = LookupDestructor(UnionFieldRecord); - if (FieldDtor->isDeleted()) - return true; - if (CheckDestructorAccess(Loc, FieldDtor, PDiag()) != - AR_accessible) - return true; - if (!FieldDtor->isTrivial()) - return true; - } - - if (CSM != CXXDestructor) { - SpecialMemberOverloadResult *SMOR = - LookupSpecialMember(UnionFieldRecord, CSM, ConstArg, false, - false, false, false); - // FIXME: Checking for accessibility and validity of this - // corresponding member is technically going beyond the - // standard, but this is believed to be a defect. - if (!SMOR->hasSuccess()) - return true; - - CXXMethodDecl *FieldMember = SMOR->getMethod(); - // A member of a union must have a trivial corresponding - // constructor. - if (!FieldMember->isTrivial()) - return true; - - if (IsConstructor) { - CXXConstructorDecl *FieldCtor = cast<CXXConstructorDecl>(FieldMember); - if (CheckConstructorAccess(Loc, FieldCtor, FieldCtor->getAccess(), - PDiag()) != AR_accessible) - return true; - } - } - } - } - - // At least one member in each anonymous union must be non-const - if (CSM == CXXDefaultConstructor && AllConst) - return true; - - // Don't try to initialize the anonymous union - // This is technically non-conformant, but sanity demands it. - continue; - } - - // Unless we're doing assignment, the field's destructor must be - // accessible and not deleted. - if (!IsAssignment) { - CXXDestructorDecl *FieldDtor = LookupDestructor(FieldRecord); - if (FieldDtor->isDeleted()) - return true; - if (CheckDestructorAccess(Loc, FieldDtor, PDiag()) != - AR_accessible) - return true; - } - - // Check that the corresponding member of the field is accessible, - // unique, and non-deleted. We don't do this if it has an explicit - // initialization when default-constructing. - if (CSM != CXXDestructor && - (CSM != CXXDefaultConstructor || !FI->hasInClassInitializer())) { - SpecialMemberOverloadResult *SMOR = - LookupSpecialMember(FieldRecord, CSM, ConstArg, false, false, false, - false); - if (!SMOR->hasSuccess()) - return true; + if (DiagKind == 1) + S.NoteDeletedFunction(Decl); + // FIXME: Explain inaccessibility if DiagKind == 3. + } - CXXMethodDecl *FieldMember = SMOR->getMethod(); - if (IsConstructor) { - CXXConstructorDecl *FieldCtor = cast<CXXConstructorDecl>(FieldMember); - if (CheckConstructorAccess(Loc, FieldCtor, FieldCtor->getAccess(), - PDiag()) != AR_accessible) - return true; + return true; +} - // For a move operation, the corresponding operation must actually - // be a move operation (and not a copy selected by overload - // resolution) unless we are working on a trivially copyable class. - if (IsMove && !FieldCtor->isMoveConstructor() && - !FieldRecord->isTriviallyCopyable()) - return true; - } +/// Check whether we should delete a special member function due to having a +/// direct or virtual base class or static data member of class type M. +bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject( + CXXRecordDecl *Class, Subobject Subobj) { + FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>(); + + // C++11 [class.ctor]p5: + // -- any direct or virtual base class, or non-static data member with no + // brace-or-equal-initializer, has class type M (or array thereof) and + // either M has no default constructor or overload resolution as applied + // to M's default constructor results in an ambiguity or in a function + // that is deleted or inaccessible + // C++11 [class.copy]p11, C++11 [class.copy]p23: + // -- a direct or virtual base class B that cannot be copied/moved because + // overload resolution, as applied to B's corresponding special member, + // results in an ambiguity or a function that is deleted or inaccessible + // from the defaulted special member + // C++11 [class.dtor]p5: + // -- any direct or virtual base class [...] has a type with a destructor + // that is deleted or inaccessible + if (!(CSM == Sema::CXXDefaultConstructor && + Field && Field->hasInClassInitializer()) && + shouldDeleteForSubobjectCall(Subobj, lookupIn(Class), false)) + return true; - // We need the corresponding member of a union to be trivial so that - // we can safely copy them all simultaneously. - // FIXME: Note that performing the check here (where we rely on the lack - // of an in-class initializer) is technically ill-formed. However, this - // seems most obviously to be a bug in the standard. - if (IsUnion && !FieldMember->isTrivial()) - return true; - } - } else if (CSM == CXXDefaultConstructor && !IsUnion && - FieldType.isConstQualified() && !FI->hasInClassInitializer()) { - // We can't initialize a const member of non-class type to any value. + // C++11 [class.ctor]p5, C++11 [class.copy]p11: + // -- any direct or virtual base class or non-static data member has a + // type with a destructor that is deleted or inaccessible + if (IsConstructor) { + Sema::SpecialMemberOverloadResult *SMOR = + S.LookupSpecialMember(Class, Sema::CXXDestructor, + false, false, false, false, false); + if (shouldDeleteForSubobjectCall(Subobj, SMOR, true)) return true; - } } - // We can't have all const members in a union when default-constructing, - // or else they're all nonsensical garbage values that can't be changed. - if (CSM == CXXDefaultConstructor && IsUnion && AllConst) - return true; - return false; } -bool Sema::ShouldDeleteCopyAssignmentOperator(CXXMethodDecl *MD) { - CXXRecordDecl *RD = MD->getParent(); - assert(!RD->isDependentType() && "do deletion after instantiation"); - if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl()) - return false; - - SourceLocation Loc = MD->getLocation(); - - // Do access control from the constructor - ContextRAII MethodContext(*this, MD); - - bool Union = RD->isUnion(); - - unsigned ArgQuals = - MD->getParamDecl(0)->getType()->getPointeeType().isConstQualified() ? - Qualifiers::Const : 0; - - // We do this because we should never actually use an anonymous - // union's constructor. - if (Union && RD->isAnonymousStructOrUnion()) - return false; - - // FIXME: We should put some diagnostic logic right into this function. - - // C++0x [class.copy]/20 - // A defaulted [copy] assignment operator for class X is defined as deleted - // if X has: +/// Check whether we should delete a special member function due to the class +/// having a particular direct or virtual base class. +bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) { + CXXRecordDecl *BaseClass = Base->getType()->getAsCXXRecordDecl(); + return shouldDeleteForClassSubobject(BaseClass, Base); +} - for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), - BE = RD->bases_end(); - BI != BE; ++BI) { - // We'll handle this one later - if (BI->isVirtual()) - continue; +/// Check whether we should delete a special member function due to the class +/// having a particular non-static data member. +bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { + QualType FieldType = S.Context.getBaseElementType(FD->getType()); + CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); - QualType BaseType = BI->getType(); - CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl(); - assert(BaseDecl && "base isn't a CXXRecordDecl"); - - // -- a [direct base class] B that cannot be [copied] because overload - // resolution, as applied to B's [copy] assignment operator, results in - // an ambiguity or a function that is deleted or inaccessible from the - // assignment operator - CXXMethodDecl *CopyOper = LookupCopyingAssignment(BaseDecl, ArgQuals, false, - 0); - if (!CopyOper || CopyOper->isDeleted()) + if (CSM == Sema::CXXDefaultConstructor) { + // For a default constructor, all references must be initialized in-class + // and, if a union, it must have a non-const member. + if (FieldType->isReferenceType() && !FD->hasInClassInitializer()) { + if (Diagnose) + S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field) + << MD->getParent() << FD << FieldType << /*Reference*/0; return true; - if (CheckDirectMemberAccess(Loc, CopyOper, PDiag()) != AR_accessible) + } + // C++11 [class.ctor]p5: any non-variant non-static data member of + // const-qualified type (or array thereof) with no + // brace-or-equal-initializer does not have a user-provided default + // constructor. + if (!inUnion() && FieldType.isConstQualified() && + !FD->hasInClassInitializer() && + (!FieldRecord || !FieldRecord->hasUserProvidedDefaultConstructor())) { + if (Diagnose) + S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field) + << MD->getParent() << FD << FieldType << /*Const*/1; return true; - } + } - for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), - BE = RD->vbases_end(); - BI != BE; ++BI) { - QualType BaseType = BI->getType(); - CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl(); - assert(BaseDecl && "base isn't a CXXRecordDecl"); - - // -- a [virtual base class] B that cannot be [copied] because overload - // resolution, as applied to B's [copy] assignment operator, results in - // an ambiguity or a function that is deleted or inaccessible from the - // assignment operator - CXXMethodDecl *CopyOper = LookupCopyingAssignment(BaseDecl, ArgQuals, false, - 0); - if (!CopyOper || CopyOper->isDeleted()) + if (inUnion() && !FieldType.isConstQualified()) + AllFieldsAreConst = false; + } else if (CSM == Sema::CXXCopyConstructor) { + // For a copy constructor, data members must not be of rvalue reference + // type. + if (FieldType->isRValueReferenceType()) { + if (Diagnose) + S.Diag(FD->getLocation(), diag::note_deleted_copy_ctor_rvalue_reference) + << MD->getParent() << FD << FieldType; return true; - if (CheckDirectMemberAccess(Loc, CopyOper, PDiag()) != AR_accessible) + } + } else if (IsAssignment) { + // For an assignment operator, data members must not be of reference type. + if (FieldType->isReferenceType()) { + if (Diagnose) + S.Diag(FD->getLocation(), diag::note_deleted_assign_field) + << IsMove << MD->getParent() << FD << FieldType << /*Reference*/0; + return true; + } + if (!FieldRecord && FieldType.isConstQualified()) { + // C++11 [class.copy]p23: + // -- a non-static data member of const non-class type (or array thereof) + if (Diagnose) + S.Diag(FD->getLocation(), diag::note_deleted_assign_field) + << IsMove << MD->getParent() << FD << FieldType << /*Const*/1; return true; + } } - for (CXXRecordDecl::field_iterator FI = RD->field_begin(), - FE = RD->field_end(); - FI != FE; ++FI) { - if (FI->isUnnamedBitfield()) - continue; - - QualType FieldType = Context.getBaseElementType(FI->getType()); - - // -- a non-static data member of reference type - if (FieldType->isReferenceType()) - return true; + if (FieldRecord) { + // Some additional restrictions exist on the variant members. + if (!inUnion() && FieldRecord->isUnion() && + FieldRecord->isAnonymousStructOrUnion()) { + bool AllVariantFieldsAreConst = true; - // -- a non-static data member of const non-class type (or array thereof) - if (FieldType.isConstQualified() && !FieldType->isRecordType()) - return true; - - CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); - - if (FieldRecord) { - // This is an anonymous union - if (FieldRecord->isUnion() && FieldRecord->isAnonymousStructOrUnion()) { - // Anonymous unions inside unions do not variant members create - if (!Union) { - for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), - UE = FieldRecord->field_end(); - UI != UE; ++UI) { - QualType UnionFieldType = Context.getBaseElementType(UI->getType()); - CXXRecordDecl *UnionFieldRecord = - UnionFieldType->getAsCXXRecordDecl(); - - // -- a variant member with a non-trivial [copy] assignment operator - // and X is a union-like class - if (UnionFieldRecord && - !UnionFieldRecord->hasTrivialCopyAssignment()) - return true; - } - } + // FIXME: Handle anonymous unions declared within anonymous unions. + for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), + UE = FieldRecord->field_end(); + UI != UE; ++UI) { + QualType UnionFieldType = S.Context.getBaseElementType(UI->getType()); - // Don't try to initalize an anonymous union - continue; - // -- a variant member with a non-trivial [copy] assignment operator - // and X is a union-like class - } else if (Union && !FieldRecord->hasTrivialCopyAssignment()) { + if (!UnionFieldType.isConstQualified()) + AllVariantFieldsAreConst = false; + + CXXRecordDecl *UnionFieldRecord = UnionFieldType->getAsCXXRecordDecl(); + if (UnionFieldRecord && + shouldDeleteForClassSubobject(UnionFieldRecord, *UI)) return true; } - CXXMethodDecl *CopyOper = LookupCopyingAssignment(FieldRecord, ArgQuals, - false, 0); - if (!CopyOper || CopyOper->isDeleted()) - return true; - if (CheckDirectMemberAccess(Loc, CopyOper, PDiag()) != AR_accessible) + // At least one member in each anonymous union must be non-const + if (CSM == Sema::CXXDefaultConstructor && AllVariantFieldsAreConst && + FieldRecord->field_begin() != FieldRecord->field_end()) { + if (Diagnose) + S.Diag(FieldRecord->getLocation(), + diag::note_deleted_default_ctor_all_const) + << MD->getParent() << /*anonymous union*/1; return true; + } + + // Don't check the implicit member of the anonymous union type. + // This is technically non-conformant, but sanity demands it. + return false; } + + if (shouldDeleteForClassSubobject(FieldRecord, FD)) + return true; } return false; } -bool Sema::ShouldDeleteMoveAssignmentOperator(CXXMethodDecl *MD) { +/// C++11 [class.ctor] p5: +/// A defaulted default constructor for a class X is defined as deleted if +/// X is a union and all of its variant members are of const-qualified type. +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())) { + if (Diagnose) + S.Diag(MD->getParent()->getLocation(), + diag::note_deleted_default_ctor_all_const) + << MD->getParent() << /*not anonymous union*/0; + return true; + } + return false; +} + +/// Determine whether a defaulted special member function should be defined as +/// deleted, as specified in C++11 [class.ctor]p5, C++11 [class.copy]p11, +/// C++11 [class.copy]p23, and C++11 [class.dtor]p5. +bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, + bool Diagnose) { + assert(!MD->isInvalidDecl()); CXXRecordDecl *RD = MD->getParent(); assert(!RD->isDependentType() && "do deletion after instantiation"); if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl()) return false; - SourceLocation Loc = MD->getLocation(); - - // Do access control from the constructor - ContextRAII MethodContext(*this, MD); - - bool Union = RD->isUnion(); - - // We do this because we should never actually use an anonymous - // union's constructor. - if (Union && RD->isAnonymousStructOrUnion()) - return false; - - // C++0x [class.copy]/20 - // A defaulted [move] assignment operator for class X is defined as deleted - // if X has: - - // -- for the move constructor, [...] any direct or indirect virtual base - // class. - if (RD->getNumVBases() != 0) + // C++11 [expr.lambda.prim]p19: + // The closure type associated with a lambda-expression has a + // deleted (8.4.3) default constructor and a deleted copy + // assignment operator. + if (RD->isLambda() && + (CSM == CXXDefaultConstructor || CSM == CXXCopyAssignment)) { + if (Diagnose) + Diag(RD->getLocation(), diag::note_lambda_decl); return true; + } - for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), - BE = RD->bases_end(); - BI != BE; ++BI) { - - QualType BaseType = BI->getType(); - CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl(); - assert(BaseDecl && "base isn't a CXXRecordDecl"); - - // -- a [direct base class] B that cannot be [moved] because overload - // resolution, as applied to B's [move] assignment operator, results in - // an ambiguity or a function that is deleted or inaccessible from the - // assignment operator - CXXMethodDecl *MoveOper = LookupMovingAssignment(BaseDecl, false, 0); - if (!MoveOper || MoveOper->isDeleted()) - return true; - if (CheckDirectMemberAccess(Loc, MoveOper, PDiag()) != AR_accessible) - return true; + // For an anonymous struct or union, the copy and assignment special members + // will never be used, so skip the check. For an anonymous union declared at + // namespace scope, the constructor and destructor are used. + if (CSM != CXXDefaultConstructor && CSM != CXXDestructor && + RD->isAnonymousStructOrUnion()) + return false; - // -- for the move assignment operator, a [direct base class] with a type - // that does not have a move assignment operator and is not trivially - // copyable. - if (!MoveOper->isMoveAssignmentOperator() && - !BaseDecl->isTriviallyCopyable()) + // C++11 [class.copy]p7, p18: + // If the class definition declares a move constructor or move assignment + // operator, an implicitly declared copy constructor or copy assignment + // operator is defined as deleted. + if (MD->isImplicit() && + (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)) { + CXXMethodDecl *UserDeclaredMove = 0; + + // 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)) { + if (!Diagnose) return true; + UserDeclaredMove = RD->getMoveConstructor(); + assert(UserDeclaredMove); + } else if (RD->hasUserDeclaredMoveAssignment() && + (!getLangOpts().MicrosoftMode || CSM == CXXCopyAssignment)) { + if (!Diagnose) return true; + UserDeclaredMove = RD->getMoveAssignmentOperator(); + assert(UserDeclaredMove); + } + + if (UserDeclaredMove) { + Diag(UserDeclaredMove->getLocation(), + diag::note_deleted_copy_user_declared_move) + << (CSM == CXXCopyAssignment) << RD + << UserDeclaredMove->isMoveAssignmentOperator(); return true; + } } - for (CXXRecordDecl::field_iterator FI = RD->field_begin(), - FE = RD->field_end(); - FI != FE; ++FI) { - if (FI->isUnnamedBitfield()) - continue; - - QualType FieldType = Context.getBaseElementType(FI->getType()); - - // -- a non-static data member of reference type - if (FieldType->isReferenceType()) - return true; + // Do access control from the special member function + ContextRAII MethodContext(*this, MD); - // -- a non-static data member of const non-class type (or array thereof) - if (FieldType.isConstQualified() && !FieldType->isRecordType()) + // C++11 [class.dtor]p5: + // -- 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; + DeclarationName Name = + Context.DeclarationNames.getCXXOperatorName(OO_Delete); + if (FindDeallocationFunction(MD->getLocation(), MD->getParent(), Name, + OperatorDelete, false)) { + if (Diagnose) + Diag(RD->getLocation(), diag::note_deleted_dtor_no_operator_delete); return true; - - CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); - - if (FieldRecord) { - // This is an anonymous union - if (FieldRecord->isUnion() && FieldRecord->isAnonymousStructOrUnion()) { - // Anonymous unions inside unions do not variant members create - if (!Union) { - for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), - UE = FieldRecord->field_end(); - UI != UE; ++UI) { - QualType UnionFieldType = Context.getBaseElementType(UI->getType()); - CXXRecordDecl *UnionFieldRecord = - UnionFieldType->getAsCXXRecordDecl(); - - // -- a variant member with a non-trivial [move] assignment operator - // and X is a union-like class - if (UnionFieldRecord && - !UnionFieldRecord->hasTrivialMoveAssignment()) - return true; - } - } - - // Don't try to initalize an anonymous union - continue; - // -- a variant member with a non-trivial [move] assignment operator - // and X is a union-like class - } else if (Union && !FieldRecord->hasTrivialMoveAssignment()) { - return true; - } - - CXXMethodDecl *MoveOper = LookupMovingAssignment(FieldRecord, false, 0); - if (!MoveOper || MoveOper->isDeleted()) - return true; - if (CheckDirectMemberAccess(Loc, MoveOper, PDiag()) != AR_accessible) - return true; - - // -- for the move assignment operator, a [non-static data member] with a - // type that does not have a move assignment operator and is not - // trivially copyable. - if (!MoveOper->isMoveAssignmentOperator() && - !FieldRecord->isTriviallyCopyable()) - return true; } } - return false; -} - -bool Sema::ShouldDeleteDestructor(CXXDestructorDecl *DD) { - CXXRecordDecl *RD = DD->getParent(); - assert(!RD->isDependentType() && "do deletion after instantiation"); - if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl()) - return false; - - SourceLocation Loc = DD->getLocation(); - - // Do access control from the destructor - ContextRAII CtorContext(*this, DD); - - bool Union = RD->isUnion(); - - // We do this because we should never actually use an anonymous - // union's destructor. - if (Union && RD->isAnonymousStructOrUnion()) - return false; + SpecialMemberDeletionInfo SMI(*this, MD, CSM, Diagnose); - // C++0x [class.dtor]p5 - // A defaulted destructor for a class X is defined as deleted if: for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), - BE = RD->bases_end(); - BI != BE; ++BI) { - // We'll handle this one later - if (BI->isVirtual()) - continue; - - CXXRecordDecl *BaseDecl = BI->getType()->getAsCXXRecordDecl(); - CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); - assert(BaseDtor && "base has no destructor"); - - // -- any direct or virtual base class has a deleted destructor or - // a destructor that is inaccessible from the defaulted destructor - if (BaseDtor->isDeleted()) + BE = RD->bases_end(); BI != BE; ++BI) + if (!BI->isVirtual() && + SMI.shouldDeleteForBase(BI)) return true; - if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != - AR_accessible) - return true; - } for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), - BE = RD->vbases_end(); - BI != BE; ++BI) { - CXXRecordDecl *BaseDecl = BI->getType()->getAsCXXRecordDecl(); - CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); - assert(BaseDtor && "base has no destructor"); - - // -- any direct or virtual base class has a deleted destructor or - // a destructor that is inaccessible from the defaulted destructor - if (BaseDtor->isDeleted()) - return true; - if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != - AR_accessible) + BE = RD->vbases_end(); BI != BE; ++BI) + if (SMI.shouldDeleteForBase(BI)) return true; - } for (CXXRecordDecl::field_iterator FI = RD->field_begin(), - FE = RD->field_end(); - FI != FE; ++FI) { - QualType FieldType = Context.getBaseElementType(FI->getType()); - CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); - if (FieldRecord) { - if (FieldRecord->isUnion() && FieldRecord->isAnonymousStructOrUnion()) { - for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), - UE = FieldRecord->field_end(); - UI != UE; ++UI) { - QualType UnionFieldType = Context.getBaseElementType(FI->getType()); - CXXRecordDecl *UnionFieldRecord = - UnionFieldType->getAsCXXRecordDecl(); - - // -- X is a union-like class that has a variant member with a non- - // trivial destructor. - if (UnionFieldRecord && !UnionFieldRecord->hasTrivialDestructor()) - return true; - } - // Technically we are supposed to do this next check unconditionally. - // But that makes absolutely no sense. - } else { - CXXDestructorDecl *FieldDtor = LookupDestructor(FieldRecord); - - // -- any of the non-static data members has class type M (or array - // thereof) and M has a deleted destructor or a destructor that is - // inaccessible from the defaulted destructor - if (FieldDtor->isDeleted()) - return true; - if (CheckDestructorAccess(Loc, FieldDtor, PDiag()) != - AR_accessible) - return true; - - // -- X is a union-like class that has a variant member with a non- - // trivial destructor. - if (Union && !FieldDtor->isTrivial()) - return true; - } - } - } - - if (DD->isVirtual()) { - FunctionDecl *OperatorDelete = 0; - DeclarationName Name = - Context.DeclarationNames.getCXXOperatorName(OO_Delete); - if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete, - false)) + FE = RD->field_end(); FI != FE; ++FI) + if (!FI->isInvalidDecl() && !FI->isUnnamedBitfield() && + SMI.shouldDeleteForField(*FI)) return true; - } + if (SMI.shouldDeleteForAllConstMembers()) + return true; return false; } @@ -4876,6 +4866,9 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { if (!ClassDecl->hasUserDeclaredCopyConstructor()) ++ASTContext::NumImplicitCopyConstructors; + if (getLangOpts().CPlusPlus0x && ClassDecl->needsImplicitMoveConstructor()) + ++ASTContext::NumImplicitMoveConstructors; + if (!ClassDecl->hasUserDeclaredCopyAssignment()) { ++ASTContext::NumImplicitCopyAssignmentOperators; @@ -4887,6 +4880,14 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { DeclareImplicitCopyAssignment(ClassDecl); } + if (getLangOpts().CPlusPlus0x && ClassDecl->needsImplicitMoveAssignment()) { + ++ASTContext::NumImplicitMoveAssignmentOperators; + + // Likewise for the move assignment operator. + if (ClassDecl->isDynamicClass()) + DeclareImplicitMoveAssignment(ClassDecl); + } + if (!ClassDecl->hasUserDeclaredDestructor()) { ++ASTContext::NumImplicitDestructors; @@ -5139,7 +5140,7 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete)) return true; - MarkDeclarationReferenced(Loc, OperatorDelete); + MarkFunctionReferenced(Loc, OperatorDelete); Destructor->setOperatorDelete(OperatorDelete); } @@ -5342,9 +5343,11 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, R = Context.getFunctionType(ConvType, 0, 0, Proto->getExtProtoInfo()); // C++0x explicit conversion operators. - if (D.getDeclSpec().isExplicitSpecified() && !getLangOptions().CPlusPlus0x) + if (D.getDeclSpec().isExplicitSpecified()) Diag(D.getDeclSpec().getExplicitSpecLoc(), - diag::warn_explicit_conversion_functions) + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_explicit_conversion_functions : + diag::ext_explicit_conversion_functions) << SourceRange(D.getDeclSpec().getExplicitSpecLoc()); } @@ -5413,17 +5416,13 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; // For anonymous namespace, take the location of the left brace. SourceLocation Loc = II ? IdentLoc : LBrace; - NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, - StartLoc, Loc, II); - Namespc->setInline(InlineLoc.isValid()); - + bool IsInline = InlineLoc.isValid(); + bool IsInvalid = false; + bool IsStd = false; + bool AddToKnown = false; Scope *DeclRegionScope = NamespcScope->getParent(); - ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList); - - if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>()) - PushNamespaceVisibilityAttr(Attr); - + NamespaceDecl *PrevNS = 0; if (II) { // C++ [namespace.def]p2: // The identifier in an original-namespace-definition shall not @@ -5437,11 +5436,11 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // look through using directives, just look for any ordinary names. const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Member | - Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag | - Decl::IDNS_Namespace; + Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag | + Decl::IDNS_Namespace; NamedDecl *PrevDecl = 0; for (DeclContext::lookup_result R - = CurContext->getRedeclContext()->lookup(II); + = CurContext->getRedeclContext()->lookup(II); R.first != R.second; ++R.first) { if ((*R.first)->getIdentifierNamespace() & IDNS) { PrevDecl = *R.first; @@ -5449,100 +5448,91 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, } } - if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) { + PrevNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl); + + if (PrevNS) { // This is an extended namespace definition. - if (Namespc->isInline() != OrigNS->isInline()) { + if (IsInline != PrevNS->isInline()) { // inline-ness must match - if (OrigNS->isInline()) { + if (PrevNS->isInline()) { // The user probably just forgot the 'inline', so suggest that it // be added back. - Diag(Namespc->getLocation(), - diag::warn_inline_namespace_reopened_noninline) + Diag(Loc, diag::warn_inline_namespace_reopened_noninline) << FixItHint::CreateInsertion(NamespaceLoc, "inline "); } else { - Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch) - << Namespc->isInline(); + Diag(Loc, diag::err_inline_namespace_mismatch) + << IsInline; } - Diag(OrigNS->getLocation(), diag::note_previous_definition); - - // Recover by ignoring the new namespace's inline status. - Namespc->setInline(OrigNS->isInline()); - } - - // Attach this namespace decl to the chain of extended namespace - // definitions. - OrigNS->setNextNamespace(Namespc); - Namespc->setOriginalNamespace(OrigNS->getOriginalNamespace()); - - // Remove the previous declaration from the scope. - if (DeclRegionScope->isDeclScope(OrigNS)) { - IdResolver.RemoveDecl(OrigNS); - DeclRegionScope->RemoveDecl(OrigNS); - } + Diag(PrevNS->getLocation(), diag::note_previous_definition); + + IsInline = PrevNS->isInline(); + } } else if (PrevDecl) { // This is an invalid name redefinition. - Diag(Namespc->getLocation(), diag::err_redefinition_different_kind) - << Namespc->getDeclName(); + Diag(Loc, diag::err_redefinition_different_kind) + << II; Diag(PrevDecl->getLocation(), diag::note_previous_definition); - Namespc->setInvalidDecl(); + IsInvalid = true; // Continue on to push Namespc as current DeclContext and return it. - } else if (II->isStr("std") && + } else if (II->isStr("std") && CurContext->getRedeclContext()->isTranslationUnit()) { // This is the first "real" definition of the namespace "std", so update // our cache of the "std" namespace to point at this definition. - if (NamespaceDecl *StdNS = getStdNamespace()) { - // We had already defined a dummy namespace "std". Link this new - // namespace definition to the dummy namespace "std". - StdNS->setNextNamespace(Namespc); - StdNS->setLocation(IdentLoc); - Namespc->setOriginalNamespace(StdNS->getOriginalNamespace()); - } - - // Make our StdNamespace cache point at the first real definition of the - // "std" namespace. - StdNamespace = Namespc; - - // Add this instance of "std" to the set of known namespaces - KnownNamespaces[Namespc] = false; - } else if (!Namespc->isInline()) { - // Since this is an "original" namespace, add it to the known set of - // namespaces if it is not an inline namespace. - KnownNamespaces[Namespc] = false; + PrevNS = getStdNamespace(); + IsStd = true; + AddToKnown = !IsInline; + } else { + // We've seen this namespace for the first time. + AddToKnown = !IsInline; } - - PushOnScopeChains(Namespc, DeclRegionScope); } else { // Anonymous namespaces. - assert(Namespc->isAnonymousNamespace()); - - // Link the anonymous namespace into its parent. - NamespaceDecl *PrevDecl; + + // Determine whether the parent already has an anonymous namespace. DeclContext *Parent = CurContext->getRedeclContext(); if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) { - PrevDecl = TU->getAnonymousNamespace(); - TU->setAnonymousNamespace(Namespc); + PrevNS = TU->getAnonymousNamespace(); } else { NamespaceDecl *ND = cast<NamespaceDecl>(Parent); - PrevDecl = ND->getAnonymousNamespace(); - ND->setAnonymousNamespace(Namespc); + PrevNS = ND->getAnonymousNamespace(); } - // Link the anonymous namespace with its previous declaration. - if (PrevDecl) { - assert(PrevDecl->isAnonymousNamespace()); - assert(!PrevDecl->getNextNamespace()); - Namespc->setOriginalNamespace(PrevDecl->getOriginalNamespace()); - PrevDecl->setNextNamespace(Namespc); + if (PrevNS && IsInline != PrevNS->isInline()) { + // inline-ness must match + Diag(Loc, diag::err_inline_namespace_mismatch) + << IsInline; + Diag(PrevNS->getLocation(), diag::note_previous_definition); + + // Recover by ignoring the new namespace's inline status. + IsInline = PrevNS->isInline(); + } + } + + NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, IsInline, + StartLoc, Loc, II, PrevNS); + if (IsInvalid) + Namespc->setInvalidDecl(); + + ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList); - if (Namespc->isInline() != PrevDecl->isInline()) { - // inline-ness must match - Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch) - << Namespc->isInline(); - Diag(PrevDecl->getLocation(), diag::note_previous_definition); - Namespc->setInvalidDecl(); - // Recover by ignoring the new namespace's inline status. - Namespc->setInline(PrevDecl->isInline()); - } + // FIXME: Should we be merging attributes? + if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>()) + PushNamespaceVisibilityAttr(Attr, Loc); + + if (IsStd) + StdNamespace = Namespc; + if (AddToKnown) + KnownNamespaces[Namespc] = false; + + if (II) { + PushOnScopeChains(Namespc, DeclRegionScope); + } else { + // Link the anonymous namespace into its parent. + DeclContext *Parent = CurContext->getRedeclContext(); + if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) { + TU->setAnonymousNamespace(Namespc); + } else { + cast<NamespaceDecl>(Parent)->setAnonymousNamespace(Namespc); } CurContext->addDecl(Namespc); @@ -5563,7 +5553,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // declarations semantically contained within an anonymous // namespace internal linkage. - if (!PrevDecl) { + if (!PrevNS) { UsingDirectiveDecl* UD = UsingDirectiveDecl::Create(Context, CurContext, /* 'using' */ LBrace, @@ -5602,7 +5592,7 @@ void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) { Namespc->setRBraceLoc(RBrace); PopDeclContext(); if (Namespc->hasAttr<VisibilityAttr>()) - PopPragmaVisibility(); + PopPragmaVisibility(true, RBrace); } CXXRecordDecl *Sema::getStdBadAlloc() const { @@ -5622,14 +5612,142 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() { // The "std" namespace has not yet been defined, so build one implicitly. StdNamespace = NamespaceDecl::Create(Context, Context.getTranslationUnitDecl(), + /*Inline=*/false, SourceLocation(), SourceLocation(), - &PP.getIdentifierTable().get("std")); + &PP.getIdentifierTable().get("std"), + /*PrevDecl=*/0); getStdNamespace()->setImplicit(true); } return getStdNamespace(); } +bool Sema::isStdInitializerList(QualType Ty, QualType *Element) { + assert(getLangOpts().CPlusPlus && + "Looking for std::initializer_list outside of C++."); + + // We're looking for implicit instantiations of + // template <typename E> class std::initializer_list. + + if (!StdNamespace) // If we haven't seen namespace std yet, this can't be it. + return false; + + ClassTemplateDecl *Template = 0; + const TemplateArgument *Arguments = 0; + + if (const RecordType *RT = Ty->getAs<RecordType>()) { + + ClassTemplateSpecializationDecl *Specialization = + dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl()); + if (!Specialization) + return false; + + Template = Specialization->getSpecializedTemplate(); + Arguments = Specialization->getTemplateArgs().data(); + } else if (const TemplateSpecializationType *TST = + Ty->getAs<TemplateSpecializationType>()) { + Template = dyn_cast_or_null<ClassTemplateDecl>( + TST->getTemplateName().getAsTemplateDecl()); + Arguments = TST->getArgs(); + } + if (!Template) + return false; + + if (!StdInitializerList) { + // Haven't recognized std::initializer_list yet, maybe this is it. + CXXRecordDecl *TemplateClass = Template->getTemplatedDecl(); + if (TemplateClass->getIdentifier() != + &PP.getIdentifierTable().get("initializer_list") || + !getStdNamespace()->InEnclosingNamespaceSetOf( + TemplateClass->getDeclContext())) + return false; + // This is a template called std::initializer_list, but is it the right + // template? + TemplateParameterList *Params = Template->getTemplateParameters(); + if (Params->getMinRequiredArguments() != 1) + return false; + if (!isa<TemplateTypeParmDecl>(Params->getParam(0))) + return false; + + // It's the right template. + StdInitializerList = Template; + } + + if (Template != StdInitializerList) + return false; + + // This is an instance of std::initializer_list. Find the argument type. + if (Element) + *Element = Arguments[0].getAsType(); + return true; +} + +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; + } + + 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; + } + ClassTemplateDecl *Template = Result.getAsSingle<ClassTemplateDecl>(); + if (!Template) { + Result.suppressDiagnostics(); + // We found something weird. Complain about the first thing we found. + NamedDecl *Found = *Result.begin(); + S.Diag(Found->getLocation(), diag::err_malformed_std_initializer_list); + return 0; + } + + // We found some template called std::initializer_list. Now verify that it's + // correct. + TemplateParameterList *Params = Template->getTemplateParameters(); + if (Params->getMinRequiredArguments() != 1 || + !isa<TemplateTypeParmDecl>(Params->getParam(0))) { + S.Diag(Template->getLocation(), diag::err_malformed_std_initializer_list); + return 0; + } + + return Template; +} + +QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) { + if (!StdInitializerList) { + StdInitializerList = LookupStdInitializerList(*this, Loc); + if (!StdInitializerList) + return QualType(); + } + + TemplateArgumentListInfo Args(Loc, Loc); + Args.addArgument(TemplateArgumentLoc(TemplateArgument(Element), + Context.getTrivialTypeSourceInfo(Element, + Loc))); + return Context.getCanonicalType( + CheckTemplateIdType(TemplateName(StdInitializerList), Loc, Args)); +} + +bool Sema::isInitListConstructor(const CXXConstructorDecl* Ctor) { + // C++ [dcl.init.list]p2: + // A constructor is an initializer-list constructor if its first parameter + // is of type std::initializer_list<E> or reference to possibly cv-qualified + // std::initializer_list<E> for some type E, and either there are no other + // parameters or else all other parameters have default arguments. + if (Ctor->getNumParams() < 1 || + (Ctor->getNumParams() > 1 && !Ctor->getParamDecl(1)->hasDefaultArg())) + return false; + + QualType ArgType = Ctor->getParamDecl(0)->getType(); + if (const ReferenceType *RT = ArgType->getAs<ReferenceType>()) + ArgType = RT->getPointeeType().getUnqualifiedType(); + + return isStdInitializerList(ArgType, 0); +} + /// \brief Determine whether a using statement is in a context where it will be /// apply in all contexts. static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) { @@ -5643,35 +5761,46 @@ static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) { } } +namespace { + +// Callback to only accept typo corrections that are namespaces. +class NamespaceValidatorCCC : public CorrectionCandidateCallback { + public: + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + if (NamedDecl *ND = candidate.getCorrectionDecl()) { + return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND); + } + return false; + } +}; + +} + static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc, CXXScopeSpec &SS, SourceLocation IdentLoc, IdentifierInfo *Ident) { + NamespaceValidatorCCC Validator; R.clear(); if (TypoCorrection Corrected = S.CorrectTypo(R.getLookupNameInfo(), - R.getLookupKind(), Sc, &SS, NULL, - false, S.CTC_NoKeywords, NULL)) { - if (Corrected.getCorrectionDeclAs<NamespaceDecl>() || - Corrected.getCorrectionDeclAs<NamespaceAliasDecl>()) { - std::string CorrectedStr(Corrected.getAsString(S.getLangOptions())); - std::string CorrectedQuotedStr(Corrected.getQuoted(S.getLangOptions())); - if (DeclContext *DC = S.computeDeclContext(SS, false)) - S.Diag(IdentLoc, diag::err_using_directive_member_suggest) - << Ident << DC << CorrectedQuotedStr << SS.getRange() - << FixItHint::CreateReplacement(IdentLoc, CorrectedStr); - else - S.Diag(IdentLoc, diag::err_using_directive_suggest) - << Ident << CorrectedQuotedStr - << FixItHint::CreateReplacement(IdentLoc, CorrectedStr); + R.getLookupKind(), Sc, &SS, + Validator)) { + std::string CorrectedStr(Corrected.getAsString(S.getLangOpts())); + std::string CorrectedQuotedStr(Corrected.getQuoted(S.getLangOpts())); + if (DeclContext *DC = S.computeDeclContext(SS, false)) + S.Diag(IdentLoc, diag::err_using_directive_member_suggest) + << Ident << DC << CorrectedQuotedStr << SS.getRange() + << FixItHint::CreateReplacement(IdentLoc, CorrectedStr); + else + S.Diag(IdentLoc, diag::err_using_directive_suggest) + << Ident << CorrectedQuotedStr + << FixItHint::CreateReplacement(IdentLoc, CorrectedStr); - S.Diag(Corrected.getCorrectionDecl()->getLocation(), - diag::note_namespace_defined_here) << CorrectedQuotedStr; + S.Diag(Corrected.getCorrectionDecl()->getLocation(), + diag::note_namespace_defined_here) << CorrectedQuotedStr; - Ident = Corrected.getCorrectionAsIdentifierInfo(); - R.addDecl(Corrected.getCorrectionDecl()); - return true; - } - R.setLookupName(Ident); + R.addDecl(Corrected.getCorrectionDecl()); + return true; } return false; } @@ -5757,14 +5886,15 @@ Decl *Sema::ActOnUsingDirective(Scope *S, } void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { - // If scope has associated entity, then using directive is at namespace - // or translation unit scope. We add UsingDirectiveDecls, into - // it's lookup structure. - if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) + // If the scope has an associated entity and the using directive is at + // namespace or translation unit scope, add the UsingDirectiveDecl into + // its lookup structure so qualified name lookup can find it. + DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()); + if (Ctx && !Ctx->isFunctionOrMethod()) Ctx->addDecl(UDir); else - // Otherwise it is block-sope. using-directives will affect lookup - // only to the end of scope. + // Otherwise, it is at block sope. The using-directives will affect lookup + // only to the end of the scope. S->PushUsingDirective(UDir); } @@ -5791,19 +5921,23 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, case UnqualifiedId::IK_ConstructorName: case UnqualifiedId::IK_ConstructorTemplateId: // C++0x inherited constructors. - if (getLangOptions().CPlusPlus0x) break; - - Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_constructor) + Diag(Name.getLocStart(), + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_using_decl_constructor : + diag::err_using_decl_constructor) << SS.getRange(); + + if (getLangOpts().CPlusPlus0x) break; + return 0; case UnqualifiedId::IK_DestructorName: - Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_destructor) + Diag(Name.getLocStart(), diag::err_using_decl_destructor) << SS.getRange(); return 0; case UnqualifiedId::IK_TemplateId: - Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_template_id) + Diag(Name.getLocStart(), diag::err_using_decl_template_id) << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc); return 0; } @@ -5818,7 +5952,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, // talk about access decls instead of using decls in the // diagnostics. if (!HasUsingKeyword) { - UsingLoc = Name.getSourceRange().getBegin(); + UsingLoc = Name.getLocStart(); Diag(UsingLoc, diag::warn_access_decl_deprecated) << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using "); @@ -5883,7 +6017,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, // specialization. The UsingShadowDecl in D<T> then points directly // to A::foo, which will look well-formed when we instantiate. // The right solution is to not collapse the shadow-decl chain. - if (!getLangOptions().CPlusPlus0x && CurContext->isRecord()) { + if (!getLangOpts().CPlusPlus0x && CurContext->isRecord()) { DeclContext *OrigDC = Orig->getDeclContext(); // Handle enums and anonymous structs. @@ -6148,9 +6282,9 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, return UD; } - // Constructor inheriting using decls get special treatment. + // The normal rules do not apply to inheriting constructor declarations. if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) { - if (CheckInheritedConstructorUsingDecl(UD)) + if (CheckInheritingConstructorUsingDecl(UD)) UD->setInvalidDecl(); return UD; } @@ -6166,6 +6300,13 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, if (!IsInstantiation) R.setHideTags(false); + // For the purposes of this lookup, we have a base object type + // equal to that of the current context. + if (CurContext->isRecord()) { + R.setBaseObjectType( + Context.getTypeDeclType(cast<CXXRecordDecl>(CurContext))); + } + LookupQualifiedName(R, LookupContext); if (R.empty()) { @@ -6220,11 +6361,8 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, } /// Additional checks for a using declaration referring to a constructor name. -bool Sema::CheckInheritedConstructorUsingDecl(UsingDecl *UD) { - if (UD->isTypeName()) { - // FIXME: Cannot specify typename when specifying constructor - return true; - } +bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) { + assert(!UD->isTypeName() && "expecting a constructor name"); const Type *SourceType = UD->getQualifier()->getAsType(); assert(SourceType && @@ -6239,6 +6377,8 @@ bool Sema::CheckInheritedConstructorUsingDecl(UsingDecl *UD) { CanQualType BaseType = BaseIt->getType()->getCanonicalTypeUnqualified(); if (CanonicalSourceType == BaseType) break; + if (BaseIt->getType()->isDependentType()) + break; } if (BaseIt == BaseE) { @@ -6250,7 +6390,8 @@ bool Sema::CheckInheritedConstructorUsingDecl(UsingDecl *UD) { return true; } - BaseIt->setInheritConstructors(); + if (!CurContext->isDependentContext()) + BaseIt->setInheritConstructors(); return false; } @@ -6365,7 +6506,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), NamedContext)) return true; - if (getLangOptions().CPlusPlus0x) { + if (getLangOpts().CPlusPlus0x) { // C++0x [namespace.udecl]p3: // In a using-declaration used as a member-declaration, the // nested-name-specifier shall name a base class of the class @@ -6405,7 +6546,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, // need to be repeated. struct UserData { - llvm::DenseSet<const CXXRecordDecl*> Bases; + llvm::SmallPtrSet<const CXXRecordDecl*, 4> Bases; static bool collect(const CXXRecordDecl *Base, void *OpaqueData) { UserData *Data = reinterpret_cast<UserData*>(OpaqueData); @@ -6485,9 +6626,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, // Warn about shadowing the name of a template parameter. if (Previous.isSingleResult() && Previous.getFoundDecl()->isTemplateParameter()) { - if (DiagnoseTemplateParameterShadow(Name.StartLocation, - Previous.getFoundDecl())) - Invalid = true; + DiagnoseTemplateParameterShadow(Name.StartLocation,Previous.getFoundDecl()); Previous.clear(); } @@ -6633,7 +6772,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, if (R.empty()) { if (!TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, Ident)) { - Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange(); + Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); return 0; } } @@ -6664,7 +6803,7 @@ namespace { ~ImplicitlyDefinedFunctionScope() { S.PopExpressionEvaluationContext(); - S.PopFunctionOrBlockScope(); + S.PopFunctionScopeInfo(); } }; } @@ -6757,16 +6896,12 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(ClassType); DeclarationNameInfo NameInfo(Name, ClassLoc); - CXXConstructorDecl *DefaultCon - = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, - Context.getFunctionType(Context.VoidTy, - 0, 0, EPI), - /*TInfo=*/0, - /*isExplicit=*/false, - /*isInline=*/true, - /*isImplicitlyDeclared=*/true, - // FIXME: apply the rules for definitions here - /*isConstexpr=*/false); + CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create( + Context, ClassDecl, ClassLoc, NameInfo, + Context.getFunctionType(Context.VoidTy, 0, 0, EPI), /*TInfo=*/0, + /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true, + /*isConstexpr=*/ClassDecl->defaultedDefaultConstructorIsConstexpr() && + getLangOpts().CPlusPlus0x); DefaultCon->setAccess(AS_public); DefaultCon->setDefaulted(); DefaultCon->setImplicit(); @@ -6905,7 +7040,6 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { Context.getCanonicalType(CtorIt->getType()).getTypePtr()); } - Scope *S = getScopeForContext(ClassDecl); DeclarationName CreatedCtorName = Context.DeclarationNames.getCXXConstructorName( ClassDecl->getTypeForDecl()->getCanonicalTypeUnqualified()); @@ -6927,10 +7061,12 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { CtorE = BaseDecl->ctor_end(); CtorIt != CtorE; ++CtorIt) { // Find the using declaration for inheriting this base's constructors. + // FIXME: Don't perform name lookup just to obtain a source location! DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(CanonicalBase); - UsingDecl *UD = dyn_cast_or_null<UsingDecl>( - LookupSingleName(S, Name,SourceLocation(), LookupUsingDeclName)); + LookupResult Result(*this, Name, SourceLocation(), LookupUsingDeclName); + LookupQualifiedName(Result, CurContext); + UsingDecl *UD = Result.getAsSingle<UsingDecl>(); SourceLocation UsingLoc = UD ? UD->getLocation() : ClassDecl->getLocation(); @@ -7041,7 +7177,6 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { NewCtor->setParams(ParamDecls); NewCtor->setInheritedConstructor(BaseCtor); - PushOnScopeChains(NewCtor, S, false); ClassDecl->addDecl(NewCtor); result.first->second.second = NewCtor; } @@ -7131,18 +7266,19 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { // This could be uniqued if it ever proves significant. Destructor->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(Ty)); - if (ShouldDeleteDestructor(Destructor)) - Destructor->setDeletedAsWritten(); - AddOverriddenMethods(ClassDecl, Destructor); - + + if (ShouldDeleteSpecialMember(Destructor, CXXDestructor)) + Destructor->setDeletedAsWritten(); + return Destructor; } void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, CXXDestructorDecl *Destructor) { assert((Destructor->isDefaulted() && - !Destructor->doesThisDeclarationHaveABody()) && + !Destructor->doesThisDeclarationHaveABody() && + !Destructor->isDeleted()) && "DefineImplicitDestructor - call it for implicit default dtor"); CXXRecordDecl *ClassDecl = Destructor->getParent(); assert(ClassDecl && "DefineImplicitDestructor - invalid destructor"); @@ -7259,8 +7395,8 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, while (F.hasNext()) { NamedDecl *D = F.next(); if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) - if (Copying ? Method->isCopyAssignmentOperator() : - Method->isMoveAssignmentOperator()) + if (Method->isCopyAssignmentOperator() || + (!Copying && Method->isMoveAssignmentOperator())) continue; F.erase(); @@ -7290,15 +7426,18 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, // reference to operator=; this is required to suppress the virtual // call mechanism. CXXScopeSpec SS; + const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr()); SS.MakeTrivial(S.Context, NestedNameSpecifier::Create(S.Context, 0, false, - T.getTypePtr()), + CanonicalT), Loc); // Create the reference to operator=. ExprResult OpEqualRef = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS, - /*FirstQualifierInScope=*/0, OpLookup, + /*TemplateKWLoc=*/SourceLocation(), + /*FirstQualifierInScope=*/0, + OpLookup, /*TemplateArgs=*/0, /*SuppressQualifierCheck=*/true); if (OpEqualRef.isInvalid()) @@ -7339,7 +7478,7 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, // Create the iteration variable. IdentifierInfo *IterationVarName = 0; { - llvm::SmallString<8> Str; + SmallString<8> Str; llvm::raw_svector_ostream OS(Str); OS << "__i" << Depth; IterationVarName = &S.Context.Idents.get(OS.str()); @@ -7356,9 +7495,11 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, // Create a reference to the iteration variable; we'll use this several // times throughout. Expr *IterationVarRef - = S.BuildDeclRefExpr(IterationVar, SizeType, VK_RValue, Loc).take(); + = S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc).take(); assert(IterationVarRef && "Reference to invented variable cannot fail!"); - + Expr *IterationVarRefRVal = S.DefaultLvalueConversion(IterationVarRef).take(); + assert(IterationVarRefRVal && "Conversion of invented variable cannot fail!"); + // Create the DeclStmt that holds the iteration variable. Stmt *InitStmt = new (S.Context) DeclStmt(DeclGroupRef(IterationVar),Loc,Loc); @@ -7366,7 +7507,7 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, llvm::APInt Upper = ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType)); Expr *Comparison - = new (S.Context) BinaryOperator(IterationVarRef, + = new (S.Context) BinaryOperator(IterationVarRefRVal, IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), BO_NE, S.Context.BoolTy, VK_RValue, OK_Ordinary, Loc); @@ -7378,9 +7519,11 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, // Subscript the "from" and "to" expressions with the iteration variable. From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc, - IterationVarRef, Loc)); + IterationVarRefRVal, + Loc)); To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc, - IterationVarRef, Loc)); + IterationVarRefRVal, + Loc)); if (!Copying) // Cast to rvalue From = CastForMoving(S, From); @@ -7432,7 +7575,7 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst( &HasConstCopyAssignment); } - // In C++0x, the above citation has "or virtual added" + // In C++11, the above citation has "or virtual" added if (LangOpts.CPlusPlus0x) { for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), BaseEnd = ClassDecl->vbases_end(); @@ -7565,15 +7708,14 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { PushOnScopeChains(CopyAssignment, S, false); ClassDecl->addDecl(CopyAssignment); - // C++0x [class.copy]p18: - // ... If the class definition declares a move constructor or move - // assignment operator, the implicitly declared copy assignment operator is - // defined as deleted; ... - if (ClassDecl->hasUserDeclaredMoveConstructor() || - ClassDecl->hasUserDeclaredMoveAssignment() || - ShouldDeleteCopyAssignmentOperator(CopyAssignment)) + // C++0x [class.copy]p19: + // .... If the class definition does not explicitly declare a copy + // assignment operator, there is no user-declared move constructor, and + // there is no user-declared move assignment operator, a copy assignment + // operator is implicitly declared as defaulted. + if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment)) CopyAssignment->setDeletedAsWritten(); - + AddOverriddenMethods(ClassDecl, CopyAssignment); return CopyAssignment; } @@ -7583,7 +7725,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, assert((CopyAssignOperator->isDefaulted() && CopyAssignOperator->isOverloadedOperator() && CopyAssignOperator->getOverloadedOperator() == OO_Equal && - !CopyAssignOperator->doesThisDeclarationHaveABody()) && + !CopyAssignOperator->doesThisDeclarationHaveABody() && + !CopyAssignOperator->isDeleted()) && "DefineImplicitCopyAssignment called for wrong function"); CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent(); @@ -7734,10 +7877,12 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, MemberLookup.resolveKind(); ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType, Loc, /*IsArrow=*/false, - SS, 0, MemberLookup, 0); + SS, SourceLocation(), 0, + MemberLookup, 0); ExprResult To = BuildMemberReferenceExpr(This, This->getType(), Loc, /*IsArrow=*/true, - SS, 0, MemberLookup, 0); + SS, SourceLocation(), 0, + MemberLookup, 0); assert(!From.isInvalid() && "Implicit field reference cannot fail"); assert(!To.isInvalid() && "Implicit field reference cannot fail"); @@ -7869,10 +8014,14 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, CopyAssignOperator->setInvalidDecl(); return; } - - StmtResult Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements), - /*isStmtExpr=*/false); - assert(!Body.isInvalid() && "Compound statement creation cannot fail"); + + StmtResult Body; + { + CompoundScopeRAII CompoundScope(*this); + Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements), + /*isStmtExpr=*/false); + assert(!Body.isInvalid() && "Compound statement creation cannot fail"); + } CopyAssignOperator->setBody(Body.takeAs<Stmt>()); if (ASTMutationListener *L = getASTMutationListener()) { @@ -7937,7 +8086,115 @@ Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl) { return ExceptSpec; } +/// Determine whether the class type has any direct or indirect virtual base +/// classes which have a non-trivial move assignment operator. +static bool +hasVirtualBaseWithNonTrivialMoveAssignment(Sema &S, CXXRecordDecl *ClassDecl) { + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + Base != BaseEnd; ++Base) { + CXXRecordDecl *BaseClass = + cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + + // Try to declare the move assignment. If it would be deleted, then the + // class does not have a non-trivial move assignment. + if (BaseClass->needsImplicitMoveAssignment()) + S.DeclareImplicitMoveAssignment(BaseClass); + + // If the class has both a trivial move assignment and a non-trivial move + // assignment, hasTrivialMoveAssignment() is false. + if (BaseClass->hasDeclaredMoveAssignment() && + !BaseClass->hasTrivialMoveAssignment()) + return true; + } + + return false; +} + +/// Determine whether the given type either has a move constructor or is +/// trivially copyable. +static bool +hasMoveOrIsTriviallyCopyable(Sema &S, QualType Type, bool IsConstructor) { + Type = S.Context.getBaseElementType(Type); + + // FIXME: Technically, non-trivially-copyable non-class types, such as + // reference types, are supposed to return false here, but that appears + // to be a standard defect. + CXXRecordDecl *ClassDecl = Type->getAsCXXRecordDecl(); + if (!ClassDecl) + return true; + + if (Type.isTriviallyCopyableType(S.Context)) + return true; + + if (IsConstructor) { + if (ClassDecl->needsImplicitMoveConstructor()) + S.DeclareImplicitMoveConstructor(ClassDecl); + return ClassDecl->hasDeclaredMoveConstructor(); + } + + if (ClassDecl->needsImplicitMoveAssignment()) + S.DeclareImplicitMoveAssignment(ClassDecl); + return ClassDecl->hasDeclaredMoveAssignment(); +} + +/// Determine whether all non-static data members and direct or virtual bases +/// of class \p ClassDecl have either a move operation, or are trivially +/// copyable. +static bool subobjectsHaveMoveOrTrivialCopy(Sema &S, CXXRecordDecl *ClassDecl, + bool IsConstructor) { + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + Base != BaseEnd; ++Base) { + if (Base->isVirtual()) + continue; + + if (!hasMoveOrIsTriviallyCopyable(S, Base->getType(), IsConstructor)) + return false; + } + + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + Base != BaseEnd; ++Base) { + if (!hasMoveOrIsTriviallyCopyable(S, Base->getType(), IsConstructor)) + return false; + } + + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + if (!hasMoveOrIsTriviallyCopyable(S, (*Field)->getType(), IsConstructor)) + return false; + } + + return true; +} + CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { + // C++11 [class.copy]p20: + // If the definition of a class X does not explicitly declare a move + // assignment operator, one will be implicitly declared as defaulted + // if and only if: + // + // - [first 4 bullets] + assert(ClassDecl->needsImplicitMoveAssignment()); + + // [Checked after we build the declaration] + // - the move assignment operator would not be implicitly defined as + // deleted, + + // [DR1402]: + // - X has no direct or indirect virtual base class with a non-trivial + // move assignment operator, and + // - each of X's non-static data members and direct or virtual base classes + // has a type that either has a move assignment operator or is trivially + // copyable. + if (hasVirtualBaseWithNonTrivialMoveAssignment(*this, ClassDecl) || + !subobjectsHaveMoveOrTrivialCopy(*this, ClassDecl,/*Constructor*/false)) { + ClassDecl->setFailedImplicitMoveAssignment(); + return 0; + } + // Note: The following rules are largely analoguous to the move // constructor rules. @@ -7985,7 +8242,7 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { // [...] // - the move assignment operator would not be implicitly defined as // deleted. - if (ShouldDeleteMoveAssignmentOperator(MoveAssignment)) { + if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) { // Cache this result so that we don't try to generate this over and over // on every lookup, leaking memory and wasting time. ClassDecl->setFailedImplicitMoveAssignment(); @@ -8005,7 +8262,8 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, assert((MoveAssignOperator->isDefaulted() && MoveAssignOperator->isOverloadedOperator() && MoveAssignOperator->getOverloadedOperator() == OO_Equal && - !MoveAssignOperator->doesThisDeclarationHaveABody()) && + !MoveAssignOperator->doesThisDeclarationHaveABody() && + !MoveAssignOperator->isDeleted()) && "DefineImplicitMoveAssignment called for wrong function"); CXXRecordDecl *ClassDecl = MoveAssignOperator->getParent(); @@ -8052,7 +8310,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, // ASTs. Expr *This = ActOnCXXThis(Loc).takeAs<Expr>(); assert(This && "Reference to this cannot fail!"); - + // Assign base classes. bool Invalid = false; for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), @@ -8154,10 +8412,12 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, MemberLookup.resolveKind(); ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType, Loc, /*IsArrow=*/false, - SS, 0, MemberLookup, 0); + SS, SourceLocation(), 0, + MemberLookup, 0); ExprResult To = BuildMemberReferenceExpr(This, This->getType(), Loc, /*IsArrow=*/true, - SS, 0, MemberLookup, 0); + SS, SourceLocation(), 0, + MemberLookup, 0); assert(!From.isInvalid() && "Implicit field reference cannot fail"); assert(!To.isInvalid() && "Implicit field reference cannot fail"); @@ -8299,10 +8559,14 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, MoveAssignOperator->setInvalidDecl(); return; } - - StmtResult Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements), - /*isStmtExpr=*/false); - assert(!Body.isInvalid() && "Compound statement creation cannot fail"); + + StmtResult Body; + { + CompoundScopeRAII CompoundScope(*this); + Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements), + /*isStmtExpr=*/false); + assert(!Body.isInvalid() && "Compound statement creation cannot fail"); + } MoveAssignOperator->setBody(Body.takeAs<Stmt>()); if (ASTMutationListener *L = getASTMutationListener()) { @@ -8441,21 +8705,17 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( DeclarationNameInfo NameInfo(Name, ClassLoc); // An implicitly-declared copy constructor is an inline public - // member of its class. - CXXConstructorDecl *CopyConstructor - = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, - Context.getFunctionType(Context.VoidTy, - &ArgType, 1, EPI), - /*TInfo=*/0, - /*isExplicit=*/false, - /*isInline=*/true, - /*isImplicitlyDeclared=*/true, - // FIXME: apply the rules for definitions here - /*isConstexpr=*/false); + // member of its class. + CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create( + Context, ClassDecl, ClassLoc, NameInfo, + Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI), /*TInfo=*/0, + /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true, + /*isConstexpr=*/ClassDecl->defaultedCopyConstructorIsConstexpr() && + getLangOpts().CPlusPlus0x); CopyConstructor->setAccess(AS_public); CopyConstructor->setDefaulted(); CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor()); - + // Note that we have declared this constructor. ++ASTContext::NumImplicitCopyConstructorsDeclared; @@ -8472,15 +8732,14 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( PushOnScopeChains(CopyConstructor, S, false); ClassDecl->addDecl(CopyConstructor); - // C++0x [class.copy]p7: - // ... If the class definition declares a move constructor or move - // assignment operator, the implicitly declared constructor is defined as - // deleted; ... - if (ClassDecl->hasUserDeclaredMoveConstructor() || - ClassDecl->hasUserDeclaredMoveAssignment() || - ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) + // C++11 [class.copy]p8: + // ... If the class definition does not explicitly declare a copy + // constructor, there is no user-declared move constructor, and there is no + // user-declared move assignment operator, a copy constructor is implicitly + // declared as defaulted. + if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) CopyConstructor->setDeletedAsWritten(); - + return CopyConstructor; } @@ -8488,7 +8747,8 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *CopyConstructor) { assert((CopyConstructor->isDefaulted() && CopyConstructor->isCopyConstructor() && - !CopyConstructor->doesThisDeclarationHaveABody()) && + !CopyConstructor->doesThisDeclarationHaveABody() && + !CopyConstructor->isDeleted()) && "DefineImplicitCopyConstructor - call it for implicit copy ctor"); CXXRecordDecl *ClassDecl = CopyConstructor->getParent(); @@ -8503,9 +8763,10 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, << CXXCopyConstructor << Context.getTagDeclType(ClassDecl); CopyConstructor->setInvalidDecl(); } else { + Sema::CompoundScopeRAII CompoundScope(*this); CopyConstructor->setBody(ActOnCompoundStmt(CopyConstructor->getLocation(), CopyConstructor->getLocation(), - MultiStmtArg(*this, 0, 0), + MultiStmtArg(*this, 0, 0), /*isStmtExpr=*/false) .takeAs<Stmt>()); CopyConstructor->setImplicitlyDefined(true); @@ -8561,12 +8822,7 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) { for (RecordDecl::field_iterator F = ClassDecl->field_begin(), FEnd = ClassDecl->field_end(); F != FEnd; ++F) { - if (F->hasInClassInitializer()) { - if (Expr *E = F->getInClassInitializer()) - ExceptSpec.CalledExpr(E); - else if (!F->isInvalidDecl()) - ExceptSpec.SetDelayed(); - } else if (const RecordType *RecordTy + if (const RecordType *RecordTy = Context.getBaseElementType(F->getType())->getAs<RecordType>()) { CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl()); CXXConstructorDecl *Constructor = LookupMovingConstructor(FieldRecDecl); @@ -8585,6 +8841,25 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) { CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( CXXRecordDecl *ClassDecl) { + // C++11 [class.copy]p9: + // If the definition of a class X does not explicitly declare a move + // constructor, one will be implicitly declared as defaulted if and only if: + // + // - [first 4 bullets] + assert(ClassDecl->needsImplicitMoveConstructor()); + + // [Checked after we build the declaration] + // - the move assignment operator would not be implicitly defined as + // deleted, + + // [DR1402]: + // - each of X's non-static data members and direct or virtual base classes + // has a type that either has a move constructor or is trivially copyable. + if (!subobjectsHaveMoveOrTrivialCopy(*this, ClassDecl, /*Constructor*/true)) { + ClassDecl->setFailedImplicitMoveConstructor(); + return 0; + } + ImplicitExceptionSpecification Spec( ComputeDefaultedMoveCtorExceptionSpec(ClassDecl)); @@ -8601,21 +8876,17 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( // C++0x [class.copy]p11: // An implicitly-declared copy/move constructor is an inline public - // member of its class. - CXXConstructorDecl *MoveConstructor - = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, - Context.getFunctionType(Context.VoidTy, - &ArgType, 1, EPI), - /*TInfo=*/0, - /*isExplicit=*/false, - /*isInline=*/true, - /*isImplicitlyDeclared=*/true, - // FIXME: apply the rules for definitions here - /*isConstexpr=*/false); + // member of its class. + CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create( + Context, ClassDecl, ClassLoc, NameInfo, + Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI), /*TInfo=*/0, + /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true, + /*isConstexpr=*/ClassDecl->defaultedMoveConstructorIsConstexpr() && + getLangOpts().CPlusPlus0x); MoveConstructor->setAccess(AS_public); MoveConstructor->setDefaulted(); MoveConstructor->setTrivial(ClassDecl->hasTrivialMoveConstructor()); - + // Add the parameter to the constructor. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor, ClassLoc, ClassLoc, @@ -8651,7 +8922,8 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *MoveConstructor) { assert((MoveConstructor->isDefaulted() && MoveConstructor->isMoveConstructor() && - !MoveConstructor->doesThisDeclarationHaveABody()) && + !MoveConstructor->doesThisDeclarationHaveABody() && + !MoveConstructor->isDeleted()) && "DefineImplicitMoveConstructor - call it for implicit move ctor"); CXXRecordDecl *ClassDecl = MoveConstructor->getParent(); @@ -8666,9 +8938,10 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, << CXXMoveConstructor << Context.getTagDeclType(ClassDecl); MoveConstructor->setInvalidDecl(); } else { + Sema::CompoundScopeRAII CompoundScope(*this); MoveConstructor->setBody(ActOnCompoundStmt(MoveConstructor->getLocation(), MoveConstructor->getLocation(), - MultiStmtArg(*this, 0, 0), + MultiStmtArg(*this, 0, 0), /*isStmtExpr=*/false) .takeAs<Stmt>()); MoveConstructor->setImplicitlyDefined(true); @@ -8681,6 +8954,133 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, } } +bool Sema::isImplicitlyDeleted(FunctionDecl *FD) { + return FD->isDeleted() && + (FD->isDefaulted() || FD->isImplicit()) && + isa<CXXMethodDecl>(FD); +} + +/// \brief Mark the call operator of the given lambda closure type as "used". +static void markLambdaCallOperatorUsed(Sema &S, CXXRecordDecl *Lambda) { + CXXMethodDecl *CallOperator + = cast<CXXMethodDecl>( + *Lambda->lookup( + S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).first); + CallOperator->setReferenced(); + CallOperator->setUsed(); +} + +void Sema::DefineImplicitLambdaToFunctionPointerConversion( + SourceLocation CurrentLocation, + CXXConversionDecl *Conv) +{ + CXXRecordDecl *Lambda = Conv->getParent(); + + // Make sure that the lambda call operator is marked used. + markLambdaCallOperatorUsed(*this, Lambda); + + Conv->setUsed(); + + ImplicitlyDefinedFunctionScope Scope(*this, Conv); + DiagnosticErrorTrap Trap(Diags); + + // Return the address of the __invoke function. + DeclarationName InvokeName = &Context.Idents.get("__invoke"); + CXXMethodDecl *Invoke + = cast<CXXMethodDecl>(*Lambda->lookup(InvokeName).first); + Expr *FunctionRef = BuildDeclRefExpr(Invoke, Invoke->getType(), + VK_LValue, Conv->getLocation()).take(); + assert(FunctionRef && "Can't refer to __invoke function?"); + Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take(); + Conv->setBody(new (Context) CompoundStmt(Context, &Return, 1, + Conv->getLocation(), + Conv->getLocation())); + + // Fill in the __invoke function with a dummy implementation. IR generation + // will fill in the actual details. + Invoke->setUsed(); + Invoke->setReferenced(); + Invoke->setBody(new (Context) CompoundStmt(Context, 0, 0, Conv->getLocation(), + Conv->getLocation())); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Conv); + L->CompletedImplicitDefinition(Invoke); + } +} + +void Sema::DefineImplicitLambdaToBlockPointerConversion( + SourceLocation CurrentLocation, + CXXConversionDecl *Conv) +{ + Conv->setUsed(); + + ImplicitlyDefinedFunctionScope Scope(*this, Conv); + 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(); + + ExprResult BuildBlock = BuildBlockForLambdaConversion(CurrentLocation, + Conv->getLocation(), + Conv, DerefThis); + + // If we're not under ARC, make sure we still get the _Block_copy/autorelease + // behavior. Note that only the general conversion function does this + // (since it's unusable otherwise); in the case where we inline the + // block literal, it has block literal lifetime semantics. + if (!BuildBlock.isInvalid() && !getLangOpts().ObjCAutoRefCount) + BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock.get()->getType(), + CK_CopyAndAutoreleaseBlockObject, + BuildBlock.get(), 0, VK_RValue); + + if (BuildBlock.isInvalid()) { + Diag(CurrentLocation, diag::note_lambda_to_block_conv); + Conv->setInvalidDecl(); + return; + } + + // Create the return statement that returns the block from the conversion + // function. + StmtResult Return = ActOnReturnStmt(Conv->getLocation(), BuildBlock.get()); + if (Return.isInvalid()) { + Diag(CurrentLocation, diag::note_lambda_to_block_conv); + Conv->setInvalidDecl(); + return; + } + + // Set the body of the conversion function. + Stmt *ReturnS = Return.take(); + Conv->setBody(new (Context) CompoundStmt(Context, &ReturnS, 1, + Conv->getLocation(), + Conv->getLocation())); + + // We're done; notify the mutation listener, if any. + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Conv); + } +} + +/// \brief Determine whether the given list arguments contains exactly one +/// "real" (non-default) argument. +static bool hasOneRealArgument(MultiExprArg Args) { + switch (Args.size()) { + case 0: + return false; + + default: + if (!Args.get()[1]->isDefaultArgument()) + return false; + + // fall through + case 1: + return !Args.get()[0]->isDefaultArgument(); + } + + return false; +} + ExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, @@ -8702,7 +9102,7 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, // can be omitted by constructing the temporary object // directly into the target of the omitted copy/move if (ConstructKind == CXXConstructExpr::CK_Complete && - Constructor->isCopyOrMoveConstructor() && ExprArgs.size() >= 1) { + Constructor->isCopyOrMoveConstructor() && hasOneRealArgument(ExprArgs)) { Expr *SubExpr = ((Expr **)ExprArgs.get())[0]; Elidable = SubExpr->isTemporaryObject(Context, Constructor->getParent()); } @@ -8732,10 +9132,11 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CheckNonNullArguments(NonNull, ExprArgs.get(), ConstructLoc); } - MarkDeclarationReferenced(ConstructLoc, Constructor); + MarkFunctionReferenced(ConstructLoc, Constructor); return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc, Constructor, Elidable, Exprs, NumExprs, - HadMultipleCandidates, RequiresZeroInit, + HadMultipleCandidates, /*FIXME*/false, + RequiresZeroInit, static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind), ParenRange)); } @@ -8754,7 +9155,7 @@ bool Sema::InitializeVarWithConstructor(VarDecl *VD, Expr *Temp = TempResult.takeAs<Expr>(); CheckImplicitConversions(Temp, VD->getLocation()); - MarkDeclarationReferenced(VD->getLocation(), Constructor); + MarkFunctionReferenced(VD->getLocation(), Constructor); Temp = MaybeCreateExprWithCleanups(Temp); VD->setInit(Temp); @@ -8766,15 +9167,16 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl()); if (ClassDecl->isInvalidDecl()) return; - if (ClassDecl->hasTrivialDestructor()) return; + if (ClassDecl->hasIrrelevantDestructor()) return; if (ClassDecl->isDependentContext()) return; CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl); - MarkDeclarationReferenced(VD->getLocation(), Destructor); + MarkFunctionReferenced(VD->getLocation(), Destructor); CheckDestructorAccess(VD->getLocation(), Destructor, PDiag(diag::err_access_dtor_var) << VD->getDeclName() << VD->getType()); + DiagnoseUseOfDecl(Destructor, VD->getLocation()); if (!VD->hasGlobalStorage()) return; @@ -8787,188 +9189,6 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { Diag(VD->getLocation(), diag::warn_global_destructor); } -/// AddCXXDirectInitializerToDecl - This action is called immediately after -/// ActOnDeclarator, when a C++ direct initializer is present. -/// e.g: "int x(1);" -void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl, - SourceLocation LParenLoc, - MultiExprArg Exprs, - SourceLocation RParenLoc, - bool TypeMayContainAuto) { - assert(Exprs.size() != 0 && Exprs.get() && "missing expressions"); - - // If there is no declaration, there was an error parsing it. Just ignore - // the initializer. - if (RealDecl == 0) - return; - - VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl); - if (!VDecl) { - Diag(RealDecl->getLocation(), diag::err_illegal_initializer); - RealDecl->setInvalidDecl(); - return; - } - - // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. - if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) { - // FIXME: n3225 doesn't actually seem to indicate this is ill-formed - if (Exprs.size() > 1) { - Diag(Exprs.get()[1]->getSourceRange().getBegin(), - diag::err_auto_var_init_multiple_expressions) - << VDecl->getDeclName() << VDecl->getType() - << VDecl->getSourceRange(); - RealDecl->setInvalidDecl(); - return; - } - - Expr *Init = Exprs.get()[0]; - TypeSourceInfo *DeducedType = 0; - if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType)) - Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure) - << VDecl->getDeclName() << VDecl->getType() << Init->getType() - << Init->getSourceRange(); - if (!DeducedType) { - RealDecl->setInvalidDecl(); - return; - } - VDecl->setTypeSourceInfo(DeducedType); - VDecl->setType(DeducedType->getType()); - - // In ARC, infer lifetime. - if (getLangOptions().ObjCAutoRefCount && inferObjCARCLifetime(VDecl)) - VDecl->setInvalidDecl(); - - // If this is a redeclaration, check that the type we just deduced matches - // the previously declared type. - if (VarDecl *Old = VDecl->getPreviousDeclaration()) - MergeVarDeclTypes(VDecl, Old); - } - - // We will represent direct-initialization similarly to copy-initialization: - // int x(1); -as-> int x = 1; - // ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c); - // - // Clients that want to distinguish between the two forms, can check for - // direct initializer using VarDecl::hasCXXDirectInitializer(). - // A major benefit is that clients that don't particularly care about which - // exactly form was it (like the CodeGen) can handle both cases without - // special case code. - - // C++ 8.5p11: - // The form of initialization (using parentheses or '=') is generally - // insignificant, but does matter when the entity being initialized has a - // class type. - - if (!VDecl->getType()->isDependentType() && - !VDecl->getType()->isIncompleteArrayType() && - RequireCompleteType(VDecl->getLocation(), VDecl->getType(), - diag::err_typecheck_decl_incomplete_type)) { - VDecl->setInvalidDecl(); - return; - } - - // The variable can not have an abstract class type. - if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(), - diag::err_abstract_type_in_decl, - AbstractVariableType)) - VDecl->setInvalidDecl(); - - const VarDecl *Def; - if ((Def = VDecl->getDefinition()) && Def != VDecl) { - Diag(VDecl->getLocation(), diag::err_redefinition) - << VDecl->getDeclName(); - Diag(Def->getLocation(), diag::note_previous_definition); - VDecl->setInvalidDecl(); - return; - } - - // C++ [class.static.data]p4 - // If a static data member is of const integral or const - // enumeration type, its declaration in the class definition can - // specify a constant-initializer which shall be an integral - // constant expression (5.19). In that case, the member can appear - // in integral constant expressions. The member shall still be - // defined in a namespace scope if it is used in the program and the - // namespace scope definition shall not contain an initializer. - // - // We already performed a redefinition check above, but for static - // data members we also need to check whether there was an in-class - // declaration with an initializer. - const VarDecl* PrevInit = 0; - if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) { - Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName(); - Diag(PrevInit->getLocation(), diag::note_previous_definition); - return; - } - - bool IsDependent = false; - for (unsigned I = 0, N = Exprs.size(); I != N; ++I) { - if (DiagnoseUnexpandedParameterPack(Exprs.get()[I], UPPC_Expression)) { - VDecl->setInvalidDecl(); - return; - } - - if (Exprs.get()[I]->isTypeDependent()) - IsDependent = true; - } - - // If either the declaration has a dependent type or if any of the - // expressions is type-dependent, we represent the initialization - // via a ParenListExpr for later use during template instantiation. - if (VDecl->getType()->isDependentType() || IsDependent) { - // Let clients know that initialization was done with a direct initializer. - VDecl->setCXXDirectInitializer(true); - - // Store the initialization expressions as a ParenListExpr. - unsigned NumExprs = Exprs.size(); - VDecl->setInit(new (Context) ParenListExpr( - Context, LParenLoc, (Expr **)Exprs.release(), NumExprs, RParenLoc, - VDecl->getType().getNonReferenceType())); - return; - } - - // Capture the variable that is being initialized and the style of - // initialization. - InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); - - // FIXME: Poor source location information. - InitializationKind Kind - = InitializationKind::CreateDirect(VDecl->getLocation(), - LParenLoc, RParenLoc); - - QualType T = VDecl->getType(); - InitializationSequence InitSeq(*this, Entity, Kind, - Exprs.get(), Exprs.size()); - ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(Exprs), &T); - if (Result.isInvalid()) { - VDecl->setInvalidDecl(); - return; - } else if (T != VDecl->getType()) { - VDecl->setType(T); - Result.get()->setType(T); - } - - - Expr *Init = Result.get(); - CheckImplicitConversions(Init, LParenLoc); - - if (VDecl->isConstexpr() && !VDecl->isInvalidDecl() && - !Init->isValueDependent() && - !Init->isConstantInitializer(Context, - VDecl->getType()->isReferenceType())) { - // FIXME: Improve this diagnostic to explain why the initializer is not - // a constant expression. - Diag(VDecl->getLocation(), diag::err_constexpr_var_requires_const_init) - << VDecl << Init->getSourceRange(); - } - - Init = MaybeCreateExprWithCleanups(Init); - VDecl->setInit(Init); - VDecl->setCXXDirectInitializer(true); - - CheckCompleteVariableDeclaration(VDecl); -} - /// \brief Given a constructor and the set of arguments provided for the /// constructor, convert the arguments and add any required default arguments /// to form a proper call to this constructor. @@ -8978,7 +9198,8 @@ bool Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, MultiExprArg ArgsPtr, SourceLocation Loc, - ASTOwningVector<Expr*> &ConvertedArgs) { + ASTOwningVector<Expr*> &ConvertedArgs, + bool AllowExplicit) { // FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall. unsigned NumArgs = ArgsPtr.size(); Expr **Args = (Expr **)ArgsPtr.get(); @@ -8999,9 +9220,13 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, SmallVector<Expr *, 8> AllArgs; bool Invalid = GatherArgumentsForCall(Loc, Constructor, Proto, 0, Args, NumArgs, AllArgs, - CallType); - for (unsigned i =0, size = AllArgs.size(); i < size; i++) - ConvertedArgs.push_back(AllArgs[i]); + CallType, AllowExplicit); + ConvertedArgs.append(AllArgs.begin(), AllArgs.end()); + + DiagnoseSentinelCalls(Constructor, Loc, AllArgs.data(), AllArgs.size()); + + // FIXME: Missing call to CheckFunctionCall or equivalent + return Invalid; } @@ -9270,21 +9495,29 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { /// of this literal operator function is well-formed. If so, returns /// false; otherwise, emits appropriate diagnostics and returns true. bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { - DeclContext *DC = FnDecl->getDeclContext(); - Decl::Kind Kind = DC->getDeclKind(); - if (Kind != Decl::TranslationUnit && Kind != Decl::Namespace && - Kind != Decl::LinkageSpec) { + if (isa<CXXMethodDecl>(FnDecl)) { Diag(FnDecl->getLocation(), diag::err_literal_operator_outside_namespace) << FnDecl->getDeclName(); return true; } + if (FnDecl->isExternC()) { + Diag(FnDecl->getLocation(), diag::err_literal_operator_extern_c); + return true; + } + bool Valid = false; + // This might be the definition of a literal operator template. + FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate(); + // This might be a specialization of a literal operator template. + if (!TpDecl) + TpDecl = FnDecl->getPrimaryTemplate(); + // template <char...> type operator "" name() is the only valid template // signature, and the only valid signature with no parameters. - if (FnDecl->param_size() == 0) { - if (FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate()) { + if (TpDecl) { + if (FnDecl->param_size() == 0) { // Must have only one template parameter TemplateParameterList *Params = TpDecl->getTemplateParameters(); if (Params->size() == 1) { @@ -9297,11 +9530,11 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { Valid = true; } } - } else { + } else if (FnDecl->param_size()) { // Check the first parameter FunctionDecl::param_iterator Param = FnDecl->param_begin(); - QualType T = (*Param)->getType(); + QualType T = (*Param)->getType().getUnqualifiedType(); // unsigned long long int, long double, and any character type are allowed // as the only parameters. @@ -9321,7 +9554,7 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { if (!PT) goto FinishedParams; T = PT->getPointeeType(); - if (!T.isConstQualified()) + if (!T.isConstQualified() || T.isVolatileQualified()) goto FinishedParams; T = T.getUnqualifiedType(); @@ -9358,30 +9591,28 @@ FinishedParams: return true; } - StringRef LiteralName + // 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(), + diag::err_literal_operator_default_argument) + << (*Param)->getDefaultArgRange(); + break; + } + } + + StringRef LiteralName = FnDecl->getDeclName().getCXXLiteralIdentifier()->getName(); if (LiteralName[0] != '_') { - // C++0x [usrlit.suffix]p1: - // Literal suffix identifiers that do not start with an underscore are - // reserved for future standardization. - bool IsHexFloat = true; - if (LiteralName.size() > 1 && - (LiteralName[0] == 'P' || LiteralName[0] == 'p')) { - for (unsigned I = 1, N = LiteralName.size(); I < N; ++I) { - if (!isdigit(LiteralName[I])) { - IsHexFloat = false; - break; - } - } - } - - if (IsHexFloat) - Diag(FnDecl->getLocation(), diag::warn_user_literal_hexfloat) - << LiteralName; - else - Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved); + // C++11 [usrlit.suffix]p1: + // Literal suffix identifiers that do not start with an underscore + // are reserved for future standardization. + Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved); } - + return false; } @@ -9458,28 +9689,21 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, Invalid = true; } - // GCC allows catching pointers and references to incomplete types - // as an extension; so do we, but we warn by default. - QualType BaseType = ExDeclType; int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference unsigned DK = diag::err_catch_incomplete; - bool IncompleteCatchIsInvalid = true; if (const PointerType *Ptr = BaseType->getAs<PointerType>()) { BaseType = Ptr->getPointeeType(); Mode = 1; - DK = diag::ext_catch_incomplete_ptr; - IncompleteCatchIsInvalid = false; + DK = diag::err_catch_incomplete_ptr; } else if (const ReferenceType *Ref = BaseType->getAs<ReferenceType>()) { // For the purpose of error recovery, we treat rvalue refs like lvalue refs. BaseType = Ref->getPointeeType(); Mode = 2; - DK = diag::ext_catch_incomplete_ref; - IncompleteCatchIsInvalid = false; + DK = diag::err_catch_incomplete_ref; } if (!Invalid && (Mode == 0 || !BaseType->isVoidType()) && - !BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK) && - IncompleteCatchIsInvalid) + !BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK)) Invalid = true; if (!Invalid && !ExDeclType->isDependentType() && @@ -9490,7 +9714,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, // Only the non-fragile NeXT runtime currently supports C++ catches // of ObjC types, and no runtime supports catching ObjC types by value. - if (!Invalid && getLangOptions().ObjC1) { + if (!Invalid && getLangOpts().ObjC1) { QualType T = ExDeclType; if (const ReferenceType *RT = T->getAs<ReferenceType>()) T = RT->getPointeeType(); @@ -9499,7 +9723,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, Diag(Loc, diag::err_objc_object_catch); Invalid = true; } else if (T->isObjCObjectPointerType()) { - if (!getLangOptions().ObjCNonFragileABI) + if (!getLangOpts().ObjCNonFragileABI) Diag(Loc, diag::warn_objc_pointer_cxx_catch_fragile); } } @@ -9508,6 +9732,10 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, ExDeclType, TInfo, SC_None, SC_None); ExDecl->setExceptionVariable(true); + // In ARC, infer 'retaining' for variables of retainable type. + if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(ExDecl)) + Invalid = true; + if (!Invalid && !ExDeclType->isDependentType()) { if (const RecordType *recordType = ExDeclType->getAs<RecordType>()) { // C++ [except.handle]p16: @@ -9578,6 +9806,7 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { if (PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); + PrevDecl = 0; } } @@ -9588,7 +9817,7 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { } VarDecl *ExDecl = BuildExceptionDeclaration(S, TInfo, - D.getSourceRange().getBegin(), + D.getLocStart(), D.getIdentifierLoc(), D.getIdentifier()); if (Invalid) @@ -9611,17 +9840,24 @@ Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, StringLiteral *AssertMessage = cast<StringLiteral>(AssertMessageExpr_); if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent()) { - llvm::APSInt Value(32); - if (!AssertExpr->isIntegerConstantExpr(Value, Context)) { - Diag(StaticAssertLoc, - diag::err_static_assert_expression_is_not_constant) << - AssertExpr->getSourceRange(); + // In a static_assert-declaration, the constant-expression shall be a + // constant expression that can be contextually converted to bool. + ExprResult Converted = PerformContextuallyConvertToBool(AssertExpr); + if (Converted.isInvalid()) + return 0; + + llvm::APSInt Cond; + if (VerifyIntegerConstantExpression(Converted.get(), &Cond, + PDiag(diag::err_static_assert_expression_is_not_constant), + /*AllowFold=*/false).isInvalid()) return 0; - } - if (Value == 0) { + if (!Cond) { + llvm::SmallString<256> MsgBuffer; + llvm::raw_svector_ostream Msg(MsgBuffer); + AssertMessage->printPretty(Msg, Context, 0, getPrintingPolicy()); Diag(StaticAssertLoc, diag::err_static_assert_failed) - << AssertMessage->getString() << AssertExpr->getSourceRange(); + << Msg.str() << AssertExpr->getSourceRange(); } } @@ -9638,46 +9874,54 @@ Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, /// \brief Perform semantic analysis of the given friend type declaration. /// /// \returns A friend declaration that. -FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation FriendLoc, +FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation Loc, + SourceLocation FriendLoc, TypeSourceInfo *TSInfo) { assert(TSInfo && "NULL TypeSourceInfo for friend type declaration"); QualType T = TSInfo->getType(); SourceRange TypeRange = TSInfo->getTypeLoc().getLocalSourceRange(); - if (!getLangOptions().CPlusPlus0x) { - // C++03 [class.friend]p2: - // An elaborated-type-specifier shall be used in a friend declaration - // for a class.* - // - // * The class-key of the elaborated-type-specifier is required. - if (!ActiveTemplateInstantiations.empty()) { - // Do not complain about the form of friend template types during - // template instantiation; we will already have complained when the - // template was declared. - } else if (!T->isElaboratedTypeSpecifier()) { - // If we evaluated the type to a record type, suggest putting - // a tag in front. - if (const RecordType *RT = T->getAs<RecordType>()) { - RecordDecl *RD = RT->getDecl(); - - std::string InsertionText = std::string(" ") + RD->getKindName(); - - Diag(TypeRange.getBegin(), diag::ext_unelaborated_friend_type) - << (unsigned) RD->getTagKind() - << T - << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc), - InsertionText); - } else { - Diag(FriendLoc, diag::ext_nonclass_type_friend) - << T - << SourceRange(FriendLoc, TypeRange.getEnd()); - } - } else if (T->getAs<EnumType>()) { - Diag(FriendLoc, diag::ext_enum_friend) + // C++03 [class.friend]p2: + // An elaborated-type-specifier shall be used in a friend declaration + // for a class.* + // + // * The class-key of the elaborated-type-specifier is required. + if (!ActiveTemplateInstantiations.empty()) { + // Do not complain about the form of friend template types during + // template instantiation; we will already have complained when the + // template was declared. + } else if (!T->isElaboratedTypeSpecifier()) { + // If we evaluated the type to a record type, suggest putting + // a tag in front. + if (const RecordType *RT = T->getAs<RecordType>()) { + RecordDecl *RD = RT->getDecl(); + + std::string InsertionText = std::string(" ") + RD->getKindName(); + + Diag(TypeRange.getBegin(), + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_unelaborated_friend_type : + diag::ext_unelaborated_friend_type) + << (unsigned) RD->getTagKind() + << T + << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc), + InsertionText); + } else { + Diag(FriendLoc, + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_nonclass_type_friend : + diag::ext_nonclass_type_friend) << T << SourceRange(FriendLoc, TypeRange.getEnd()); } + } else if (T->getAs<EnumType>()) { + Diag(FriendLoc, + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_enum_friend : + diag::ext_enum_friend) + << T + << SourceRange(FriendLoc, TypeRange.getEnd()); } // C++0x [class.friend]p3: @@ -9688,7 +9932,7 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation FriendLoc, // FIXME: C++0x has some syntactic restrictions on friend type declarations // in [class.friend]p3 that we do not implement. - return FriendDecl::Create(Context, CurContext, FriendLoc, TSInfo, FriendLoc); + return FriendDecl::Create(Context, CurContext, Loc, TSInfo, FriendLoc); } /// Handle a friend tag declaration where the scope specifier was @@ -9732,8 +9976,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, if (Invalid) return 0; - assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?"); - bool isAllExplicitSpecializations = true; for (unsigned I = TempParamLists.size(); I-- > 0; ) { if (TempParamLists.get()[I]->size()) { @@ -9748,6 +9990,18 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, // about the template header and build an appropriate non-templated // friend. TODO: for source fidelity, remember the headers. if (isAllExplicitSpecializations) { + if (SS.isEmpty()) { + bool Owned = false; + bool IsDependent = false; + return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc, + Attr, AS_public, + /*ModulePrivateLoc=*/SourceLocation(), + MultiTemplateParamsArg(), Owned, IsDependent, + /*ScopedEnumKWLoc=*/SourceLocation(), + /*ScopedEnumUsesClassTag=*/false, + /*UnderlyingType=*/TypeResult()); + } + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); ElaboratedTypeKeyword Keyword = TypeWithKeyword::getKeywordForTagTypeKind(Kind); @@ -9759,12 +10013,12 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); if (isa<DependentNameType>(T)) { DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); - TL.setKeywordLoc(TagLoc); + TL.setElaboratedKeywordLoc(TagLoc); TL.setQualifierLoc(QualifierLoc); TL.setNameLoc(NameLoc); } else { ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc()); - TL.setKeywordLoc(TagLoc); + TL.setElaboratedKeywordLoc(TagLoc); TL.setQualifierLoc(QualifierLoc); cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(NameLoc); } @@ -9775,6 +10029,10 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, CurContext->addDecl(Friend); return Friend; } + + assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?"); + + // Handle the case of a templated-scope friend class. e.g. // template <class T> class A<T>::B; @@ -9783,7 +10041,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name); TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); - TL.setKeywordLoc(TagLoc); + TL.setElaboratedKeywordLoc(TagLoc); TL.setQualifierLoc(SS.getWithLocInContext(Context)); TL.setNameLoc(NameLoc); @@ -9815,7 +10073,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, /// template <> template <class T> friend class A<int>::B; Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, MultiTemplateParamsArg TempParams) { - SourceLocation Loc = DS.getSourceRange().getBegin(); + SourceLocation Loc = DS.getLocStart(); assert(DS.isFriendSpecified()); assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified); @@ -9871,7 +10129,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, TSI, DS.getFriendSpecLoc()); else - D = CheckFriendTypeDecl(DS.getFriendSpecLoc(), TSI); + D = CheckFriendTypeDecl(Loc, DS.getFriendSpecLoc(), TSI); if (!D) return 0; @@ -9977,7 +10235,7 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, // declarations should stop at the nearest enclosing namespace, // not that they should only consider the nearest enclosing // namespace. - while (DC->isRecord()) + while (DC->isRecord() || DC->isTransparentContext()) DC = DC->getParent(); LookupQualifiedName(Previous, DC); @@ -9996,15 +10254,17 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, // C++ [class.friend]p1: A friend of a class is a function or // class that is not a member of the class . . . - // C++0x changes this for both friend types and functions. + // C++11 changes this for both friend types and functions. // Most C++ 98 compilers do seem to give an error here, so // we do, too. - if (!Previous.empty() && DC->Equals(CurContext) - && !getLangOptions().CPlusPlus0x) - Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member); + if (!Previous.empty() && DC->Equals(CurContext)) + Diag(DS.getFriendSpecLoc(), + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_friend_is_member : + diag::err_friend_is_member); DCScope = getScopeForDeclContext(S, DC); - + // C++ [class.friend]p6: // A function can be defined in a friend declaration of a class if and // only if the class is a non-local class (9.8), the function name is @@ -10046,7 +10306,10 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, // C++ [class.friend]p1: A friend of a class is a function or // class that is not a member of the class . . . if (DC->Equals(CurContext)) - Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member); + Diag(DS.getFriendSpecLoc(), + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_friend_is_member : + diag::err_friend_is_member); if (D.isFunctionDefinition()) { // C++ [class.friend]p6: @@ -10093,6 +10356,15 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, } } + // FIXME: This is an egregious hack to cope with cases where the scope stack + // does not contain the declaration context, i.e., in an out-of-line + // definition of a class. + Scope FakeDCScope(S, Scope::DeclScope, Diags); + if (!DCScope) { + FakeDCScope.setEntity(DC); + DCScope = &FakeDCScope; + } + bool AddToScope = true; NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous, move(TemplateParams), AddToScope); @@ -10109,7 +10381,7 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, // lookup context is in lexical scope. if (!CurContext->isDependentContext()) { DC = DC->getRedeclContext(); - DC->makeDeclVisibleInContext(ND, /* Recoverable=*/ false); + DC->makeDeclVisibleInContext(ND); if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false); } @@ -10145,13 +10417,42 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { Diag(DelLoc, diag::err_deleted_non_function); return; } - if (const FunctionDecl *Prev = Fn->getPreviousDeclaration()) { + if (const FunctionDecl *Prev = Fn->getPreviousDecl()) { Diag(DelLoc, diag::err_deleted_decl_not_first); Diag(Prev->getLocation(), diag::note_previous_declaration); // If the declaration wasn't the first, we delete the function anyway for // recovery. } Fn->setDeletedAsWritten(); + + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Dcl); + if (!MD) + return; + + // A deleted special member function is trivial if the corresponding + // implicitly-declared function would have been. + switch (getSpecialMember(MD)) { + case CXXInvalid: + break; + case CXXDefaultConstructor: + MD->setTrivial(MD->getParent()->hasTrivialDefaultConstructor()); + break; + case CXXCopyConstructor: + MD->setTrivial(MD->getParent()->hasTrivialCopyConstructor()); + break; + case CXXMoveConstructor: + MD->setTrivial(MD->getParent()->hasTrivialMoveConstructor()); + break; + case CXXCopyAssignment: + MD->setTrivial(MD->getParent()->hasTrivialCopyAssignment()); + break; + case CXXMoveAssignment: + MD->setTrivial(MD->getParent()->hasTrivialMoveAssignment()); + break; + case CXXDestructor: + MD->setTrivial(MD->getParent()->hasTrivialDestructor()); + break; + } } void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { @@ -10245,7 +10546,7 @@ static void SearchForReturnInStmt(Sema &Self, Stmt *S) { if (!SubStmt) continue; if (isa<ReturnStmt>(SubStmt)) - Self.Diag(SubStmt->getSourceRange().getBegin(), + Self.Diag(SubStmt->getLocStart(), diag::err_return_in_constructor_handler); if (!isa<Expr>(SubStmt)) SearchForReturnInStmt(Self, SubStmt); @@ -10376,6 +10677,14 @@ bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) { return true; } +/// \brief Determine whether the given declaration is a static data member. +static bool isStaticDataMember(Decl *D) { + VarDecl *Var = dyn_cast_or_null<VarDecl>(D); + if (!Var) + return false; + + return Var->isStaticDataMember(); +} /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse /// an initializer for the out-of-line declaration 'Dcl'. The scope /// is a fresh scope pushed for just this purpose. @@ -10391,6 +10700,12 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) { // 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. + if (isStaticDataMember(D)) + PushExpressionEvaluationContext(PotentiallyEvaluated, D); } /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an @@ -10399,6 +10714,9 @@ 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 (isStaticDataMember(D)) + PopExpressionEvaluationContext(); + assert(D->isOutOfLine()); ExitDeclaratorContext(S); } @@ -10560,7 +10878,10 @@ bool Sema::DefineUsedVTables() { if (!KeyFunction || (KeyFunction->hasBody(KeyFunctionDef) && KeyFunctionDef->isInlined())) - Diag(Class->getLocation(), diag::warn_weak_vtable) << Class; + Diag(Class->getLocation(), Class->getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDefinition + ? diag::warn_weak_template_vtable : diag::warn_weak_vtable) + << Class; } } VTableUses.clear(); @@ -10577,7 +10898,7 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, // C++ [basic.def.odr]p2: // [...] A virtual member function is used if it is not pure. [...] if (MD->isVirtual() && !MD->isPure()) - MarkDeclarationReferenced(Loc, MD); + MarkFunctionReferenced(Loc, MD); } // Only classes that have virtual bases need a VTT. @@ -10597,7 +10918,7 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, /// SetIvarInitializers - This routine builds initialization ASTs for the /// Objective-C implementation whose ivars need be initialized. void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { - if (!getLangOptions().CPlusPlus) + if (!getLangOpts().CPlusPlus) return; if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) { SmallVector<ObjCIvarDecl*, 8> ivars; @@ -10637,7 +10958,7 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { ->getAs<RecordType>()) { CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl()); if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) { - MarkDeclarationReferenced(Field->getLocation(), Destructor); + MarkFunctionReferenced(Field->getLocation(), Destructor); CheckDestructorAccess(Field->getLocation(), Destructor, PDiag(diag::err_access_dtor_ivar) << Context.getBaseElementType(Field->getType())); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp index 62b4a7c..a942d49 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp @@ -21,8 +21,10 @@ #include "clang/AST/ExprObjC.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/ASTMutationListener.h" #include "clang/Basic/SourceManager.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Lex/Preprocessor.h" #include "llvm/ADT/DenseSet.h" using namespace clang; @@ -59,7 +61,7 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method, // It's okay for the result type to still be a forward declaration // if we're checking an interface declaration. - if (resultClass->isForwardDecl()) { + if (!resultClass->hasDefinition()) { if (receiverTypeIfCall.isNull() && !isa<ObjCImplementationDecl>(method->getDeclContext())) return false; @@ -156,7 +158,7 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, Diag(Overridden->getLocation(), diag::note_related_result_type_overridden); } - if (getLangOptions().ObjCAutoRefCount) { + if (getLangOpts().ObjCAutoRefCount) { if ((NewMethod->hasAttr<NSReturnsRetainedAttr>() != Overridden->hasAttr<NSReturnsRetainedAttr>())) { Diag(NewMethod->getLocation(), @@ -241,7 +243,8 @@ static void DiagnoseObjCImplementedDeprecations(Sema &S, if (ND && ND->isDeprecated()) { S.Diag(ImplLoc, diag::warn_deprecated_def) << select; if (select == 0) - S.Diag(ND->getLocation(), diag::note_method_declared_at); + S.Diag(ND->getLocation(), diag::note_method_declared_at) + << ND->getDeclName(); else S.Diag(ND->getLocation(), diag::note_previous_decl) << "class"; } @@ -297,7 +300,7 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { } // In ARC, disallow definition of retain/release/autorelease/retainCount - if (getLangOptions().ObjCAutoRefCount) { + if (getLangOpts().ObjCAutoRefCount) { switch (MDecl->getMethodFamily()) { case OMF_retain: case OMF_retainCount: @@ -336,16 +339,38 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { // Only do this if the current class actually has a superclass. if (IC->getSuperClass()) { ObjCShouldCallSuperDealloc = - !(Context.getLangOptions().ObjCAutoRefCount || - Context.getLangOptions().getGC() == LangOptions::GCOnly) && + !(Context.getLangOpts().ObjCAutoRefCount || + Context.getLangOpts().getGC() == LangOptions::GCOnly) && MDecl->getMethodFamily() == OMF_dealloc; ObjCShouldCallSuperFinalize = - Context.getLangOptions().getGC() != LangOptions::NonGC && + Context.getLangOpts().getGC() != LangOptions::NonGC && MDecl->getMethodFamily() == OMF_finalize; } } } +namespace { + +// Callback to only accept typo corrections that are Objective-C classes. +// If an ObjCInterfaceDecl* is given to the constructor, then the validation +// function will reject corrections to that class. +class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback { + public: + ObjCInterfaceValidatorCCC() : CurrentIDecl(0) {} + explicit ObjCInterfaceValidatorCCC(ObjCInterfaceDecl *IDecl) + : CurrentIDecl(IDecl) {} + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + ObjCInterfaceDecl *ID = candidate.getCorrectionDeclAs<ObjCInterfaceDecl>(); + return ID && !declaresSameEntity(ID, CurrentIDecl); + } + + private: + ObjCInterfaceDecl *CurrentIDecl; +}; + +} + Decl *Sema:: ActOnStartClassInterface(SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, SourceLocation ClassLoc, @@ -364,54 +389,44 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, Diag(PrevDecl->getLocation(), diag::note_previous_definition); } - ObjCInterfaceDecl* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); - if (IDecl) { - // Class already seen. Is it a forward declaration? - if (!IDecl->isForwardDecl()) { + // Create a declaration to describe this @interface. + ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); + ObjCInterfaceDecl *IDecl + = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName, + PrevIDecl, ClassLoc); + + if (PrevIDecl) { + // Class already seen. Was it a definition? + if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) { + Diag(AtInterfaceLoc, diag::err_duplicate_class_def) + << PrevIDecl->getDeclName(); + Diag(Def->getLocation(), diag::note_previous_definition); IDecl->setInvalidDecl(); - Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName(); - Diag(IDecl->getLocation(), diag::note_previous_definition); - - // Return the previous class interface. - // FIXME: don't leak the objects passed in! - return ActOnObjCContainerStartDefinition(IDecl); - } else { - IDecl->setLocation(ClassLoc); - IDecl->setForwardDecl(false); - IDecl->setAtStartLoc(AtInterfaceLoc); - // If the forward decl was in a PCH, we need to write it again in a - // dependent AST file. - IDecl->setChangedSinceDeserialization(true); - - // Since this ObjCInterfaceDecl was created by a forward declaration, - // we now add it to the DeclContext since it wasn't added before - // (see ActOnForwardClassDeclaration). - IDecl->setLexicalDeclContext(CurContext); - CurContext->addDecl(IDecl); - - if (AttrList) - ProcessDeclAttributeList(TUScope, IDecl, AttrList); } - } else { - IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, - ClassName, ClassLoc); - if (AttrList) - ProcessDeclAttributeList(TUScope, IDecl, AttrList); - - PushOnScopeChains(IDecl, TUScope); } + + if (AttrList) + ProcessDeclAttributeList(TUScope, IDecl, AttrList); + PushOnScopeChains(IDecl, TUScope); + // Start the definition of this class. If we're in a redefinition case, there + // may already be a definition, so we'll end up adding to it. + if (!IDecl->hasDefinition()) + IDecl->startDefinition(); + if (SuperName) { // Check if a different kind of symbol declared in this scope. PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc, LookupOrdinaryName); if (!PrevDecl) { - // Try to correct for a typo in the superclass name. - TypoCorrection Corrected = CorrectTypo( + // Try to correct for a typo in the superclass name without correcting + // to the class we're defining. + ObjCInterfaceValidatorCCC Validator(IDecl); + if (TypoCorrection Corrected = CorrectTypo( DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope, - NULL, NULL, false, CTC_NoKeywords); - if ((PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>())) { + NULL, Validator)) { + PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>(); Diag(SuperLoc, diag::err_undef_superclass_suggest) << SuperName << ClassName << PrevDecl->getDeclName(); Diag(PrevDecl->getLocation(), diag::note_previous_decl) @@ -419,10 +434,10 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, } } - if (PrevDecl == IDecl) { + if (declaresSameEntity(PrevDecl, IDecl)) { Diag(SuperLoc, diag::err_recursive_superclass) << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc); - IDecl->setLocEnd(ClassLoc); + IDecl->setEndOfDefinitionLoc(ClassLoc); } else { ObjCInterfaceDecl *SuperClassDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); @@ -458,27 +473,28 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, if (!SuperClassDecl) Diag(SuperLoc, diag::err_undef_superclass) << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc); - else if (SuperClassDecl->isForwardDecl()) { - Diag(SuperLoc, diag::err_forward_superclass) - << SuperClassDecl->getDeclName() << ClassName - << SourceRange(AtInterfaceLoc, ClassLoc); - Diag(SuperClassDecl->getLocation(), diag::note_forward_class); + else if (RequireCompleteType(SuperLoc, + Context.getObjCInterfaceType(SuperClassDecl), + PDiag(diag::err_forward_superclass) + << SuperClassDecl->getDeclName() + << ClassName + << SourceRange(AtInterfaceLoc, ClassLoc))) { SuperClassDecl = 0; } } IDecl->setSuperClass(SuperClassDecl); IDecl->setSuperClassLoc(SuperLoc); - IDecl->setLocEnd(SuperLoc); + IDecl->setEndOfDefinitionLoc(SuperLoc); } } else { // we have a root class. - IDecl->setLocEnd(ClassLoc); + IDecl->setEndOfDefinitionLoc(ClassLoc); } // Check then save referenced protocols. if (NumProtoRefs) { IDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, ProtoLocs, Context); - IDecl->setLocEnd(EndProtoLoc); + IDecl->setEndOfDefinitionLoc(EndProtoLoc); } CheckObjCDeclScope(IDecl); @@ -550,6 +566,10 @@ bool Sema::CheckForwardProtocolDeclarationForCircularDependency( Diag(PrevLoc, diag::note_previous_definition); res = true; } + + if (!PDecl->hasDefinition()) + continue; + if (CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc, PDecl->getLocation(), PDecl->getReferencedProtocols())) res = true; @@ -570,44 +590,52 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, bool err = false; // FIXME: Deal with AttrList. assert(ProtocolName && "Missing protocol identifier"); - ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolName, ProtocolLoc); - if (PDecl) { - // Protocol already seen. Better be a forward protocol declaration - if (!PDecl->isForwardDecl()) { - Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName; - Diag(PDecl->getLocation(), diag::note_previous_definition); - // Just return the protocol we already had. - // FIXME: don't leak the objects passed in! - return ActOnObjCContainerStartDefinition(PDecl); - } - ObjCList<ObjCProtocolDecl> PList; - PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context); - err = CheckForwardProtocolDeclarationForCircularDependency( - ProtocolName, ProtocolLoc, PDecl->getLocation(), PList); - - // Make sure the cached decl gets a valid start location. - PDecl->setAtStartLoc(AtProtoInterfaceLoc); - PDecl->setLocation(ProtocolLoc); - PDecl->setForwardDecl(false); - // Since this ObjCProtocolDecl was created by a forward declaration, - // we now add it to the DeclContext since it wasn't added before - PDecl->setLexicalDeclContext(CurContext); - CurContext->addDecl(PDecl); - // Repeat in dependent AST files. - PDecl->setChangedSinceDeserialization(true); + ObjCProtocolDecl *PrevDecl = LookupProtocol(ProtocolName, ProtocolLoc, + ForRedeclaration); + ObjCProtocolDecl *PDecl = 0; + if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : 0) { + // If we already have a definition, complain. + Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName; + Diag(Def->getLocation(), diag::note_previous_definition); + + // Create a new protocol that is completely distinct from previous + // declarations, and do not make this protocol available for name lookup. + // That way, we'll end up completely ignoring the duplicate. + // FIXME: Can we turn this into an error? + PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName, + ProtocolLoc, AtProtoInterfaceLoc, + /*PrevDecl=*/0); + PDecl->startDefinition(); } else { + if (PrevDecl) { + // Check for circular dependencies among protocol declarations. This can + // only happen if this protocol was forward-declared. + ObjCList<ObjCProtocolDecl> PList; + PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context); + err = CheckForwardProtocolDeclarationForCircularDependency( + ProtocolName, ProtocolLoc, PrevDecl->getLocation(), PList); + } + + // Create the new declaration. PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName, - ProtocolLoc, AtProtoInterfaceLoc); + ProtocolLoc, AtProtoInterfaceLoc, + /*PrevDecl=*/PrevDecl); + PushOnScopeChains(PDecl, TUScope); - PDecl->setForwardDecl(false); + PDecl->startDefinition(); } + if (AttrList) ProcessDeclAttributeList(TUScope, PDecl, AttrList); + + // Merge attributes from previous declarations. + if (PrevDecl) + mergeDeclAttributes(PDecl, PrevDecl); + if (!err && NumProtoRefs ) { /// Check then save referenced protocols. PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, ProtoLocs, Context); - PDecl->setLocEnd(EndProtoLoc); } CheckObjCDeclScope(PDecl); @@ -626,9 +654,10 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first, ProtocolId[i].second); if (!PDecl) { + DeclFilterCCC<ObjCProtocolDecl> Validator; TypoCorrection Corrected = CorrectTypo( DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second), - LookupObjCProtocolName, TUScope, NULL, NULL, false, CTC_NoKeywords); + LookupObjCProtocolName, TUScope, NULL, Validator); if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) { Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest) << ProtocolId[i].first << Corrected.getCorrection(); @@ -647,7 +676,7 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, // If this is a forward declaration and we are supposed to warn in this // case, do it. - if (WarnOnDeclarations && PDecl->isForwardDecl()) + if (WarnOnDeclarations && !PDecl->hasDefinition()) Diag(ProtocolId[i].second, diag::warn_undef_protocolref) << ProtocolId[i].first; Protocols.push_back(PDecl); @@ -684,40 +713,34 @@ void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, } /// ActOnForwardProtocolDeclaration - Handle @protocol foo; -Decl * +Sema::DeclGroupPtrTy Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, const IdentifierLocPair *IdentList, unsigned NumElts, AttributeList *attrList) { - SmallVector<ObjCProtocolDecl*, 32> Protocols; - SmallVector<SourceLocation, 8> ProtoLocs; - + SmallVector<Decl *, 8> DeclsInGroup; for (unsigned i = 0; i != NumElts; ++i) { IdentifierInfo *Ident = IdentList[i].first; - ObjCProtocolDecl *PDecl = LookupProtocol(Ident, IdentList[i].second); - bool isNew = false; - if (PDecl == 0) { // Not already seen? - PDecl = ObjCProtocolDecl::Create(Context, CurContext, Ident, - IdentList[i].second, AtProtocolLoc); - PushOnScopeChains(PDecl, TUScope, false); - isNew = true; - } - if (attrList) { + ObjCProtocolDecl *PrevDecl = LookupProtocol(Ident, IdentList[i].second, + ForRedeclaration); + ObjCProtocolDecl *PDecl + = ObjCProtocolDecl::Create(Context, CurContext, Ident, + IdentList[i].second, AtProtocolLoc, + PrevDecl); + + PushOnScopeChains(PDecl, TUScope); + CheckObjCDeclScope(PDecl); + + if (attrList) ProcessDeclAttributeList(TUScope, PDecl, attrList); - if (!isNew) - PDecl->setChangedSinceDeserialization(true); - } - Protocols.push_back(PDecl); - ProtoLocs.push_back(IdentList[i].second); + + if (PrevDecl) + mergeDeclAttributes(PDecl, PrevDecl); + + DeclsInGroup.push_back(PDecl); } - ObjCForwardProtocolDecl *PDecl = - ObjCForwardProtocolDecl::Create(Context, CurContext, AtProtocolLoc, - Protocols.data(), Protocols.size(), - ProtoLocs.data()); - CurContext->addDecl(PDecl); - CheckObjCDeclScope(PDecl); - return PDecl; + return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false); } Decl *Sema:: @@ -733,14 +756,21 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); /// Check that class of this category is already completely declared. - if (!IDecl || IDecl->isForwardDecl()) { + + if (!IDecl + || RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), + PDiag(diag::err_category_forward_interface) + << (CategoryName == 0))) { // 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. CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, ClassLoc, CategoryLoc, CategoryName,IDecl); CDecl->setInvalidDecl(); - Diag(ClassLoc, diag::err_undef_interface) << ClassName; + CurContext->addDecl(CDecl); + + if (!IDecl) + Diag(ClassLoc, diag::err_undef_interface) << ClassName; return ActOnObjCContainerStartDefinition(CDecl); } @@ -792,24 +822,28 @@ Decl *Sema::ActOnStartCategoryImplementation( IdentifierInfo *CatName, SourceLocation CatLoc) { ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); ObjCCategoryDecl *CatIDecl = 0; - if (IDecl) { + if (IDecl && IDecl->hasDefinition()) { CatIDecl = IDecl->FindCategoryDeclaration(CatName); if (!CatIDecl) { // Category @implementation with no corresponding @interface. // Create and install one. - CatIDecl = ObjCCategoryDecl::Create(Context, CurContext, SourceLocation(), - SourceLocation(), SourceLocation(), + CatIDecl = ObjCCategoryDecl::Create(Context, CurContext, AtCatImplLoc, + ClassLoc, CatLoc, CatName, IDecl); + CatIDecl->setImplicit(); } } ObjCCategoryImplDecl *CDecl = ObjCCategoryImplDecl::Create(Context, CurContext, CatName, IDecl, - ClassLoc, AtCatImplLoc); + ClassLoc, AtCatImplLoc, CatLoc); /// Check that class of this category is already completely declared. - if (!IDecl || IDecl->isForwardDecl()) { + if (!IDecl) { Diag(ClassLoc, diag::err_undef_interface) << ClassName; CDecl->setInvalidDecl(); + } else if (RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), + diag::err_undef_interface)) { + CDecl->setInvalidDecl(); } // FIXME: PushOnScopeChains? @@ -854,23 +888,21 @@ Decl *Sema::ActOnStartClassImplementation( Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; Diag(PrevDecl->getLocation(), diag::note_previous_definition); } else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) { - // If this is a forward declaration of an interface, warn. - if (IDecl->isForwardDecl()) { - Diag(ClassLoc, diag::warn_undef_interface) << ClassName; - IDecl = 0; - } + RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), + diag::warn_undef_interface); } else { // We did not find anything with the name ClassName; try to correct for // typos in the class name. - TypoCorrection Corrected = CorrectTypo( + ObjCInterfaceValidatorCCC Validator; + if (TypoCorrection Corrected = CorrectTypo( DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope, - NULL, NULL, false, CTC_NoKeywords); - if ((IDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>())) { + NULL, Validator)) { // Suggest the (potentially) correct interface name. However, put the // fix-it hint itself in a separate note, since changing the name in // the warning would make the fix-it change semantics.However, don't // provide a code-modification hint or use the typo name for recovery, // because this is just a warning. The program may actually be correct. + IDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>(); DeclarationName CorrectedName = Corrected.getCorrection(); Diag(ClassLoc, diag::warn_undef_interface_suggest) << ClassName << CorrectedName; @@ -894,10 +926,12 @@ Decl *Sema::ActOnStartClassImplementation( Diag(PrevDecl->getLocation(), diag::note_previous_definition); } else { SDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); + if (SDecl && !SDecl->hasDefinition()) + SDecl = 0; if (!SDecl) Diag(SuperClassLoc, diag::err_undef_superclass) << SuperClassname << ClassName; - else if (IDecl && IDecl->getSuperClass() != SDecl) { + else if (IDecl && !declaresSameEntity(IDecl->getSuperClass(), SDecl)) { // This implementation and its interface do not have the same // super class. Diag(SuperClassLoc, diag::err_conflicting_super_class) @@ -914,16 +948,24 @@ 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, ClassLoc, false, true); - IDecl->setSuperClass(SDecl); - IDecl->setLocEnd(ClassLoc); - + ClassName, /*PrevDecl=*/0, ClassLoc, + true); + IDecl->startDefinition(); + if (SDecl) { + IDecl->setSuperClass(SDecl); + IDecl->setSuperClassLoc(SuperClassLoc); + IDecl->setEndOfDefinitionLoc(SuperClassLoc); + } else { + IDecl->setEndOfDefinitionLoc(ClassLoc); + } + PushOnScopeChains(IDecl, TUScope); } else { // Mark the interface as being completed, even if it was just as // @class ....; // declaration; the user cannot reopen it. - IDecl->setForwardDecl(false); + if (!IDecl->hasDefinition()) + IDecl->startDefinition(); } ObjCImplementationDecl* IMPDecl = @@ -951,6 +993,25 @@ Decl *Sema::ActOnStartClassImplementation( return ActOnObjCContainerStartDefinition(IMPDecl); } +Sema::DeclGroupPtrTy +Sema::ActOnFinishObjCImplementation(Decl *ObjCImpDecl, ArrayRef<Decl *> Decls) { + SmallVector<Decl *, 64> DeclsInGroup; + DeclsInGroup.reserve(Decls.size() + 1); + + for (unsigned i = 0, e = Decls.size(); i != e; ++i) { + Decl *Dcl = Decls[i]; + if (!Dcl) + continue; + if (Dcl->getDeclContext()->isFileContext()) + Dcl->setTopLevelDeclInObjCContainer(); + DeclsInGroup.push_back(Dcl); + } + + DeclsInGroup.push_back(ObjCImpDecl); + + return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false); +} + void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, ObjCIvarDecl **ivars, unsigned numIvars, SourceLocation RBrace) { @@ -962,11 +1023,11 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, /// (legacy objective-c @implementation decl without an @interface decl). /// Add implementations's ivar to the synthesize class's ivar list. if (IDecl->isImplicitInterfaceDecl()) { - IDecl->setLocEnd(RBrace); + IDecl->setEndOfDefinitionLoc(RBrace); // Add ivar's to class's DeclContext. for (unsigned i = 0, e = numIvars; i != e; ++i) { ivars[i]->setLexicalDeclContext(ImpDecl); - IDecl->makeDeclVisibleInContext(ivars[i], false); + IDecl->makeDeclVisibleInContext(ivars[i]); ImpDecl->addDecl(ivars[i]); } @@ -990,7 +1051,7 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, } // Instance ivar to Implementation's DeclContext. ImplIvar->setLexicalDeclContext(ImpDecl); - IDecl->makeDeclVisibleInContext(ImplIvar, false); + IDecl->makeDeclVisibleInContext(ImplIvar); ImpDecl->addDecl(ImplIvar); } return; @@ -1329,7 +1390,7 @@ static bool checkMethodFamilyMismatch(Sema &S, ObjCMethodDecl *impl, void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl, ObjCMethodDecl *MethodDecl, bool IsProtocolMethodDecl) { - if (getLangOptions().ObjCAutoRefCount && + if (getLangOpts().ObjCAutoRefCount && checkMethodFamilyMismatch(*this, ImpMethodDecl, MethodDecl)) return; @@ -1410,7 +1471,8 @@ void Sema::WarnExactTypedMethods(ObjCMethodDecl *ImpMethodDecl, if (match) { Diag(ImpMethodDecl->getLocation(), diag::warn_category_method_impl_match); - Diag(MethodDecl->getLocation(), diag::note_method_declared_at); + Diag(MethodDecl->getLocation(), diag::note_method_declared_at) + << MethodDecl->getDeclName(); } } @@ -1428,16 +1490,14 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, const llvm::DenseSet<Selector> &InsMap, const llvm::DenseSet<Selector> &ClsMap, ObjCContainerDecl *CDecl) { - ObjCInterfaceDecl *IDecl; - if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) - IDecl = C->getClassInterface(); - else - IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl); + 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 (getLangOptions().NeXTRuntime) { + if (getLangOpts().NeXTRuntime) { // 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. @@ -1467,20 +1527,28 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, !method->isSynthesized() && !InsMap.count(method->getSelector()) && (!Super || !Super->lookupInstanceMethod(method->getSelector()))) { + // 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. + // This is because method will be implemented in the primary class + // or one of its super class implementation. + // Ugly, but necessary. Method declared in protcol might have // have been synthesized due to a property declared in the class which // uses the protocol. - ObjCMethodDecl *MethodInClass = - IDecl->lookupInstanceMethod(method->getSelector()); - if (!MethodInClass || !MethodInClass->isSynthesized()) { - unsigned DIAG = diag::warn_unimplemented_protocol_method; - if (Diags.getDiagnosticLevel(DIAG, ImpLoc) - != DiagnosticsEngine::Ignored) { - WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG); - Diag(method->getLocation(), diag::note_method_declared_at); - Diag(CDecl->getLocation(), diag::note_required_for_protocol_at) - << PDecl->getDeclName(); - } + if (ObjCMethodDecl *MethodInClass = + IDecl->lookupInstanceMethod(method->getSelector(), + true /*shallowCategoryLookup*/)) + if (C || MethodInClass->isSynthesized()) + continue; + unsigned DIAG = diag::warn_unimplemented_protocol_method; + if (Diags.getDiagnosticLevel(DIAG, ImpLoc) + != DiagnosticsEngine::Ignored) { + WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG); + Diag(method->getLocation(), diag::note_method_declared_at) + << method->getDeclName(); + Diag(CDecl->getLocation(), diag::note_required_for_protocol_at) + << PDecl->getDeclName(); } } } @@ -1492,11 +1560,16 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, if (method->getImplementationControl() != ObjCMethodDecl::Optional && !ClsMap.count(method->getSelector()) && (!Super || !Super->lookupClassMethod(method->getSelector()))) { + // See above comment for instance method lookups. + if (C && IDecl->lookupClassMethod(method->getSelector(), + true /*shallowCategoryLookup*/)) + continue; unsigned DIAG = diag::warn_unimplemented_protocol_method; if (Diags.getDiagnosticLevel(DIAG, ImpLoc) != DiagnosticsEngine::Ignored) { WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG); - Diag(method->getLocation(), diag::note_method_declared_at); + Diag(method->getLocation(), diag::note_method_declared_at) + << method->getDeclName(); Diag(IDecl->getLocation(), diag::note_required_for_protocol_at) << PDecl->getDeclName(); } @@ -1505,7 +1578,7 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, // 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, IDecl); + CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, CDecl); } /// MatchAllMethodDeclarations - Check methods declared in interface @@ -1519,7 +1592,7 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap, ObjCContainerDecl* CDecl, bool &IncompleteImpl, bool ImmediateClass, - bool WarnExactMatch) { + 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(), @@ -1541,12 +1614,12 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap, ObjCMethodDecl *MethodDecl = *I; // ImpMethodDecl may be null as in a @dynamic property. if (ImpMethodDecl) { - if (!WarnExactMatch) + if (!WarnCategoryMethodImpl) WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl, isa<ObjCProtocolDecl>(CDecl)); else if (!MethodDecl->isSynthesized()) WarnExactTypedMethods(ImpMethodDecl, MethodDecl, - isa<ObjCProtocolDecl>(CDecl)); + isa<ObjCProtocolDecl>(CDecl)); } } } @@ -1568,12 +1641,12 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap, assert(CDecl->getClassMethod((*I)->getSelector()) && "Expected to find the method through lookup as well"); ObjCMethodDecl *MethodDecl = *I; - if (!WarnExactMatch) + if (!WarnCategoryMethodImpl) WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl, isa<ObjCProtocolDecl>(CDecl)); else WarnExactTypedMethods(ImpMethodDecl, MethodDecl, - isa<ObjCProtocolDecl>(CDecl)); + isa<ObjCProtocolDecl>(CDecl)); } } @@ -1584,7 +1657,8 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap, MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, IMPDecl, const_cast<ObjCCategoryDecl *>(ClsExtDecl), - IncompleteImpl, false, WarnExactMatch); + IncompleteImpl, false, + WarnCategoryMethodImpl); // Check for any implementation of a methods declared in protocol. for (ObjCInterfaceDecl::all_protocol_iterator @@ -1592,11 +1666,12 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap, E = I->all_referenced_protocol_end(); PI != E; ++PI) MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, IMPDecl, - (*PI), IncompleteImpl, false, WarnExactMatch); + (*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 (!WarnExactMatch && I->getSuperClass()) + if (!WarnCategoryMethodImpl && I->getSuperClass()) MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, IMPDecl, I->getSuperClass(), IncompleteImpl, false); @@ -1633,7 +1708,8 @@ void Sema::CheckCategoryVsClassMethodMatches( bool IncompleteImpl = false; MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, CatIMPDecl, IDecl, - IncompleteImpl, false, true /*WarnExactMatch*/); + IncompleteImpl, false, + true /*WarnCategoryMethodImpl*/); } void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, @@ -1649,9 +1725,10 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, // 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 (isa<ObjCInterfaceDecl>(CDecl) && - !(LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCNonFragileABI2)) - DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap); + if (const ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) + if (!(LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCNonFragileABI2) || + IDecl->isObjCRequiresPropertyDefs()) + DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap); llvm::DenseSet<Selector> ClsMap; for (ObjCImplementationDecl::classmeth_iterator @@ -1738,37 +1815,36 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, // typedef NSObject < XCElementTogglerP > XCElementToggler; // @class XCElementToggler; // - // FIXME: Make an extension? + // Here we have chosen to ignore the forward class declaration + // with a warning. Since this is the implied behavior. TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(PrevDecl); if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) { Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i]; Diag(PrevDecl->getLocation(), diag::note_previous_definition); } else { // a forward class declaration matching a typedef name of a class refers - // to the underlying class. - if (const ObjCObjectType *OI = - TDD->getUnderlyingType()->getAs<ObjCObjectType>()) - PrevDecl = OI->getInterface(); + // to the underlying class. Just ignore the forward class with a warning + // as this will force the intended behavior which is to lookup the typedef + // name. + if (isa<ObjCObjectType>(TDD->getUnderlyingType())) { + Diag(AtClassLoc, diag::warn_forward_class_redefinition) << IdentList[i]; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + continue; + } } } - ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); - if (!IDecl) { // Not already seen? Make a forward decl. - IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc, - IdentList[i], IdentLocs[i], true); - - // Push the ObjCInterfaceDecl on the scope chain but do *not* add it to - // the current DeclContext. This prevents clients that walk DeclContext - // from seeing the imaginary ObjCInterfaceDecl until it is actually - // declared later (if at all). We also take care to explicitly make - // sure this declaration is visible for name lookup. - PushOnScopeChains(IDecl, TUScope, false); - CurContext->makeDeclVisibleInContext(IDecl, true); - } - ObjCClassDecl *CDecl = ObjCClassDecl::Create(Context, CurContext, AtClassLoc, - IDecl, IdentLocs[i]); - CurContext->addDecl(CDecl); - CheckObjCDeclScope(CDecl); - DeclsInGroup.push_back(CDecl); + + // Create a declaration to describe this forward declaration. + ObjCInterfaceDecl *PrevIDecl + = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); + ObjCInterfaceDecl *IDecl + = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc, + IdentList[i], PrevIDecl, IdentLocs[i]); + IDecl->setAtEndRange(IdentLocs[i]); + + PushOnScopeChains(IDecl, TUScope); + CheckObjCDeclScope(IDecl); + DeclsInGroup.push_back(IDecl); } return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false); @@ -1870,7 +1946,7 @@ bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *left, left->getResultType(), right->getResultType())) return false; - if (getLangOptions().ObjCAutoRefCount && + if (getLangOpts().ObjCAutoRefCount && (left->hasAttr<NSReturnsRetainedAttr>() != right->hasAttr<NSReturnsRetainedAttr>() || left->hasAttr<NSConsumesSelfAttr>() @@ -1887,76 +1963,81 @@ bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *left, if (!matchTypes(Context, strategy, lparm->getType(), rparm->getType())) return false; - if (getLangOptions().ObjCAutoRefCount && + if (getLangOpts().ObjCAutoRefCount && lparm->hasAttr<NSConsumedAttr>() != rparm->hasAttr<NSConsumedAttr>()) return false; } return true; } +void Sema::addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method) { + // If the list is empty, make it a singleton list. + if (List->Method == 0) { + List->Method = Method; + List->Next = 0; + return; + } + + // We've seen a method with this name, see if we have already seen this type + // signature. + ObjCMethodList *Previous = List; + for (; List; Previous = List, List = List->Next) { + if (!MatchTwoMethodDeclarations(Method, List->Method)) + continue; + + ObjCMethodDecl *PrevObjCMethod = List->Method; + + // Propagate the 'defined' bit. + if (Method->isDefined()) + PrevObjCMethod->setDefined(true); + + // If a method is deprecated, push it in the global pool. + // This is used for better diagnostics. + if (Method->isDeprecated()) { + if (!PrevObjCMethod->isDeprecated()) + List->Method = Method; + } + // If new method is unavailable, push it into global pool + // unless previous one is deprecated. + if (Method->isUnavailable()) { + if (PrevObjCMethod->getAvailability() < AR_Deprecated) + List->Method = Method; + } + + return; + } + + // 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->Next = new (Mem) ObjCMethodList(Method, 0); +} + /// \brief Read the contents of the method pool for a given selector from /// external storage. -/// -/// This routine should only be called once, when the method pool has no entry -/// for this selector. -Sema::GlobalMethodPool::iterator Sema::ReadMethodPool(Selector Sel) { +void Sema::ReadMethodPool(Selector Sel) { assert(ExternalSource && "We need an external AST source"); - assert(MethodPool.find(Sel) == MethodPool.end() && - "Selector data already loaded into the method pool"); - - // Read the method list from the external source. - GlobalMethods Methods = ExternalSource->ReadMethodPool(Sel); - - return MethodPool.insert(std::make_pair(Sel, Methods)).first; + ExternalSource->ReadMethodPool(Sel); } void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance) { + // Ignore methods of invalid containers. + if (cast<Decl>(Method->getDeclContext())->isInvalidDecl()) + return; + + if (ExternalSource) + ReadMethodPool(Method->getSelector()); + GlobalMethodPool::iterator Pos = MethodPool.find(Method->getSelector()); - if (Pos == MethodPool.end()) { - if (ExternalSource) - Pos = ReadMethodPool(Method->getSelector()); - else - Pos = MethodPool.insert(std::make_pair(Method->getSelector(), - GlobalMethods())).first; - } + if (Pos == MethodPool.end()) + Pos = MethodPool.insert(std::make_pair(Method->getSelector(), + GlobalMethods())).first; + Method->setDefined(impl); + ObjCMethodList &Entry = instance ? Pos->second.first : Pos->second.second; - if (Entry.Method == 0) { - // Haven't seen a method with this selector name yet - add it. - Entry.Method = Method; - Entry.Next = 0; - return; - } - - // We've seen a method with this name, see if we have already seen this type - // signature. - for (ObjCMethodList *List = &Entry; List; List = List->Next) { - bool match = MatchTwoMethodDeclarations(Method, List->Method); - - if (match) { - ObjCMethodDecl *PrevObjCMethod = List->Method; - PrevObjCMethod->setDefined(impl); - // If a method is deprecated, push it in the global pool. - // This is used for better diagnostics. - if (Method->isDeprecated()) { - if (!PrevObjCMethod->isDeprecated()) - List->Method = Method; - } - // If new method is unavailable, push it into global pool - // unless previous one is deprecated. - if (Method->isUnavailable()) { - if (PrevObjCMethod->getAvailability() < AR_Deprecated) - List->Method = Method; - } - return; - } - } - - // 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>(); - Entry.Next = new (Mem) ObjCMethodList(Method, Entry.Next); + addMethodToGlobalList(&Entry, Method); } /// Determines if this is an "acceptable" loose mismatch in the global @@ -1981,13 +2062,12 @@ static bool isAcceptableMethodMismatch(ObjCMethodDecl *chosen, ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, bool receiverIdOrClass, bool warn, bool instance) { + if (ExternalSource) + ReadMethodPool(Sel); + GlobalMethodPool::iterator Pos = MethodPool.find(Sel); - if (Pos == MethodPool.end()) { - if (ExternalSource) - Pos = ReadMethodPool(Sel); - else - return 0; - } + if (Pos == MethodPool.end()) + return 0; ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second; @@ -2014,14 +2094,14 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, // differences. In ARC, however, we also need to check for loose // mismatches, because most of them are errors. if (!strictSelectorMatch || - (issueDiagnostic && getLangOptions().ObjCAutoRefCount)) + (issueDiagnostic && getLangOpts().ObjCAutoRefCount)) for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) { // This checks if the methods differ in type mismatch. if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, MMS_loose) && !isAcceptableMethodMismatch(MethList.Method, Next->Method)) { issueDiagnostic = true; - if (getLangOptions().ObjCAutoRefCount) + if (getLangOpts().ObjCAutoRefCount) issueError = true; break; } @@ -2120,15 +2200,39 @@ void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, } } +Sema::ObjCContainerKind Sema::getObjCContainerKind() const { + switch (CurContext->getDeclKind()) { + case Decl::ObjCInterface: + return Sema::OCK_Interface; + case Decl::ObjCProtocol: + return Sema::OCK_Protocol; + case Decl::ObjCCategory: + if (dyn_cast<ObjCCategoryDecl>(CurContext)->IsClassExtension()) + return Sema::OCK_ClassExtension; + else + return Sema::OCK_Category; + case Decl::ObjCImplementation: + return Sema::OCK_Implementation; + case Decl::ObjCCategoryImpl: + return Sema::OCK_CategoryImplementation; + + default: + return Sema::OCK_None; + } +} + // Note: For class/category implemenations, allMethods/allProperties is // always null. -void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, - Decl **allMethods, unsigned allNum, - Decl **allProperties, unsigned pNum, - DeclGroupPtrTy *allTUVars, unsigned tuvNum) { +Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, + Decl **allMethods, unsigned allNum, + Decl **allProperties, unsigned pNum, + DeclGroupPtrTy *allTUVars, unsigned tuvNum) { + + if (getObjCContainerKind() == Sema::OCK_None) + return 0; + + assert(AtEnd.isValid() && "Invalid location for '@end'"); - if (!CurContext->isObjCContainer()) - return; ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext); Decl *ClassDecl = cast<Decl>(OCD); @@ -2137,15 +2241,6 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, || isa<ObjCProtocolDecl>(ClassDecl); bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl); - if (!isInterfaceDeclKind && AtEnd.isInvalid()) { - // FIXME: This is wrong. We shouldn't be pretending that there is - // an '@end' in the declaration. - SourceLocation L = ClassDecl->getLocation(); - AtEnd.setBegin(L); - AtEnd.setEnd(L); - Diag(L, diag::err_missing_atend); - } - // FIXME: Remove these and use the ObjCContainerDecl/DeclContext. llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap; llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap; @@ -2167,8 +2262,14 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, Diag(PrevMethod->getLocation(), diag::note_previous_declaration); Method->setInvalidDecl(); } else { - if (PrevMethod) + if (PrevMethod) { Method->setAsRedeclaration(PrevMethod); + if (!Context.getSourceManager().isInSystemHeader( + Method->getLocation())) + Diag(Method->getLocation(), diag::warn_duplicate_method_decl) + << Method->getDeclName(); + Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + } InsMap[Method->getSelector()] = Method; /// The following allows us to typecheck messages to "id". AddInstanceMethodToGlobalPool(Method); @@ -2188,8 +2289,14 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, Diag(PrevMethod->getLocation(), diag::note_previous_declaration); Method->setInvalidDecl(); } else { - if (PrevMethod) + if (PrevMethod) { Method->setAsRedeclaration(PrevMethod); + if (!Context.getSourceManager().isInSystemHeader( + Method->getLocation())) + Diag(Method->getLocation(), diag::warn_duplicate_method_decl) + << Method->getDeclName(); + Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + } ClsMap[Method->getSelector()] = Method; /// The following allows us to typecheck messages to "Class". AddFactoryMethodToGlobalPool(Method); @@ -2265,11 +2372,39 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, AtomicPropertySetterGetterRules(IC, IDecl); DiagnoseOwningPropertyGetterSynthesis(IC); - if (LangOpts.ObjCNonFragileABI2) + bool HasRootClassAttr = IDecl->hasAttr<ObjCRootClassAttr>(); + if (IDecl->getSuperClass() == NULL) { + // 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)); + Diag(DeclLoc, diag::warn_objc_root_class_missing) + << IDecl->getIdentifier(); + // See if NSObject is in the current scope, and if it is, suggest + // adding " : NSObject " to the class declaration. + NamedDecl *IF = LookupSingleName(TUScope, + NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject), + DeclLoc, LookupOrdinaryName); + ObjCInterfaceDecl *NSObjectDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + if (NSObjectDecl && NSObjectDecl->getDefinition()) { + Diag(SuperClassLoc, diag::note_objc_needs_superclass) + << FixItHint::CreateInsertion(SuperClassLoc, " : NSObject "); + } else { + Diag(SuperClassLoc, diag::note_objc_needs_superclass); + } + } + } else if (HasRootClassAttr) { + // Complain that only root classes may have this attribute. + Diag(IDecl->getLocation(), diag::err_objc_root_class_subclass); + } + + if (LangOpts.ObjCNonFragileABI2) { while (IDecl->getSuperClass()) { DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass()); IDecl = IDecl->getSuperClass(); } + } } SetIvarInitializers(IC); } else if (ObjCCategoryImplDecl* CatImplClass = @@ -2300,6 +2435,15 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, } } ActOnObjCContainerFinishDefinition(); + + for (unsigned i = 0; i != tuvNum; i++) { + DeclGroupRef DG = allTUVars[i].getAsVal<DeclGroupRef>(); + for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) + (*I)->setTopLevelDeclInObjCContainer(); + Consumer.HandleTopLevelDeclInObjCContainer(DG); + } + + return ClassDecl; } @@ -2311,13 +2455,36 @@ CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) { } static inline -bool containsInvalidMethodImplAttribute(const AttrVec &A) { - // The 'ibaction' attribute is allowed on method definitions because of - // how the IBAction macro is used on both method declarations and definitions. - // If the method definitions contains any other attributes, return true. - for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i) - if ((*i)->getKind() != attr::IBAction) +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 + if (!IMD->hasAttrs()) + return true; + + const AttrVec &D = IMD->getAttrs(); + if (D.size() != A.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) { + 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; } @@ -2352,7 +2519,7 @@ CheckRelatedResultTypeCompatibility(Sema &S, ObjCMethodDecl *Method, if (ObjCInterfaceDecl *ResultClass = ResultObjectType->getInterfaceDecl()) { // - it is the same as the method's class type, or - if (CurrentClass == ResultClass) + if (declaresSameEntity(CurrentClass, ResultClass)) return RTC_Compatible; // - it is a superclass of the method's class type @@ -2373,10 +2540,11 @@ namespace { /// A helper class for searching for methods which a particular method /// overrides. class OverrideSearch { +public: Sema &S; ObjCMethodDecl *Method; - llvm::SmallPtrSet<ObjCContainerDecl*, 8> Searched; - llvm::SmallPtrSet<ObjCMethodDecl*, 8> Overridden; + llvm::SmallPtrSet<ObjCContainerDecl*, 128> Searched; + llvm::SmallPtrSet<ObjCMethodDecl*, 4> Overridden; bool Recursive; public: @@ -2388,7 +2556,11 @@ public: Sema::GlobalMethodPool::iterator it = S.MethodPool.find(selector); if (it == S.MethodPool.end()) { if (!S.ExternalSource) return; - it = S.ReadMethodPool(selector); + S.ReadMethodPool(selector); + + it = S.MethodPool.find(selector); + if (it == S.MethodPool.end()) + return; } ObjCMethodList &list = method->isInstanceMethod() ? it->second.first : it->second.second; @@ -2404,7 +2576,7 @@ public: searchFromContainer(container); } - typedef llvm::SmallPtrSet<ObjCMethodDecl*,8>::iterator iterator; + typedef llvm::SmallPtrSet<ObjCMethodDecl*, 128>::iterator iterator; iterator begin() const { return Overridden.begin(); } iterator end() const { return Overridden.end(); } @@ -2426,6 +2598,9 @@ private: } void searchFrom(ObjCProtocolDecl *protocol) { + if (!protocol->hasDefinition()) + return; + // A method in a protocol declaration overrides declarations from // referenced ("parent") protocols. search(protocol->getReferencedProtocols()); @@ -2453,7 +2628,9 @@ private: void searchFrom(ObjCInterfaceDecl *iface) { // A method in a class declaration overrides declarations from - + if (!iface->hasDefinition()) + return; + // - categories, for (ObjCCategoryDecl *category = iface->getCategoryList(); category; category = category->getNextClassCategory()) @@ -2606,6 +2783,10 @@ Decl *Sema::ActOnMethodDeclaration( // Apply the attributes to the parameter. ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs); + if (Param->hasAttr<BlocksAttr>()) { + Diag(Param->getLocation(), diag::err_block_on_nonlocal); + Param->setInvalidDecl(); + } S->AddDecl(Param); IdResolver.AddDecl(Param); @@ -2649,9 +2830,19 @@ Decl *Sema::ActOnMethodDeclaration( ImpDecl->addClassMethod(ObjCMethod); } + ObjCMethodDecl *IMD = 0; + if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface()) + IMD = IDecl->lookupMethod(ObjCMethod->getSelector(), + ObjCMethod->isInstanceMethod()); if (ObjCMethod->hasAttrs() && - containsInvalidMethodImplAttribute(ObjCMethod->getAttrs())) - Diag(EndLoc, diag::warn_attribute_method_def); + 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->getDeclName(); + } + } } else { cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod); } @@ -2701,7 +2892,7 @@ Decl *Sema::ActOnMethodDeclaration( } bool ARCError = false; - if (getLangOptions().ObjCAutoRefCount) + if (getLangOpts().ObjCAutoRefCount) ARCError = CheckARCMethodDecl(*this, ObjCMethod); // Infer the related result type when possible. @@ -2741,13 +2932,15 @@ Decl *Sema::ActOnMethodDeclaration( } bool Sema::CheckObjCDeclScope(Decl *D) { - if (isa<TranslationUnitDecl>(CurContext->getRedeclContext())) - return false; // Following is also an error. But it is caused by a missing @end // and diagnostic is issued elsewhere. - if (isa<ObjCContainerDecl>(CurContext->getRedeclContext())) { + if (isa<ObjCContainerDecl>(CurContext->getRedeclContext())) + return false; + + // If we switched context to translation unit while we are still lexically in + // an objc container, it means the parser missed emitting an error. + if (isa<TranslationUnitDecl>(getCurLexicalContext()->getRedeclContext())) return false; - } Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope); D->setInvalidDecl(); @@ -2790,7 +2983,7 @@ void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, for (SmallVectorImpl<Decl*>::iterator D = Decls.begin(); D != Decls.end(); ++D) { FieldDecl *FD = cast<FieldDecl>(*D); - if (getLangOptions().CPlusPlus) + if (getLangOpts().CPlusPlus) PushOnScopeChains(cast<FieldDecl>(FD), S); else if (RecordDecl *Record = dyn_cast<RecordDecl>(TagD)) Record->addDecl(FD); @@ -2830,6 +3023,10 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T, T, TInfo, SC_None, SC_None); New->setExceptionVariable(true); + // In ARC, infer 'retaining' for variables of retainable type. + if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(New)) + Invalid = true; + if (Invalid) New->setInvalidDecl(); return New; @@ -2855,7 +3052,7 @@ Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { // Check that there are no default arguments inside the type of this // exception object (C++ only). - if (getLangOptions().CPlusPlus) + if (getLangOpts().CPlusPlus) CheckExtraCXXDefaultArguments(D); TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp index 92af2d9..42221f8 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp @@ -20,6 +20,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" namespace clang { @@ -101,7 +102,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { bool MissingExceptionSpecification = false; bool MissingEmptyExceptionSpecification = false; unsigned DiagID = diag::err_mismatched_exception_spec; - if (getLangOptions().MicrosoftExt) + if (getLangOpts().MicrosoftExt) DiagID = diag::warn_mismatched_exception_spec; if (!CheckEquivalentExceptionSpec(PDiag(DiagID), @@ -170,7 +171,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { // If exceptions are disabled, suppress the warning about missing // exception specifications for new and delete operators. - if (!getLangOptions().CXXExceptions) { + if (!getLangOpts().CXXExceptions) { switch (New->getDeclName().getCXXOverloadedOperator()) { case OO_New: case OO_Array_New: @@ -186,7 +187,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { } // Warn about the lack of exception specification. - llvm::SmallString<128> ExceptionSpecString; + SmallString<128> ExceptionSpecString; llvm::raw_svector_ostream OS(ExceptionSpecString); switch (OldProto->getExceptionSpecType()) { case EST_DynamicNone: @@ -264,7 +265,7 @@ bool Sema::CheckEquivalentExceptionSpec( const FunctionProtoType *Old, SourceLocation OldLoc, const FunctionProtoType *New, SourceLocation NewLoc) { unsigned DiagID = diag::err_mismatched_exception_spec; - if (getLangOptions().MicrosoftExt) + if (getLangOpts().MicrosoftExt) DiagID = diag::warn_mismatched_exception_spec; return CheckEquivalentExceptionSpec( PDiag(DiagID), @@ -285,7 +286,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, bool AllowNoexceptAllMatchWithNoSpec, bool IsOperatorNew) { // Just completely ignore this under -fno-exceptions. - if (!getLangOptions().CXXExceptions) + if (!getLangOpts().CXXExceptions) return false; if (MissingExceptionSpecification) @@ -379,7 +380,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, // As a special compatibility feature, under C++0x we accept no spec and // throw(std::bad_alloc) as equivalent for operator new and operator new[]. // This is because the implicit declaration changed, but old code would break. - if (getLangOptions().CPlusPlus0x && IsOperatorNew) { + if (getLangOpts().CPlusPlus0x && IsOperatorNew) { const FunctionProtoType *WithExceptions = 0; if (OldEST == EST_None && NewEST == EST_Dynamic) WithExceptions = New; @@ -473,7 +474,7 @@ bool Sema::CheckExceptionSpecSubset( const FunctionProtoType *Subset, SourceLocation SubLoc) { // Just auto-succeed under -fno-exceptions. - if (!getLangOptions().CXXExceptions) + if (!getLangOpts().CXXExceptions) return false; // FIXME: As usual, we could be more specific in our error messages, but @@ -611,10 +612,8 @@ bool Sema::CheckExceptionSpecSubset( case AR_inaccessible: continue; case AR_dependent: llvm_unreachable("access check dependent for unprivileged context"); - break; case AR_delayed: llvm_unreachable("access check delayed in non-declaration"); - break; } Contained = true; @@ -703,7 +702,7 @@ bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, const CXXMethodDecl *Old) { - if (getLangOptions().CPlusPlus0x && isa<CXXDestructorDecl>(New)) { + if (getLangOpts().CPlusPlus0x && isa<CXXDestructorDecl>(New)) { // Don't check uninstantiated template destructors at all. We can only // synthesize correct specs after the template is instantiated. if (New->getParent()->isDependentType()) @@ -717,7 +716,7 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, } } unsigned DiagID = diag::err_override_exception_spec; - if (getLangOptions().MicrosoftExt) + if (getLangOpts().MicrosoftExt) DiagID = diag::warn_override_exception_spec; return CheckExceptionSpecSubset(PDiag(DiagID), PDiag(diag::note_overridden_virtual_function), diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp index 170097c..0d0f2f5 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -12,10 +12,13 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/ScopeInfo.h" #include "clang/Sema/AnalysisBasedWarnings.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" @@ -38,6 +41,7 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/SemaFixItUtils.h" #include "clang/Sema/Template.h" +#include "TreeTransform.h" using namespace clang; using namespace sema; @@ -53,6 +57,12 @@ bool Sema::CanUseDecl(NamedDecl *D) { if (FD->isDeleted()) return false; } + + // See if this function is unavailable. + if (D->getAvailability() == AR_Unavailable && + cast<Decl>(CurContext)->getAvailability() != AR_Unavailable) + return false; + return true; } @@ -62,6 +72,13 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, // See if this declaration is unavailable or deprecated. std::string Message; AvailabilityResult Result = D->getAvailability(&Message); + if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) + if (Result == AR_Available) { + const DeclContext *DC = ECD->getDeclContext(); + if (const EnumDecl *TheEnumDecl = dyn_cast<EnumDecl>(DC)) + Result = TheEnumDecl->getAvailability(&Message); + } + switch (Result) { case AR_Available: case AR_NotYetIntroduced: @@ -91,6 +108,28 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, return Result; } +/// \brief Emit a note explaining that this function is deleted or unavailable. +void Sema::NoteDeletedFunction(FunctionDecl *Decl) { + CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Decl); + + if (Method && Method->isDeleted() && !Method->isDeletedAsWritten()) { + // If the method was explicitly defaulted, point at that declaration. + if (!Method->isImplicit()) + Diag(Decl->getLocation(), diag::note_implicitly_deleted); + + // Try to diagnose why this special member function was implicitly + // deleted. This might fail, if that reason no longer applies. + CXXSpecialMember CSM = getSpecialMember(Method); + if (CSM != CXXInvalid) + ShouldDeleteSpecialMember(Method, CSM, /*Diagnose=*/true); + + return; + } + + Diag(Decl->getLocation(), diag::note_unavailable_here) + << 1 << Decl->isDeleted(); +} + /// \brief Determine whether the use of this declaration is valid, and /// emit any corresponding diagnostics. /// @@ -105,7 +144,7 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, /// bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, const ObjCInterfaceDecl *UnknownObjCClass) { - if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) { + if (getLangOpts().CPlusPlus && isa<FunctionDecl>(D)) { // If there were any diagnostics suppressed by template argument deduction, // emit them now. llvm::DenseMap<Decl *, SmallVector<PartialDiagnosticAt, 1> >::iterator @@ -134,26 +173,15 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (FD->isDeleted()) { Diag(Loc, diag::err_deleted_function_use); - Diag(D->getLocation(), diag::note_unavailable_here) << 1 << true; + NoteDeletedFunction(FD); return true; } } - AvailabilityResult Result = - DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass); + DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass); // Warn if this is used but marked unused. if (D->hasAttr<UnusedAttr>()) Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName(); - // For available enumerator, it will become unavailable/deprecated - // if its enum declaration is as such. - if (Result == AR_Available) - if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) { - const DeclContext *DC = ECD->getDeclContext(); - if (const EnumDecl *TheEnumDecl = dyn_cast<EnumDecl>(DC)) - DiagnoseAvailabilityOfDecl(*this, - const_cast< EnumDecl *>(TheEnumDecl), - Loc, UnknownObjCClass); - } return false; } @@ -243,17 +271,7 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, Expr *sentinelExpr = args[numArgs - numArgsAfterSentinel - 1]; if (!sentinelExpr) return; if (sentinelExpr->isValueDependent()) return; - - // nullptr_t is always treated as null. - if (sentinelExpr->getType()->isNullPtrType()) return; - - if (sentinelExpr->getType()->isAnyPointerType() && - sentinelExpr->IgnoreParenCasts()->isNullPointerConstant(Context, - Expr::NPC_ValueDependentIsNull)) - return; - - // Unfortunately, __null has type 'int'. - if (isa<GNUNullExpr>(sentinelExpr)) return; + if (Context.isSentinelNullExpr(sentinelExpr)) return; // Pick a reasonable string to insert. Optimistically use 'nil' or // 'NULL' if those are actually defined in the context. Only use @@ -314,7 +332,7 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) { // An lvalue or rvalue of type "array of N T" or "array of unknown bound of // T" can be converted to an rvalue of type "pointer to T". // - if (getLangOptions().C99 || getLangOptions().CPlusPlus || E->isLValue()) + if (getLangOpts().C99 || getLangOpts().CPlusPlus || E->isLValue()) E = ImpCastExprToType(E, Context.getArrayDecayedType(Ty), CK_ArrayToPointerDecay).take(); } @@ -356,23 +374,9 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { QualType T = E->getType(); assert(!T.isNull() && "r-value conversion on typeless expression?"); - // We can't do lvalue-to-rvalue on atomics yet. - if (T->getAs<AtomicType>()) - return Owned(E); - - // Create a load out of an ObjCProperty l-value, if necessary. - if (E->getObjectKind() == OK_ObjCProperty) { - ExprResult Res = ConvertPropertyForRValue(E); - if (Res.isInvalid()) - return Owned(E); - E = Res.take(); - if (!E->isGLValue()) - return Owned(E); - } - // We don't want to throw lvalue-to-rvalue casts on top of // expressions of certain types in C++. - if (getLangOptions().CPlusPlus && + if (getLangOpts().CPlusPlus && (E->getType() == Context.OverloadTy || T->isDependentType() || T->isRecordType())) @@ -400,9 +404,20 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { if (T.hasQualifiers()) T = T.getUnqualifiedType(); + UpdateMarkingForLValueToRValue(E); + ExprResult Res = Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, E, 0, 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)); + } + return Res; } @@ -495,7 +510,7 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) { // is a prvalue for the temporary. // FIXME: add some way to gate this entire thing for correctness in // potentially potentially evaluated contexts. - if (getLangOptions().CPlusPlus && E->isGLValue() && + if (getLangOpts().CPlusPlus && E->isGLValue() && ExprEvalContexts.back().Context != Unevaluated) { ExprResult Temp = PerformCopyInitialization( InitializedEntity::InitializeTemporary(E->getType()), @@ -514,11 +529,23 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) { /// interfaces passed by value. ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, FunctionDecl *FDecl) { - ExprResult ExprRes = CheckPlaceholderExpr(E); - if (ExprRes.isInvalid()) - return ExprError(); + if (const BuiltinType *PlaceholderTy = E->getType()->getAsPlaceholderType()) { + // Strip the unbridged-cast placeholder expression off, if applicable. + if (PlaceholderTy->getKind() == BuiltinType::ARCUnbridgedCast && + (CT == VariadicMethod || + (FDecl && FDecl->hasAttr<CFAuditedTransferAttr>()))) { + E = stripARCUnbridgedCast(E); + + // Otherwise, do normal placeholder checking. + } else { + ExprResult ExprRes = CheckPlaceholderExpr(E); + if (ExprRes.isInvalid()) + return ExprError(); + E = ExprRes.take(); + } + } - ExprRes = DefaultArgumentPromotion(E); + ExprResult ExprRes = DefaultArgumentPromotion(E); if (ExprRes.isInvalid()) return ExprError(); E = ExprRes.take(); @@ -540,17 +567,21 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, // or a non-trivial destructor, with no corresponding parameter, // is conditionally-supported with implementation-defined semantics. bool TrivialEnough = false; - if (getLangOptions().CPlusPlus0x && !E->getType()->isDependentType()) { + if (getLangOpts().CPlusPlus0x && !E->getType()->isDependentType()) { if (CXXRecordDecl *Record = E->getType()->getAsCXXRecordDecl()) { if (Record->hasTrivialCopyConstructor() && Record->hasTrivialMoveConstructor() && - Record->hasTrivialDestructor()) + Record->hasTrivialDestructor()) { + DiagRuntimeBehavior(E->getLocStart(), 0, + PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg) + << E->getType() << CT); TrivialEnough = true; + } } } if (!TrivialEnough && - getLangOptions().ObjCAutoRefCount && + getLangOpts().ObjCAutoRefCount && E->getType()->isObjCLifetimeType()) TrivialEnough = true; @@ -558,14 +589,16 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, // Nothing to diagnose. This is okay. } else if (DiagRuntimeBehavior(E->getLocStart(), 0, PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) - << getLangOptions().CPlusPlus0x << E->getType() + << getLangOpts().CPlusPlus0x << E->getType() << CT)) { // Turn this into a trap. CXXScopeSpec SS; + SourceLocation TemplateKWLoc; UnqualifiedId Name; Name.setIdentifier(PP.getIdentifierInfo("__builtin_trap"), E->getLocStart()); - ExprResult TrapFn = ActOnIdExpression(TUScope, SS, Name, true, false); + ExprResult TrapFn = ActOnIdExpression(TUScope, SS, TemplateKWLoc, Name, + true, false); if (TrapFn.isInvalid()) return ExprError(); @@ -581,6 +614,11 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, E = Comma.get(); } } + // c++ rules are enforced elsewhere. + if (!getLangOpts().CPlusPlus && + RequireCompleteType(E->getExprLoc(), E->getType(), + diag::err_call_incomplete_argument)) + return ExprError(); return Owned(E); } @@ -811,14 +849,21 @@ static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS, if (LHSComplexInt) { // int -> _Complex int + // FIXME: This needs to take integer ranks into account + RHS = S.ImpCastExprToType(RHS.take(), LHSComplexInt->getElementType(), + CK_IntegralCast); RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralRealToComplex); return LHSType; } assert(RHSComplexInt); // int -> _Complex int - if (!IsCompAssign) + // FIXME: This needs to take integer ranks into account + if (!IsCompAssign) { + LHS = S.ImpCastExprToType(LHS.take(), RHSComplexInt->getElementType(), + CK_IntegralCast); LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralRealToComplex); + } return RHSType; } @@ -999,7 +1044,7 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, if (Types[i]->getType()->isDependentType()) { IsResultDependent = true; } else { - // C1X 6.5.1.1p2 "The type name in a generic association shall specify a + // C11 6.5.1.1p2 "The type name in a generic association shall specify a // complete object type other than a variably modified type." unsigned D = 0; if (Types[i]->getType()->isIncompleteType()) @@ -1016,7 +1061,7 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, TypeErrorFound = true; } - // C1X 6.5.1.1p2 "No two generic associations in the same generic + // C11 6.5.1.1p2 "No two generic associations in the same generic // selection shall specify compatible types." for (unsigned j = i+1; j < NumAssocs; ++j) if (Types[j] && !Types[j]->getType()->isDependentType() && @@ -1057,7 +1102,7 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, CompatIndices.push_back(i); } - // C1X 6.5.1.1p2 "The controlling expression of a generic selection shall have + // C11 6.5.1.1p2 "The controlling expression of a generic selection shall have // type compatible with at most one of the types named in its generic // association list." if (CompatIndices.size() > 1) { @@ -1077,7 +1122,7 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, return ExprError(); } - // C1X 6.5.1.1p2 "If a generic selection has no default generic association, + // C11 6.5.1.1p2 "If a generic selection has no default generic association, // its controlling expression shall have type compatible with exactly one of // the types named in its generic association list." if (DefaultIndex == -1U && CompatIndices.size() == 0) { @@ -1089,7 +1134,7 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, return ExprError(); } - // C1X 6.5.1.1p3 "If a generic selection has a generic association with a + // C11 6.5.1.1p3 "If a generic selection has a generic association with a // type name that is compatible with the type of the controlling expression, // then the result expression of the generic selection is the expression // in that generic association. Otherwise, the result expression of the @@ -1104,6 +1149,43 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, ResultIndex)); } +/// getUDSuffixLoc - Create a SourceLocation for a ud-suffix, given the +/// location of the token and the offset of the ud-suffix within it. +static SourceLocation getUDSuffixLoc(Sema &S, SourceLocation TokLoc, + unsigned Offset) { + return Lexer::AdvanceToTokenCharacter(TokLoc, Offset, S.getSourceManager(), + S.getLangOpts()); +} + +/// BuildCookedLiteralOperatorCall - A user-defined literal was found. Look up +/// the corresponding cooked (non-raw) literal operator, and build a call to it. +static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope, + IdentifierInfo *UDSuffix, + SourceLocation UDSuffixLoc, + ArrayRef<Expr*> Args, + SourceLocation LitEndLoc) { + assert(Args.size() <= 2 && "too many arguments for literal operator"); + + QualType ArgTy[2]; + for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) { + ArgTy[ArgIdx] = Args[ArgIdx]->getType(); + if (ArgTy[ArgIdx]->isArrayType()) + ArgTy[ArgIdx] = S.Context.getArrayDecayedType(ArgTy[ArgIdx]); + } + + DeclarationName OpName = + S.Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix); + DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc); + OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc); + + LookupResult R(S, OpName, UDSuffixLoc, Sema::LookupOrdinaryName); + if (S.LookupLiteralOperator(Scope, R, llvm::makeArrayRef(ArgTy, Args.size()), + /*AllowRawAndTemplate*/false) == Sema::LOLR_Error) + return ExprError(); + + return S.BuildLiteralOperatorCall(R, OpNameInfo, Args, LitEndLoc); +} + /// ActOnStringLiteral - The specified tokens were lexed as pasted string /// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string /// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from @@ -1111,7 +1193,8 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, /// string. /// ExprResult -Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { +Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks, + Scope *UDLScope) { assert(NumStringToks && "Must have at least one string!"); StringLiteralParser Literal(StringToks, NumStringToks, PP); @@ -1129,7 +1212,7 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { StrTy = Context.Char16Ty; else if (Literal.isUTF32()) StrTy = Context.Char32Ty; - else if (Literal.Pascal) + else if (Literal.isPascal()) StrTy = Context.UnsignedCharTy; StringLiteral::StringKind Kind = StringLiteral::Ascii; @@ -1143,7 +1226,7 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { Kind = StringLiteral::UTF32; // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). - if (getLangOptions().CPlusPlus || getLangOptions().ConstStrings) + if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings) StrTy.addConst(); // Get an array type for the string, according to C99 6.4.5. This includes @@ -1154,243 +1237,32 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { ArrayType::Normal, 0); // Pass &StringTokLocs[0], StringTokLocs.size() to factory! - return Owned(StringLiteral::Create(Context, Literal.GetString(), - Kind, Literal.Pascal, StrTy, - &StringTokLocs[0], - StringTokLocs.size())); -} - -enum CaptureResult { - /// No capture is required. - CR_NoCapture, - - /// A capture is required. - CR_Capture, - - /// A by-ref capture is required. - CR_CaptureByRef, - - /// An error occurred when trying to capture the given variable. - CR_Error -}; - -/// Diagnose an uncapturable value reference. -/// -/// \param var - the variable referenced -/// \param DC - the context which we couldn't capture through -static CaptureResult -diagnoseUncapturableValueReference(Sema &S, SourceLocation loc, - VarDecl *var, DeclContext *DC) { - switch (S.ExprEvalContexts.back().Context) { - case Sema::Unevaluated: - // The argument will never be evaluated, so don't complain. - return CR_NoCapture; - - case Sema::PotentiallyEvaluated: - case Sema::PotentiallyEvaluatedIfUsed: - break; - - case Sema::PotentiallyPotentiallyEvaluated: - // FIXME: delay these! - break; - } - - // Don't diagnose about capture if we're not actually in code right - // now; in general, there are more appropriate places that will - // diagnose this. - if (!S.CurContext->isFunctionOrMethod()) return CR_NoCapture; - - // Certain madnesses can happen with parameter declarations, which - // we want to ignore. - if (isa<ParmVarDecl>(var)) { - // - If the parameter still belongs to the translation unit, then - // we're actually just using one parameter in the declaration of - // the next. This is useful in e.g. VLAs. - if (isa<TranslationUnitDecl>(var->getDeclContext())) - return CR_NoCapture; - - // - This particular madness can happen in ill-formed default - // arguments; claim it's okay and let downstream code handle it. - if (S.CurContext == var->getDeclContext()->getParent()) - return CR_NoCapture; - } - - DeclarationName functionName; - if (FunctionDecl *fn = dyn_cast<FunctionDecl>(var->getDeclContext())) - functionName = fn->getDeclName(); - // FIXME: variable from enclosing block that we couldn't capture from! - - S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_function) - << var->getIdentifier() << functionName; - S.Diag(var->getLocation(), diag::note_local_variable_declared_here) - << var->getIdentifier(); - - return CR_Error; -} - -/// There is a well-formed capture at a particular scope level; -/// propagate it through all the nested blocks. -static CaptureResult propagateCapture(Sema &S, unsigned ValidScopeIndex, - const BlockDecl::Capture &Capture) { - VarDecl *var = Capture.getVariable(); - - // Update all the inner blocks with the capture information. - for (unsigned i = ValidScopeIndex + 1, e = S.FunctionScopes.size(); - i != e; ++i) { - BlockScopeInfo *innerBlock = cast<BlockScopeInfo>(S.FunctionScopes[i]); - innerBlock->Captures.push_back( - BlockDecl::Capture(Capture.getVariable(), Capture.isByRef(), - /*nested*/ true, Capture.getCopyExpr())); - innerBlock->CaptureMap[var] = innerBlock->Captures.size(); // +1 - } - - return Capture.isByRef() ? CR_CaptureByRef : CR_Capture; -} - -/// shouldCaptureValueReference - Determine if a reference to the -/// given value in the current context requires a variable capture. -/// -/// This also keeps the captures set in the BlockScopeInfo records -/// up-to-date. -static CaptureResult shouldCaptureValueReference(Sema &S, SourceLocation loc, - ValueDecl *Value) { - // Only variables ever require capture. - VarDecl *var = dyn_cast<VarDecl>(Value); - if (!var) return CR_NoCapture; - - // Fast path: variables from the current context never require capture. - DeclContext *DC = S.CurContext; - if (var->getDeclContext() == DC) return CR_NoCapture; - - // Only variables with local storage require capture. - // FIXME: What about 'const' variables in C++? - if (!var->hasLocalStorage()) return CR_NoCapture; - - // Otherwise, we need to capture. - - unsigned functionScopesIndex = S.FunctionScopes.size() - 1; - do { - // Only blocks (and eventually C++0x closures) can capture; other - // scopes don't work. - if (!isa<BlockDecl>(DC)) - return diagnoseUncapturableValueReference(S, loc, var, DC); - - BlockScopeInfo *blockScope = - cast<BlockScopeInfo>(S.FunctionScopes[functionScopesIndex]); - assert(blockScope->TheDecl == static_cast<BlockDecl*>(DC)); - - // Check whether we've already captured it in this block. If so, - // we're done. - if (unsigned indexPlus1 = blockScope->CaptureMap[var]) - return propagateCapture(S, functionScopesIndex, - blockScope->Captures[indexPlus1 - 1]); - - functionScopesIndex--; - DC = cast<BlockDecl>(DC)->getDeclContext(); - } while (var->getDeclContext() != DC); - - // Okay, we descended all the way to the block that defines the variable. - // Actually try to capture it. - QualType type = var->getType(); - - // Prohibit variably-modified types. - if (type->isVariablyModifiedType()) { - S.Diag(loc, diag::err_ref_vm_type); - S.Diag(var->getLocation(), diag::note_declared_at); - return CR_Error; - } - - // Prohibit arrays, even in __block variables, but not references to - // them. - if (type->isArrayType()) { - S.Diag(loc, diag::err_ref_array_type); - S.Diag(var->getLocation(), diag::note_declared_at); - return CR_Error; - } - - S.MarkDeclarationReferenced(loc, var); - - // The BlocksAttr indicates the variable is bound by-reference. - bool byRef = var->hasAttr<BlocksAttr>(); - - // Build a copy expression. - Expr *copyExpr = 0; - const RecordType *rtype; - if (!byRef && S.getLangOptions().CPlusPlus && !type->isDependentType() && - (rtype = type->getAs<RecordType>())) { - - // The capture logic needs the destructor, so make sure we mark it. - // Usually this is unnecessary because most local variables have - // their destructors marked at declaration time, but parameters are - // an exception because it's technically only the call site that - // actually requires the destructor. - if (isa<ParmVarDecl>(var)) - S.FinalizeVarWithDestructor(var, rtype); - - // According to the blocks spec, the capture of a variable from - // the stack requires a const copy constructor. This is not true - // of the copy/move done to move a __block variable to the heap. - type.addConst(); - - Expr *declRef = new (S.Context) DeclRefExpr(var, type, VK_LValue, loc); - ExprResult result = - S.PerformCopyInitialization( - InitializedEntity::InitializeBlock(var->getLocation(), - type, false), - loc, S.Owned(declRef)); - - // Build a full-expression copy expression if initialization - // succeeded and used a non-trivial constructor. Recover from - // errors by pretending that the copy isn't necessary. - if (!result.isInvalid() && - !cast<CXXConstructExpr>(result.get())->getConstructor()->isTrivial()) { - result = S.MaybeCreateExprWithCleanups(result); - copyExpr = result.take(); - } - } - - // We're currently at the declarer; go back to the closure. - functionScopesIndex++; - BlockScopeInfo *blockScope = - cast<BlockScopeInfo>(S.FunctionScopes[functionScopesIndex]); - - // Build a valid capture in this scope. - blockScope->Captures.push_back( - BlockDecl::Capture(var, byRef, /*nested*/ false, copyExpr)); - blockScope->CaptureMap[var] = blockScope->Captures.size(); // +1 - - // Propagate that to inner captures if necessary. - return propagateCapture(S, functionScopesIndex, - blockScope->Captures.back()); -} - -static ExprResult BuildBlockDeclRefExpr(Sema &S, ValueDecl *VD, - const DeclarationNameInfo &NameInfo, - bool ByRef) { - assert(isa<VarDecl>(VD) && "capturing non-variable"); - - VarDecl *var = cast<VarDecl>(VD); - assert(var->hasLocalStorage() && "capturing non-local"); - assert(ByRef == var->hasAttr<BlocksAttr>() && "byref set wrong"); - - QualType exprType = var->getType().getNonReferenceType(); - - BlockDeclRefExpr *BDRE; - if (!ByRef) { - // The variable will be bound by copy; make it const within the - // closure, but record that this was done in the expression. - bool constAdded = !exprType.isConstQualified(); - exprType.addConst(); - - BDRE = new (S.Context) BlockDeclRefExpr(var, exprType, VK_LValue, - NameInfo.getLoc(), false, - constAdded); - } else { - BDRE = new (S.Context) BlockDeclRefExpr(var, exprType, VK_LValue, - NameInfo.getLoc(), true); - } - - return S.Owned(BDRE); + StringLiteral *Lit = StringLiteral::Create(Context, Literal.GetString(), + Kind, Literal.Pascal, StrTy, + &StringTokLocs[0], + StringTokLocs.size()); + if (Literal.getUDSuffix().empty()) + return Owned(Lit); + + // We're building a user-defined literal. + IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix()); + SourceLocation UDSuffixLoc = + getUDSuffixLoc(*this, StringTokLocs[Literal.getUDSuffixToken()], + Literal.getUDSuffixOffset()); + + // Make sure we're allowed user-defined literals here. + if (!UDLScope) + return ExprError(Diag(UDSuffixLoc, diag::err_invalid_string_udl)); + + // C++11 [lex.ext]p5: The literal L is treated as a call of the form + // operator "" X (str, len) + QualType SizeType = Context.getSizeType(); + llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars()); + IntegerLiteral *LenArg = IntegerLiteral::Create(Context, Len, SizeType, + StringTokLocs[0]); + Expr *Args[] = { Lit, LenArg }; + return BuildCookedLiteralOperatorCall(*this, UDLScope, UDSuffix, UDSuffixLoc, + Args, StringTokLocs.back()); } ExprResult @@ -1407,7 +1279,7 @@ ExprResult Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, const DeclarationNameInfo &NameInfo, const CXXScopeSpec *SS) { - if (getLangOptions().CUDA) + if (getLangOpts().CUDA) if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext)) if (const FunctionDecl *Callee = dyn_cast<FunctionDecl>(D)) { CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller), @@ -1421,12 +1293,18 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, } } - MarkDeclarationReferenced(NameInfo.getLoc(), D); + bool refersToEnclosingScope = + (CurContext != D->getDeclContext() && + D->getDeclContext()->isFunctionOrMethod()); + + DeclRefExpr *E = DeclRefExpr::Create(Context, + SS ? SS->getWithLocInContext(Context) + : NestedNameSpecifierLoc(), + SourceLocation(), + D, refersToEnclosingScope, + NameInfo, Ty, VK); - Expr *E = DeclRefExpr::Create(Context, - SS? SS->getWithLocInContext(Context) - : NestedNameSpecifierLoc(), - D, NameInfo, Ty, VK); + MarkDeclRefReferenced(E); // Just in case we're building an illegal pointer-to-member. FieldDecl *FD = dyn_cast<FieldDecl>(D); @@ -1474,9 +1352,9 @@ Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id, /// /// \return false if new lookup candidates were found bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, - CorrectTypoContext CTC, + CorrectionCandidateCallback &CCC, TemplateArgumentListInfo *ExplicitTemplateArgs, - Expr **Args, unsigned NumArgs) { + llvm::ArrayRef<Expr *> Args) { DeclarationName Name = R.getLookupName(); unsigned diagnostic = diag::err_undeclared_var_use; @@ -1492,8 +1370,8 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, // unqualified lookup. This is useful when (for example) the // original lookup would not have found something because it was a // dependent name. - for (DeclContext *DC = SS.isEmpty() ? CurContext : 0; - DC; DC = DC->getParent()) { + DeclContext *DC = SS.isEmpty() ? CurContext : 0; + while (DC) { if (isa<CXXRecordDecl>(DC)) { LookupQualifiedName(R, DC); @@ -1501,10 +1379,17 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, // Don't give errors about ambiguities in this lookup. R.suppressDiagnostics(); + // During a default argument instantiation the CurContext points + // to a CXXMethodDecl; but we can't apply a this-> fixit inside a + // function parameter list, hence add an explicit check. + bool isDefaultArgument = !ActiveTemplateInstantiations.empty() && + ActiveTemplateInstantiations.back().Kind == + ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation; CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext); bool isInstance = CurMethod && CurMethod->isInstance() && - DC == CurMethod->getParent(); + DC == CurMethod->getParent() && !isDefaultArgument; + // Give a code modification hint to insert 'this->'. // TODO: fixit for inserting 'Base<T>::' in the other cases. @@ -1515,11 +1400,12 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, CXXMethodDecl *DepMethod = cast_or_null<CXXMethodDecl>( CurMethod->getInstantiatedFromMemberFunction()); if (DepMethod) { - if (getLangOptions().MicrosoftExt) + if (getLangOpts().MicrosoftMode) diagnostic = diag::warn_found_via_dependent_bases_lookup; Diag(R.getNameLoc(), diagnostic) << Name << FixItHint::CreateInsertion(R.getNameLoc(), "this->"); QualType DepThisType = DepMethod->getThisType(Context); + CheckCXXThisCapture(R.getNameLoc()); CXXThisExpr *DepThis = new (Context) CXXThisExpr( R.getNameLoc(), DepThisType, false); TemplateArgumentListInfo TList; @@ -1531,7 +1417,8 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, CXXDependentScopeMemberExpr *DepExpr = CXXDependentScopeMemberExpr::Create( Context, DepThis, DepThisType, true, SourceLocation(), - SS.getWithLocInContext(Context), NULL, + SS.getWithLocInContext(Context), + ULE->getTemplateKeywordLoc(), 0, R.getLookupNameInfo(), ULE->hasExplicitTemplateArgs() ? &TList : 0); CallsUndergoingInstantiation.back()->setCallee(DepExpr); @@ -1541,6 +1428,8 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, Diag(R.getNameLoc(), diagnostic) << Name; } } else { + if (getLangOpts().MicrosoftMode) + diagnostic = diag::warn_found_via_dependent_bases_lookup; Diag(R.getNameLoc(), diagnostic) << Name; } @@ -1548,20 +1437,40 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) Diag((*I)->getLocation(), diag::note_dependent_var_use); + // Return true if we are inside a default argument instantiation + // and the found name refers to an instance member function, otherwise + // the function calling DiagnoseEmptyLookup will try to create an + // implicit member call and this is wrong for default argument. + if (isDefaultArgument && ((*R.begin())->isCXXInstanceMember())) { + Diag(R.getNameLoc(), diag::err_member_call_without_object); + return true; + } + // Tell the callee to try to recover. return false; } R.clear(); } + + // In Microsoft mode, if we are performing lookup from within a friend + // 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) && + cast<FunctionDecl>(DC)->getFriendObjectKind() && + DC->getLexicalParent()->isRecord()) + DC = DC->getLexicalParent(); + else + DC = DC->getParent(); } // We didn't find anything, so try to correct for a typo. TypoCorrection Corrected; if (S && (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), - S, &SS, NULL, false, CTC))) { - std::string CorrectedStr(Corrected.getAsString(getLangOptions())); - std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions())); + S, &SS, CCC))) { + std::string CorrectedStr(Corrected.getAsString(getLangOpts())); + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); R.setLookupName(Corrected.getCorrection()); if (NamedDecl *ND = Corrected.getCorrectionDecl()) { @@ -1575,11 +1484,11 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, dyn_cast<FunctionTemplateDecl>(*CD)) AddTemplateOverloadCandidate( FTD, DeclAccessPair::make(FTD, AS_none), ExplicitTemplateArgs, - Args, NumArgs, OCS); + Args, OCS); else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*CD)) if (!ExplicitTemplateArgs || ExplicitTemplateArgs->size() == 0) AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none), - Args, NumArgs, OCS); + Args, OCS); } switch (OCS.BestViableFunction(*this, R.getNameLoc(), Best)) { case OR_Success: @@ -1654,9 +1563,11 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, ExprResult Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, UnqualifiedId &Id, bool HasTrailingLParen, - bool IsAddressOfOperand) { + bool IsAddressOfOperand, + CorrectionCandidateCallback *CCC) { assert(!(IsAddressOfOperand && HasTrailingLParen) && "cannot be direct & operand and have a trailing lparen"); @@ -1699,10 +1610,9 @@ ExprResult Sema::ActOnIdExpression(Scope *S, } if (DependentID) - return ActOnDependentIdExpression(SS, NameInfo, IsAddressOfOperand, - TemplateArgs); + return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, + IsAddressOfOperand, TemplateArgs); - bool IvarLookupFollowUp = false; // Perform the required lookup. LookupResult R(*this, NameInfo, (Id.getKind() == UnqualifiedId::IK_ImplicitSelfParam) @@ -1719,18 +1629,18 @@ ExprResult Sema::ActOnIdExpression(Scope *S, if (MemberOfUnknownSpecialization || (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)) - return ActOnDependentIdExpression(SS, NameInfo, IsAddressOfOperand, - TemplateArgs); + return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, + IsAddressOfOperand, TemplateArgs); } else { - IvarLookupFollowUp = (!SS.isSet() && II && getCurMethodDecl()); + bool IvarLookupFollowUp = II && !SS.isSet() && getCurMethodDecl(); LookupParsedName(R, S, &SS, !IvarLookupFollowUp); // If the result might be in a dependent base class, this is a dependent // id-expression. if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) - return ActOnDependentIdExpression(SS, NameInfo, IsAddressOfOperand, - TemplateArgs); - + return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, + IsAddressOfOperand, TemplateArgs); + // If this reference is in an Objective-C method, then we need to do // some special Objective-C lookup, too. if (IvarLookupFollowUp) { @@ -1740,9 +1650,6 @@ ExprResult Sema::ActOnIdExpression(Scope *S, if (Expr *Ex = E.takeAs<Expr>()) return Owned(Ex); - - // for further use, this must be set to false if in class method. - IvarLookupFollowUp = getCurMethodDecl()->isInstanceMethod(); } } @@ -1756,7 +1663,7 @@ ExprResult Sema::ActOnIdExpression(Scope *S, 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 && !getLangOptions().CPlusPlus) { + if (HasTrailingLParen && II && !getLangOpts().CPlusPlus) { NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S); if (D) R.addDecl(D); } @@ -1769,12 +1676,13 @@ ExprResult Sema::ActOnIdExpression(Scope *S, // and we can't resolve an identifier then assume the identifier is type // dependent. The goal is to postpone name lookup to instantiation time // to be able to search into type dependent base classes. - if (getLangOptions().MicrosoftMode && CurContext->isDependentContext() && + if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() && isa<CXXMethodDecl>(CurContext)) - return ActOnDependentIdExpression(SS, NameInfo, IsAddressOfOperand, - TemplateArgs); + return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, + IsAddressOfOperand, TemplateArgs); - if (DiagnoseEmptyLookup(S, SS, R, CTC_Unknown)) + CorrectionCandidateCallback DefaultValidator; + if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator)) return ExprError(); assert(!R.empty() && @@ -1837,11 +1745,12 @@ ExprResult Sema::ActOnIdExpression(Scope *S, isa<IndirectFieldDecl>(R.getFoundDecl()); if (MightBeImplicitMember) - return BuildPossibleImplicitMemberExpr(SS, R, TemplateArgs); + return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, + R, TemplateArgs); } - if (TemplateArgs) - return BuildTemplateIdExpr(SS, R, ADL, *TemplateArgs); + if (TemplateArgs || TemplateKWLoc.isValid()) + return BuildTemplateIdExpr(SS, TemplateKWLoc, R, ADL, TemplateArgs); return BuildDeclarationNameExpr(SS, R, ADL); } @@ -1855,7 +1764,8 @@ Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo) { DeclContext *DC; if (!(DC = computeDeclContext(SS, false)) || DC->isDependentContext()) - return BuildDependentDeclRefExpr(SS, NameInfo, 0); + return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), + NameInfo, /*TemplateArgs=*/0); if (RequireCompleteDeclContext(SS, DC)) return ExprError(); @@ -1912,7 +1822,8 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, if (LookForIvars) { IFace = CurMethod->getClassInterface(); ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { + ObjCIvarDecl *IV = 0; + if (IFace && (IV = IFace->lookupInstanceVariable(II, ClassDeclared))) { // Diagnose using an ivar in a class method. if (IsClassMethod) return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method) @@ -1929,7 +1840,8 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, // Diagnose the use of an ivar outside of the declaring class. if (IV->getAccessControl() == ObjCIvarDecl::Private && - ClassDeclared != IFace) + !declaresSameEntity(ClassDeclared, IFace) && + !getLangOpts().DebuggerSupport) Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName(); // FIXME: This should use a new expr for a direct reference, don't @@ -1939,7 +1851,8 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, SelfName.setIdentifier(&II, SourceLocation()); SelfName.setKind(UnqualifiedId::IK_ImplicitSelfParam); CXXScopeSpec SelfScopeSpec; - ExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, + SourceLocation TemplateKWLoc; + ExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc, SelfName, false, false); if (SelfExpr.isInvalid()) return ExprError(); @@ -1948,26 +1861,33 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, if (SelfExpr.isInvalid()) return ExprError(); - MarkDeclarationReferenced(Loc, IV); + MarkAnyDeclReferenced(Loc, IV); return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), Loc, SelfExpr.take(), true, true)); } } else if (CurMethod->isInstanceMethod()) { // We should warn if a local variable hides an ivar. - ObjCInterfaceDecl *IFace = CurMethod->getClassInterface(); - ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { - if (IV->getAccessControl() != ObjCIvarDecl::Private || - IFace == ClassDeclared) - Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName(); + if (ObjCInterfaceDecl *IFace = CurMethod->getClassInterface()) { + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { + if (IV->getAccessControl() != ObjCIvarDecl::Private || + declaresSameEntity(IFace, ClassDeclared)) + Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName(); + } } + } else if (Lookup.isSingleResult() && + Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()) { + // If accessing a stand-alone ivar in a class method, this is an error. + if (const ObjCIvarDecl *IV = dyn_cast<ObjCIvarDecl>(Lookup.getFoundDecl())) + return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method) + << IV->getDeclName()); } if (Lookup.empty() && II && AllowBuiltinCreation) { // FIXME. Consolidate this with similar code in LookupName. if (unsigned BuiltinID = II->getBuiltinID()) { - if (!(getLangOptions().CPlusPlus && + if (!(getLangOpts().CPlusPlus && Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))) { NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, S, Lookup.isForRedeclaration(), @@ -2159,7 +2079,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, return false; // Only in C++ or ObjC++. - if (!getLangOptions().CPlusPlus) + if (!getLangOpts().CPlusPlus) return false; // Turn off ADL when we find certain kinds of declarations during @@ -2308,30 +2228,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, return BuildAnonymousStructUnionMemberReference(SS, NameInfo.getLoc(), indirectField); - // If the identifier reference is inside a block, and it refers to a value - // that is outside the block, create a BlockDeclRefExpr instead of a - // DeclRefExpr. This ensures the value is treated as a copy-in snapshot when - // the block is formed. - // - // We do not do this for things like enum constants, global variables, etc, - // as they do not get snapshotted. - // - switch (shouldCaptureValueReference(*this, NameInfo.getLoc(), VD)) { - case CR_Error: - return ExprError(); - - case CR_Capture: - assert(!SS.isSet() && "referenced local variable with scope specifier?"); - return BuildBlockDeclRefExpr(*this, VD, NameInfo, /*byref*/ false); - - case CR_CaptureByRef: - assert(!SS.isSet() && "referenced local variable with scope specifier?"); - return BuildBlockDeclRefExpr(*this, VD, NameInfo, /*byref*/ true); - - case CR_NoCapture: { - // If this reference is not in a block or if the referenced - // variable is within the block, create a normal DeclRefExpr. - + { QualType type = VD->getType(); ExprValueKind valueKind = VK_RValue; @@ -2343,13 +2240,11 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, case Decl::type: #include "clang/AST/DeclNodes.inc" llvm_unreachable("invalid value decl kind"); - return ExprError(); // These shouldn't make it here. case Decl::ObjCAtDefsField: case Decl::ObjCIvar: llvm_unreachable("forming non-member reference to ivar?"); - return ExprError(); // Enum constants are always r-values and never references. // Unresolved using declarations are dependent. @@ -2364,7 +2259,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, // exist in the high-level semantics. case Decl::Field: case Decl::IndirectField: - assert(getLangOptions().CPlusPlus && + assert(getLangOpts().CPlusPlus && "building reference to field in C?"); // These can't have reference type in well-formed programs, but @@ -2391,7 +2286,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, case Decl::Var: // In C, "extern void blah;" is valid and is an r-value. - if (!getLangOptions().CPlusPlus && + if (!getLangOpts().CPlusPlus && !type.hasQualifiers() && type->isVoidType()) { valueKind = VK_RValue; @@ -2400,12 +2295,23 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, // fallthrough case Decl::ImplicitParam: - case Decl::ParmVar: + case Decl::ParmVar: { // These are always l-values. valueKind = VK_LValue; type = type.getNonReferenceType(); - break; + // FIXME: Does the addition of const really only apply in + // potentially-evaluated contexts? Since the variable isn't actually + // captured in an unevaluated context, it seems that the answer is no. + if (ExprEvalContexts.back().Context != Sema::Unevaluated) { + QualType CapturedType = getCapturedDeclRefType(cast<VarDecl>(VD), Loc); + if (!CapturedType.isNull()) + type = CapturedType; + } + + break; + } + case Decl::Function: { const FunctionType *fty = type->castAs<FunctionType>(); @@ -2418,7 +2324,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, } // Functions are l-values in C++. - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { valueKind = VK_LValue; break; } @@ -2466,11 +2372,6 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS); } - - } - - llvm_unreachable("unknown capture result"); - return ExprError(); } ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { @@ -2507,8 +2408,8 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT)); } -ExprResult Sema::ActOnCharacterConstant(const Token &Tok) { - llvm::SmallString<16> CharBuffer; +ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) { + SmallString<16> CharBuffer; bool Invalid = false; StringRef ThisTok = PP.getSpelling(Tok, CharBuffer, &Invalid); if (Invalid) @@ -2520,16 +2421,14 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok) { return ExprError(); QualType Ty; - if (!getLangOptions().CPlusPlus) - Ty = Context.IntTy; // 'x' and L'x' -> int in C. - else if (Literal.isWide()) - Ty = Context.WCharTy; // L'x' -> wchar_t in C++. + if (Literal.isWide()) + Ty = Context.WCharTy; // L'x' -> wchar_t in C and C++. else if (Literal.isUTF16()) - Ty = Context.Char16Ty; // u'x' -> char16_t in C++0x. + Ty = Context.Char16Ty; // u'x' -> char16_t in C11 and C++11. else if (Literal.isUTF32()) - Ty = Context.Char32Ty; // U'x' -> char32_t in C++0x. - else if (Literal.isMultiChar()) - Ty = Context.IntTy; // 'wxyz' -> int in C++. + Ty = Context.Char32Ty; // U'x' -> char32_t in C11 and C++11. + else if (!getLangOpts().CPlusPlus || Literal.isMultiChar()) + Ty = Context.IntTy; // 'x' -> int in C, 'wxyz' -> int in C++. else Ty = Context.CharTy; // 'x' -> char in C++ @@ -2541,21 +2440,75 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok) { else if (Literal.isUTF32()) Kind = CharacterLiteral::UTF32; - return Owned(new (Context) CharacterLiteral(Literal.getValue(), Kind, Ty, - Tok.getLocation())); + Expr *Lit = new (Context) CharacterLiteral(Literal.getValue(), Kind, Ty, + Tok.getLocation()); + + if (Literal.getUDSuffix().empty()) + return Owned(Lit); + + // We're building a user-defined literal. + IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix()); + SourceLocation UDSuffixLoc = + getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset()); + + // Make sure we're allowed user-defined literals here. + if (!UDLScope) + return ExprError(Diag(UDSuffixLoc, diag::err_invalid_character_udl)); + + // C++11 [lex.ext]p6: The literal L is treated as a call of the form + // operator "" X (ch) + return BuildCookedLiteralOperatorCall(*this, UDLScope, UDSuffix, UDSuffixLoc, + llvm::makeArrayRef(&Lit, 1), + Tok.getLocation()); } -ExprResult Sema::ActOnNumericConstant(const Token &Tok) { +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)); +} + +static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal, + QualType Ty, SourceLocation Loc) { + const llvm::fltSemantics &Format = S.Context.getFloatTypeSemantics(Ty); + + using llvm::APFloat; + APFloat Val(Format); + + APFloat::opStatus result = Literal.GetFloatValue(Val); + + // Overflow is always an error, but underflow is only an error if + // we underflowed to zero (APFloat reports denormals as underflow). + if ((result & APFloat::opOverflow) || + ((result & APFloat::opUnderflow) && Val.isZero())) { + unsigned diagnostic; + SmallString<20> buffer; + if (result & APFloat::opOverflow) { + diagnostic = diag::warn_float_overflow; + APFloat::getLargest(Format).toString(buffer); + } else { + diagnostic = diag::warn_float_underflow; + APFloat::getSmallest(Format).toString(buffer); + } + + S.Diag(Loc, diagnostic) + << Ty + << StringRef(buffer.data(), buffer.size()); + } + + bool isExact = (result == APFloat::opOK); + return FloatingLiteral::Create(S.Context, Val, isExact, Ty, Loc); +} + +ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { // Fast path for a single digit (which is quite common). A single digit - // cannot have a trigraph, escaped newline, radix prefix, or type suffix. + // cannot have a trigraph, escaped newline, radix prefix, or suffix. if (Tok.getLength() == 1) { const char Val = PP.getSpellingOfSingleCharacterNumericConstant(Tok); - unsigned IntSize = Context.getTargetInfo().getIntWidth(); - return Owned(IntegerLiteral::Create(Context, llvm::APInt(IntSize, Val-'0'), - Context.IntTy, Tok.getLocation())); + return ActOnIntegerConstant(Tok.getLocation(), Val-'0'); } - llvm::SmallString<512> IntegerBuffer; + SmallString<512> IntegerBuffer; // Add padding so that NumericLiteralParser can overread by one character. IntegerBuffer.resize(Tok.getLength()+1); const char *ThisTokBegin = &IntegerBuffer[0]; @@ -2571,6 +2524,96 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok) { if (Literal.hadError) return ExprError(); + if (Literal.hasUDSuffix()) { + // We're building a user-defined literal. + IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix()); + SourceLocation UDSuffixLoc = + getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset()); + + // Make sure we're allowed user-defined literals here. + if (!UDLScope) + return ExprError(Diag(UDSuffixLoc, diag::err_invalid_numeric_udl)); + + QualType CookedTy; + if (Literal.isFloatingLiteral()) { + // C++11 [lex.ext]p4: If S contains a literal operator with parameter type + // long double, the literal is treated as a call of the form + // operator "" X (f L) + CookedTy = Context.LongDoubleTy; + } else { + // C++11 [lex.ext]p3: If S contains a literal operator with parameter type + // unsigned long long, the literal is treated as a call of the form + // operator "" X (n ULL) + CookedTy = Context.UnsignedLongLongTy; + } + + DeclarationName OpName = + Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix); + DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc); + OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc); + + // Perform literal operator lookup to determine if we're building a raw + // literal or a cooked one. + LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName); + switch (LookupLiteralOperator(UDLScope, R, llvm::makeArrayRef(&CookedTy, 1), + /*AllowRawAndTemplate*/true)) { + case LOLR_Error: + return ExprError(); + + case LOLR_Cooked: { + Expr *Lit; + if (Literal.isFloatingLiteral()) { + Lit = BuildFloatingLiteral(*this, Literal, CookedTy, Tok.getLocation()); + } else { + llvm::APInt ResultVal(Context.getTargetInfo().getLongLongWidth(), 0); + if (Literal.GetIntegerValue(ResultVal)) + Diag(Tok.getLocation(), diag::warn_integer_too_large); + Lit = IntegerLiteral::Create(Context, ResultVal, CookedTy, + Tok.getLocation()); + } + return BuildLiteralOperatorCall(R, OpNameInfo, + llvm::makeArrayRef(&Lit, 1), + Tok.getLocation()); + } + + case LOLR_Raw: { + // C++11 [lit.ext]p3, p4: If S contains a raw literal operator, the + // literal is treated as a call of the form + // operator "" X ("n") + SourceLocation TokLoc = Tok.getLocation(); + unsigned Length = Literal.getUDSuffixOffset(); + QualType StrTy = Context.getConstantArrayType( + Context.CharTy, llvm::APInt(32, Length + 1), + ArrayType::Normal, 0); + Expr *Lit = StringLiteral::Create( + Context, StringRef(ThisTokBegin, Length), StringLiteral::Ascii, + /*Pascal*/false, StrTy, &TokLoc, 1); + return BuildLiteralOperatorCall(R, OpNameInfo, + llvm::makeArrayRef(&Lit, 1), TokLoc); + } + + case LOLR_Template: + // C++11 [lit.ext]p3, p4: Otherwise (S contains a literal operator + // template), L is treated as a call fo the form + // operator "" X <'c1', 'c2', ... 'ck'>() + // where n is the source character sequence c1 c2 ... ck. + TemplateArgumentListInfo ExplicitArgs; + unsigned CharBits = Context.getIntWidth(Context.CharTy); + bool CharIsUnsigned = Context.CharTy->isUnsignedIntegerType(); + llvm::APSInt Value(CharBits, CharIsUnsigned); + for (unsigned I = 0, N = Literal.getUDSuffixOffset(); I != N; ++I) { + Value = ThisTokBegin[I]; + TemplateArgument Arg(Value, Context.CharTy); + TemplateArgumentLocInfo ArgInfo; + ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo)); + } + return BuildLiteralOperatorCall(R, OpNameInfo, ArrayRef<Expr*>(), + Tok.getLocation(), &ExplicitArgs); + } + + llvm_unreachable("unexpected literal operator lookup result"); + } + Expr *Res; if (Literal.isFloatingLiteral()) { @@ -2582,39 +2625,12 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok) { else Ty = Context.LongDoubleTy; - const llvm::fltSemantics &Format = Context.getFloatTypeSemantics(Ty); - - using llvm::APFloat; - APFloat Val(Format); - - APFloat::opStatus result = Literal.GetFloatValue(Val); - - // Overflow is always an error, but underflow is only an error if - // we underflowed to zero (APFloat reports denormals as underflow). - if ((result & APFloat::opOverflow) || - ((result & APFloat::opUnderflow) && Val.isZero())) { - unsigned diagnostic; - llvm::SmallString<20> buffer; - if (result & APFloat::opOverflow) { - diagnostic = diag::warn_float_overflow; - APFloat::getLargest(Format).toString(buffer); - } else { - diagnostic = diag::warn_float_underflow; - APFloat::getSmallest(Format).toString(buffer); - } - - Diag(Tok.getLocation(), diagnostic) - << Ty - << StringRef(buffer.data(), buffer.size()); - } - - bool isExact = (result == APFloat::opOK); - Res = FloatingLiteral::Create(Context, Val, isExact, Ty, Tok.getLocation()); + Res = BuildFloatingLiteral(*this, Literal, Ty, Tok.getLocation()); if (Ty == Context.DoubleTy) { - if (getLangOptions().SinglePrecisionConstants) { + if (getLangOpts().SinglePrecisionConstants) { Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).take(); - } else if (getLangOptions().OpenCL && !getOpenCLOptions().cl_khr_fp64) { + } 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(); } @@ -2625,9 +2641,10 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok) { QualType Ty; // long long is a C99 feature. - if (!getLangOptions().C99 && !getLangOptions().CPlusPlus0x && - Literal.isLongLong) - Diag(Tok.getLocation(), diag::ext_longlong); + if (!getLangOpts().C99 && Literal.isLongLong) + Diag(Tok.getLocation(), + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_longlong : diag::ext_longlong); // Get the value in the widest-possible width. llvm::APInt ResultVal(Context.getTargetInfo().getIntMaxTWidth(), 0); @@ -2688,7 +2705,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok) { // To be compatible with MSVC, hex integer literals ending with the // LL or i64 suffix are always signed in Microsoft mode. if (!Literal.isUnsigned && (ResultVal[LongLongSize-1] == 0 || - (getLangOptions().MicrosoftExt && Literal.isLongLong))) + (getLangOpts().MicrosoftExt && Literal.isLongLong))) Ty = Context.LongLongTy; else if (AllowUnsigned) Ty = Context.UnsignedLongLongTy; @@ -2971,6 +2988,12 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, if (isInvalid) return ExprError(); + if (ExprKind == UETT_SizeOf && E->getType()->isVariableArrayType()) { + PE = TranformToPotentiallyEvaluated(E); + if (PE.isInvalid()) return ExprError(); + E = PE.take(); + } + // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t. return Owned(new (Context) UnaryExprOrTypeTraitExpr( ExprKind, E, Context.getSizeType(), OpLoc, @@ -3044,6 +3067,11 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, case tok::minusminus: Opc = UO_PostDec; break; } + // Since this might is a postfix expression, get rid of ParenListExprs. + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Input); + if (Result.isInvalid()) return ExprError(); + Input = Result.take(); + return BuildUnaryOp(S, OpLoc, Opc, Input); } @@ -3057,7 +3085,7 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc, Expr *LHSExp = Base, *RHSExp = Idx; - if (getLangOptions().CPlusPlus && + if (getLangOpts().CPlusPlus && (LHSExp->isTypeDependent() || RHSExp->isTypeDependent())) { return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp, Context.DependentTy, @@ -3065,11 +3093,12 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc, RLoc)); } - if (getLangOptions().CPlusPlus && + if (getLangOpts().CPlusPlus && (LHSExp->getType()->isRecordType() || LHSExp->getType()->isEnumeralType() || RHSExp->getType()->isRecordType() || - RHSExp->getType()->isEnumeralType())) { + RHSExp->getType()->isEnumeralType()) && + !LHSExp->getType()->isObjCObjectPointerType()) { return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, Base, Idx); } @@ -3113,17 +3142,20 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, BaseExpr = LHSExp; IndexExpr = RHSExp; ResultType = PTy->getPointeeType(); + } else if (const ObjCObjectPointerType *PTy = + LHSTy->getAs<ObjCObjectPointerType>()) { + BaseExpr = LHSExp; + IndexExpr = RHSExp; + Result = BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, 0, 0); + if (!Result.isInvalid()) + return Owned(Result.take()); + ResultType = PTy->getPointeeType(); } else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) { // Handle the uncommon case of "123[Ptr]". BaseExpr = RHSExp; IndexExpr = LHSExp; ResultType = PTy->getPointeeType(); } else if (const ObjCObjectPointerType *PTy = - LHSTy->getAs<ObjCObjectPointerType>()) { - BaseExpr = LHSExp; - IndexExpr = RHSExp; - ResultType = PTy->getPointeeType(); - } else if (const ObjCObjectPointerType *PTy = RHSTy->getAs<ObjCObjectPointerType>()) { // Handle the uncommon case of "123[Ptr]". BaseExpr = RHSExp; @@ -3188,7 +3220,7 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, return ExprError(); } - if (ResultType->isVoidType() && !getLangOptions().CPlusPlus) { + if (ResultType->isVoidType() && !getLangOpts().CPlusPlus) { // GNU extension: subscripting on pointer to void Diag(LLoc, diag::ext_gnu_subscript_void_type) << BaseExpr->getSourceRange(); @@ -3247,6 +3279,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, // the semantic constraints are checked, at the point where the // default argument expression appears. ContextRAII SavedContext(*this, FD); + LocalInstantiationScope Local(*this); Result = SubstExpr(UninstExpr, ArgList); } if (Result.isInvalid()) @@ -3257,7 +3290,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, = InitializedEntity::InitializeParameter(Context, Param); InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(), - /*FIXME:EqualLoc*/UninstExpr->getSourceRange().getBegin()); + /*FIXME:EqualLoc*/UninstExpr->getLocStart()); Expr *ResultE = Result.takeAs<Expr>(); InitializationSequence InitSeq(*this, Entity, Kind, &ResultE, 1); @@ -3276,18 +3309,25 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, // be properly destroyed. // FIXME: We should really be rebuilding the default argument with new // bound temporaries; see the comment in PR5810. - for (unsigned i = 0, e = Param->getNumDefaultArgTemporaries(); i != e; ++i) { - CXXTemporary *Temporary = Param->getDefaultArgTemporary(i); - MarkDeclarationReferenced(Param->getDefaultArg()->getLocStart(), - const_cast<CXXDestructorDecl*>(Temporary->getDestructor())); - ExprTemporaries.push_back(Temporary); + // We don't need to do that with block decls, though, because + // blocks in default argument expression can never capture anything. + if (isa<ExprWithCleanups>(Param->getInit())) { + // Set the "needs cleanups" bit regardless of whether there are + // any explicit objects. ExprNeedsCleanups = true; + + // Append all the objects to the cleanup list. Right now, this + // should always be a no-op, because blocks in default argument + // expressions should never be able to capture anything. + assert(!cast<ExprWithCleanups>(Param->getInit())->getNumObjects() && + "default argument expression has capturing blocks?"); } // We already type-checked the argument, so we know it works. // Just mark all of the declarations in this potentially-evaluated expression // as being "referenced". - MarkDeclarationsReferencedInExpr(Param->getDefaultArg()); + MarkDeclarationsReferencedInExpr(Param->getDefaultArg(), + /*SkipLocalVariables=*/true); return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param)); } @@ -3371,7 +3411,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, CallType = VariadicBlock; // Block else if (isa<MemberExpr>(Fn)) CallType = VariadicMethod; - Invalid = GatherArgumentsForCall(Call->getSourceRange().getBegin(), FDecl, + Invalid = GatherArgumentsForCall(Call->getLocStart(), FDecl, Proto, 0, Args, NumArgs, AllArgs, CallType); if (Invalid) return true; @@ -3388,7 +3428,8 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, unsigned FirstProtoArg, Expr **Args, unsigned NumArgs, SmallVector<Expr *, 8> &AllArgs, - VariadicCallType CallType) { + VariadicCallType CallType, + bool AllowExplicit) { unsigned NumArgsInProto = Proto->getNumArgs(); unsigned NumArgsToCheck = NumArgs; bool Invalid = false; @@ -3401,33 +3442,42 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, QualType ProtoArgType = Proto->getArgType(i); Expr *Arg; + ParmVarDecl *Param; if (ArgIx < NumArgs) { Arg = Args[ArgIx++]; - if (RequireCompleteType(Arg->getSourceRange().getBegin(), + if (RequireCompleteType(Arg->getLocStart(), ProtoArgType, PDiag(diag::err_call_incomplete_argument) << Arg->getSourceRange())) return true; // Pass the argument - ParmVarDecl *Param = 0; + Param = 0; if (FDecl && i < FDecl->getNumParams()) Param = FDecl->getParamDecl(i); + // Strip the unbridged-cast placeholder expression off, if applicable. + if (Arg->getType() == Context.ARCUnbridgedCastTy && + FDecl && FDecl->hasAttr<CFAuditedTransferAttr>() && + (!Param || !Param->hasAttr<CFConsumedAttr>())) + Arg = stripARCUnbridgedCast(Arg); + InitializedEntity Entity = Param? InitializedEntity::InitializeParameter(Context, Param) : InitializedEntity::InitializeParameter(Context, ProtoArgType, Proto->isArgConsumed(i)); ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), - Owned(Arg)); + Owned(Arg), + /*TopLevelOfInitList=*/false, + AllowExplicit); if (ArgE.isInvalid()) return true; Arg = ArgE.takeAs<Expr>(); } else { - ParmVarDecl *Param = FDecl->getParamDecl(i); + Param = FDecl->getParamDecl(i); ExprResult ArgExpr = BuildCXXDefaultArgExpr(CallLoc, FDecl, Param); @@ -3442,6 +3492,9 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, // with its own checking, such as a BinaryOperator. CheckArrayAccess(Arg); + // Check for violations of C99 static array rules (C99 6.7.5.3p7). + CheckStaticArrayArgument(CallLoc, Param, Arg); + AllArgs.push_back(Arg); } @@ -3479,6 +3532,60 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, return Invalid; } +static void DiagnoseCalleeStaticArrayParam(Sema &S, ParmVarDecl *PVD) { + TypeLoc TL = PVD->getTypeSourceInfo()->getTypeLoc(); + if (ArrayTypeLoc *ATL = dyn_cast<ArrayTypeLoc>(&TL)) + S.Diag(PVD->getLocation(), diag::note_callee_static_array) + << ATL->getLocalSourceRange(); +} + +/// CheckStaticArrayArgument - If the given argument corresponds to a static +/// array parameter, check that it is non-null, and that if it is formed by +/// array-to-pointer decay, the underlying array is sufficiently large. +/// +/// C99 6.7.5.3p7: If the keyword static also appears within the [ and ] of the +/// array type derivation, then for each call to the function, the value of the +/// corresponding actual argument shall provide access to the first element of +/// an array with at least as many elements as specified by the size expression. +void +Sema::CheckStaticArrayArgument(SourceLocation CallLoc, + ParmVarDecl *Param, + const Expr *ArgExpr) { + // Static array parameters are not supported in C++. + if (!Param || getLangOpts().CPlusPlus) + return; + + QualType OrigTy = Param->getOriginalType(); + + const ArrayType *AT = Context.getAsArrayType(OrigTy); + if (!AT || AT->getSizeModifier() != ArrayType::Static) + return; + + if (ArgExpr->isNullPointerConstant(Context, + Expr::NPC_NeverValueDependent)) { + Diag(CallLoc, diag::warn_null_arg) << ArgExpr->getSourceRange(); + DiagnoseCalleeStaticArrayParam(*this, Param); + return; + } + + const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT); + if (!CAT) + return; + + const ConstantArrayType *ArgCAT = + Context.getAsConstantArrayType(ArgExpr->IgnoreParenImpCasts()->getType()); + if (!ArgCAT) + return; + + if (ArgCAT->getSize().ult(CAT->getSize())) { + Diag(CallLoc, diag::warn_static_array_too_small) + << ArgExpr->getSourceRange() + << (unsigned) ArgCAT->getSize().getZExtValue() + << (unsigned) CAT->getSize().getZExtValue(); + DiagnoseCalleeStaticArrayParam(*this, Param); + } +} + /// Given a function expression of unknown-any type, try to rebuild it /// to have a function type. static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn); @@ -3499,7 +3606,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, Expr **Args = ArgExprs.release(); - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { // If this is a pseudo-destructor expression, build the call immediately. if (isa<CXXPseudoDestructorExpr>(Fn)) { if (NumArgs > 0) { @@ -3508,8 +3615,6 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, << FixItHint::CreateRemoval( SourceRange(Args[0]->getLocStart(), Args[NumArgs-1]->getLocEnd())); - - NumArgs = 0; } return Owned(new (Context) CallExpr(Context, Fn, 0, 0, Context.VoidTy, @@ -3523,7 +3628,8 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, bool Dependent = false; if (Fn->isTypeDependent()) Dependent = true; - else if (Expr::hasAnyTypeDependentArguments(Args, NumArgs)) + else if (Expr::hasAnyTypeDependentArguments( + llvm::makeArrayRef(Args, NumArgs))) Dependent = true; if (Dependent) { @@ -3574,6 +3680,11 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, } // If we're directly calling a function, get the appropriate declaration. + if (Fn->getType() == Context.UnknownAnyTy) { + ExprResult result = rebuildUnknownAnyFunction(*this, Fn); + if (result.isInvalid()) return ExprError(); + Fn = result.take(); + } Expr *NakedFn = Fn->IgnoreParens(); @@ -3601,7 +3712,8 @@ Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, QualType ConfigQTy = ConfigDecl->getType(); DeclRefExpr *ConfigDR = new (Context) DeclRefExpr( - ConfigDecl, ConfigQTy, VK_LValue, LLLLoc); + ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc); + MarkFunctionReferenced(LLLLoc, ConfigDecl); return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, 0, /*IsExecConfig=*/true); @@ -3698,7 +3810,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, << Fn->getType() << Fn->getSourceRange()); } - if (getLangOptions().CUDA) { + if (getLangOpts().CUDA) { if (Config) { // CUDA: Kernel calls must be to global functions if (FDecl && !FDecl->hasAttr<CUDAGlobalAttr>()) @@ -3719,7 +3831,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, // Check for a valid return type if (CheckCallReturnType(FuncT->getResultType(), - Fn->getSourceRange().getBegin(), TheCall, + Fn->getLocStart(), TheCall, FDecl)) return ExprError(); @@ -3778,7 +3890,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, Arg = ArgE.takeAs<Expr>(); } - if (RequireCompleteType(Arg->getSourceRange().getBegin(), + if (RequireCompleteType(Arg->getLocStart(), Arg->getType(), PDiag(diag::err_call_incomplete_argument) << Arg->getSourceRange())) @@ -3852,7 +3964,8 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, = InitializedEntity::InitializeTemporary(literalType); InitializationKind Kind = InitializationKind::CreateCStyleCast(LParenLoc, - SourceRange(LParenLoc, RParenLoc)); + SourceRange(LParenLoc, RParenLoc), + /*InitList=*/true); InitializationSequence InitSeq(*this, Entity, Kind, &LiteralExpr, 1); ExprResult Result = InitSeq.Perform(*this, Entity, Kind, MultiExprArg(*this, &LiteralExpr, 1), @@ -3868,7 +3981,7 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, } // In C, compound literals are l-values for some reason. - ExprValueKind VK = getLangOptions().CPlusPlus ? VK_RValue : VK_LValue; + ExprValueKind VK = getLangOpts().CPlusPlus ? VK_RValue : VK_LValue; return MaybeBindToTemporary( new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType, @@ -3881,6 +3994,20 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, unsigned NumInit = InitArgList.size(); Expr **InitList = InitArgList.release(); + // Immediately handle non-overload placeholders. Overloads can be + // resolved contextually, but everything else here can't. + for (unsigned I = 0; I != NumInit; ++I) { + if (InitList[I]->getType()->isNonOverloadPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(InitList[I]); + + // Ignore failures; dropping the entire initializer list because + // of one failure would be terrible for indexing/etc. + if (result.isInvalid()) continue; + + InitList[I] = result.take(); + } + } + // Semantic analysis for initializers is done by ActOnDeclarator() and // CheckInitializer() - it requires knowledge of the object being intialized. @@ -3896,7 +4023,7 @@ static void maybeExtendBlockObject(Sema &S, ExprResult &E) { assert(E.get()->isRValue()); // Only do this in an r-value context. - if (!S.getLangOptions().ObjCAutoRefCount) return; + if (!S.getLangOpts().ObjCAutoRefCount) return; E = ImplicitCastExpr::Create(S.Context, E.get()->getType(), CK_ARCExtendBlockObject, E.get(), @@ -3927,6 +4054,11 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { // pointers. Everything else should be possible. QualType SrcTy = Src.get()->getType(); + if (const AtomicType *SrcAtomicTy = SrcTy->getAs<AtomicType>()) + SrcTy = SrcAtomicTy->getValueType(); + if (const AtomicType *DestAtomicTy = DestTy->getAs<AtomicType>()) + DestTy = DestAtomicTy->getValueType(); + if (Context.hasSameUnqualifiedType(SrcTy, DestTy)) return CK_NoOp; @@ -3946,12 +4078,10 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { case Type::STK_ObjCObjectPointer: if (SrcKind == Type::STK_ObjCObjectPointer) return CK_BitCast; - else if (SrcKind == Type::STK_CPointer) + if (SrcKind == Type::STK_CPointer) return CK_CPointerToObjCPointerCast; - else { - maybeExtendBlockObject(*this, Src); - return CK_BlockPointerToObjCPointerCast; - } + maybeExtendBlockObject(*this, Src); + return CK_BlockPointerToObjCPointerCast; case Type::STK_Bool: return CK_PointerToBoolean; case Type::STK_Integral: @@ -3962,7 +4092,7 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { case Type::STK_MemberPointer: llvm_unreachable("illegal cast from pointer"); } - break; + llvm_unreachable("Should have returned before this"); case Type::STK_Bool: // casting from bool is like casting from an integer case Type::STK_Integral: @@ -3993,7 +4123,7 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { case Type::STK_MemberPointer: llvm_unreachable("member pointer type in C"); } - break; + llvm_unreachable("Should have returned before this"); case Type::STK_Floating: switch (DestTy->getScalarTypeKind()) { @@ -4020,7 +4150,7 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { case Type::STK_MemberPointer: llvm_unreachable("member pointer type in C"); } - break; + llvm_unreachable("Should have returned before this"); case Type::STK_FloatingComplex: switch (DestTy->getScalarTypeKind()) { @@ -4049,7 +4179,7 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { case Type::STK_MemberPointer: llvm_unreachable("member pointer type in C"); } - break; + llvm_unreachable("Should have returned before this"); case Type::STK_IntegralComplex: switch (DestTy->getScalarTypeKind()) { @@ -4078,7 +4208,7 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { case Type::STK_MemberPointer: llvm_unreachable("member pointer type in C"); } - break; + llvm_unreachable("Should have returned before this"); } llvm_unreachable("Unhandled scalar cast"); @@ -4116,7 +4246,7 @@ ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, // (See OpenCL 6.2). if (SrcTy->isVectorType()) { if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy) - || (getLangOptions().OpenCL && + || (getLangOpts().OpenCL && (DestTy.getCanonicalType() != SrcTy.getCanonicalType()))) { Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors) << DestTy << SrcTy << R; @@ -4156,7 +4286,7 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, if (D.isInvalidType()) return ExprError(); - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { // Check that there are no default arguments (C++ only). CheckExtraCXXDefaultArguments(D); } @@ -4172,7 +4302,7 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, // i.e. all the elements are integer constants. ParenExpr *PE = dyn_cast<ParenExpr>(CastExpr); ParenListExpr *PLE = dyn_cast<ParenListExpr>(CastExpr); - if ((getLangOptions().AltiVec || getLangOptions().OpenCL) + if ((getLangOpts().AltiVec || getLangOpts().OpenCL) && castType->isVectorType() && (PE || PLE)) { if (PLE && PLE->getNumExprs() == 0) { Diag(PLE->getExprLoc(), diag::err_altivec_empty_initializer); @@ -4239,7 +4369,9 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc, // be replicated to all the components of the vector if (numExprs == 1) { QualType ElemTy = Ty->getAs<VectorType>()->getElementType(); - ExprResult Literal = Owned(exprs[0]); + ExprResult Literal = DefaultLvalueConversion(exprs[0]); + if (Literal.isInvalid()) + return ExprError(); Literal = ImpCastExprToType(Literal.take(), ElemTy, PrepareScalarCast(Literal, ElemTy)); return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.take()); @@ -4250,24 +4382,24 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc, return ExprError(); } else - for (unsigned i = 0, e = numExprs; i != e; ++i) - initExprs.push_back(exprs[i]); + initExprs.append(exprs, exprs + numExprs); } else { // For OpenCL, when the number of initializers is a single value, // it will be replicated to all components of the vector. - if (getLangOptions().OpenCL && + if (getLangOpts().OpenCL && VTy->getVectorKind() == VectorType::GenericVector && numExprs == 1) { QualType ElemTy = Ty->getAs<VectorType>()->getElementType(); - ExprResult Literal = Owned(exprs[0]); + ExprResult Literal = DefaultLvalueConversion(exprs[0]); + if (Literal.isInvalid()) + return ExprError(); Literal = ImpCastExprToType(Literal.take(), ElemTy, PrepareScalarCast(Literal, ElemTy)); return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.take()); } - for (unsigned i = 0, e = numExprs; i != e; ++i) - initExprs.push_back(exprs[i]); + initExprs.append(exprs, exprs + numExprs); } // FIXME: This means that pretty-printing the final AST will produce curly // braces instead of the original commas. @@ -4278,8 +4410,8 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc, return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, initE); } -/// This is not an AltiVec-style cast, so turn the ParenListExpr into a sequence -/// of comma binary operators. +/// This is not an AltiVec-style cast or or C++ direct-initialization, so turn +/// the ParenListExpr into a sequence of comma binary operators. ExprResult Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) { ParenListExpr *E = dyn_cast<ParenListExpr>(OrigExpr); @@ -4297,18 +4429,13 @@ Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) { return ActOnParenExpr(E->getLParenLoc(), E->getRParenLoc(), Result.get()); } -ExprResult Sema::ActOnParenOrParenListExpr(SourceLocation L, - SourceLocation R, - MultiExprArg Val) { +ExprResult Sema::ActOnParenListExpr(SourceLocation L, + SourceLocation R, + MultiExprArg Val) { unsigned nexprs = Val.size(); Expr **exprs = reinterpret_cast<Expr**>(Val.release()); assert((exprs != 0) && "ActOnParenOrParenListExpr() missing expr list"); - Expr *expr; - if (nexprs == 1) - expr = new (Context) ParenExpr(L, R, exprs[0]); - else - expr = new (Context) ParenListExpr(Context, L, exprs, nexprs, R, - exprs[nexprs-1]->getType()); + Expr *expr = new (Context) ParenListExpr(Context, L, exprs, nexprs, R); return Owned(expr); } @@ -4358,11 +4485,11 @@ static bool checkCondition(Sema &S, Expr *Cond) { if (CondTy->isScalarType()) return false; // OpenCL: Sec 6.3.i says the condition is allowed to be a vector or scalar. - if (S.getLangOptions().OpenCL && CondTy->isVectorType()) + if (S.getLangOpts().OpenCL && CondTy->isVectorType()) return false; // Emit the proper error message. - S.Diag(Cond->getLocStart(), S.getLangOptions().OpenCL ? + S.Diag(Cond->getLocStart(), S.getLangOpts().OpenCL ? diag::err_typecheck_cond_expect_scalar : diag::err_typecheck_cond_expect_scalar_or_vector) << CondTy; @@ -4446,8 +4573,28 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS, rhptee = RHSTy->castAs<PointerType>()->getPointeeType(); } - if (!S.Context.typesAreCompatible(lhptee.getUnqualifiedType(), - rhptee.getUnqualifiedType())) { + // C99 6.5.15p6: If both operands are pointers to compatible types or to + // differently qualified versions of compatible types, the result type is + // a pointer to an appropriately qualified version of the composite + // type. + + // Only CVR-qualifiers exist in the standard, and the differently-qualified + // clause doesn't make sense for our extensions. E.g. address space 2 should + // be incompatible with address space 3: they may live on different devices or + // anything. + Qualifiers lhQual = lhptee.getQualifiers(); + Qualifiers rhQual = rhptee.getQualifiers(); + + unsigned MergedCVRQual = lhQual.getCVRQualifiers() | rhQual.getCVRQualifiers(); + lhQual.removeCVRQualifiers(); + rhQual.removeCVRQualifiers(); + + lhptee = S.Context.getQualifiedType(lhptee.getUnqualifiedType(), lhQual); + rhptee = S.Context.getQualifiedType(rhptee.getUnqualifiedType(), rhQual); + + QualType CompositeTy = S.Context.mergeTypes(lhptee, rhptee); + + if (CompositeTy.isNull()) { S.Diag(Loc, diag::warn_typecheck_cond_incompatible_pointers) << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); @@ -4461,16 +4608,12 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS, } // The pointer types are compatible. - // C99 6.5.15p6: If both operands are pointers to compatible types *or* to - // differently qualified versions of compatible types, the result type is - // a pointer to an appropriately qualified version of the *composite* - // type. - // FIXME: Need to calculate the composite type. - // FIXME: Need to add qualifiers + QualType ResultTy = CompositeTy.withCVRQualifiers(MergedCVRQual); + ResultTy = S.Context.getPointerType(ResultTy); - LHS = S.ImpCastExprToType(LHS.take(), LHSTy, CK_BitCast); - RHS = S.ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); - return LHSTy; + LHS = S.ImpCastExprToType(LHS.take(), ResultTy, CK_BitCast); + RHS = S.ImpCastExprToType(RHS.take(), ResultTy, CK_BitCast); + return ResultTy; } /// \brief Return the resulting type when the operands are both block pointers. @@ -4574,7 +4717,7 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, RHS = move(RHSResult); // C++ is sufficiently different to merit its own checker. - if (getLangOptions().CPlusPlus) + if (getLangOpts().CPlusPlus) return CXXCheckConditionalOperands(Cond, LHS, RHS, VK, OK, QuestionLoc); VK = VK_RValue; @@ -4605,7 +4748,7 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, // OpenCL: If the condition is a vector, and both operands are scalar, // attempt to implicity convert them to the vector type to act like the // built in select. - if (getLangOptions().OpenCL && CondTy->isVectorType()) + if (getLangOpts().OpenCL && CondTy->isVectorType()) if (checkConditionalConvertScalarsToVectors(*this, LHS, RHS, CondTy)) return QualType(); @@ -4780,6 +4923,14 @@ QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, } // Check Objective-C object pointer types and 'void *' if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) { + if (getLangOpts().ObjCAutoRefCount) { + // ARC forbids the implicit conversion of object pointers to 'void *', + // so these types are not compatible. + Diag(QuestionLoc, diag::err_cond_voidptr_arc) << LHSTy << RHSTy + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + LHS = RHS = true; + return QualType(); + } QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType(); QualType rhptee = RHSTy->getAs<ObjCObjectPointerType>()->getPointeeType(); QualType destPointee @@ -4792,6 +4943,14 @@ QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, return destType; } if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) { + if (getLangOpts().ObjCAutoRefCount) { + // ARC forbids the implicit conversion of object pointers to 'void *', + // so these types are not compatible. + Diag(QuestionLoc, diag::err_cond_voidptr_arc) << LHSTy << RHSTy + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + LHS = RHS = true; + return QualType(); + } QualType lhptee = LHSTy->getAs<ObjCObjectPointerType>()->getPointeeType(); QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType(); QualType destPointee @@ -4938,7 +5097,7 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, // We usually want to apply unary conversions *before* saving, except // in the special case of a C++ l-value conditional. - if (!(getLangOptions().CPlusPlus + if (!(getLangOpts().CPlusPlus && !commonExpr->isTypeDependent() && commonExpr->getValueKind() == RHSExpr->getValueKind() && commonExpr->isGLValue() @@ -4954,7 +5113,8 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, opaqueValue = new (Context) OpaqueValueExpr(commonExpr->getExprLoc(), commonExpr->getType(), commonExpr->getValueKind(), - commonExpr->getObjectKind()); + commonExpr->getObjectKind(), + commonExpr); LHSExpr = CondExpr = opaqueValue; } @@ -5019,9 +5179,9 @@ checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) { // It's okay to add or remove GC or lifetime qualifiers when converting to // and from void*. - else if (lhq.withoutObjCGCAttr().withoutObjCGLifetime() + else if (lhq.withoutObjCGCAttr().withoutObjCLifetime() .compatiblyIncludes( - rhq.withoutObjCGCAttr().withoutObjCGLifetime()) + rhq.withoutObjCGCAttr().withoutObjCLifetime()) && (lhptee->isVoidType() || rhptee->isVoidType())) ; // keep old @@ -5099,7 +5259,7 @@ checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) { // General pointer incompatibility takes priority over qualifiers. return Sema::IncompatiblePointer; } - if (!S.getLangOptions().CPlusPlus && + if (!S.getLangOpts().CPlusPlus && S.IsNoReturnConversion(ltrans, rtrans, ltrans)) return Sema::IncompatiblePointer; return ConvTy; @@ -5122,7 +5282,7 @@ checkBlockPointerTypesForAssignment(Sema &S, QualType LHSType, rhptee = cast<BlockPointerType>(RHSType)->getPointeeType(); // In C++, the types have to match exactly. - if (S.getLangOptions().CPlusPlus) + if (S.getLangOpts().CPlusPlus) return Sema::IncompatibleBlockPointer; Sema::AssignConvertType ConvTy = Sema::Compatible; @@ -5161,7 +5321,9 @@ checkObjCPointerTypesForAssignment(Sema &S, QualType LHSType, QualType lhptee = LHSType->getAs<ObjCObjectPointerType>()->getPointeeType(); QualType rhptee = RHSType->getAs<ObjCObjectPointerType>()->getPointeeType(); - if (!lhptee.isAtLeastAsQualifiedAs(rhptee)) + if (!lhptee.isAtLeastAsQualifiedAs(rhptee) && + // make an exception for id<P> + !LHSType->isObjCQualifiedIdType()) return Sema::CompatiblePointerDiscardsQualifiers; if (S.Context.typesAreCompatible(LHSType, RHSType)) @@ -5213,9 +5375,6 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, LHSType = Context.getCanonicalType(LHSType).getUnqualifiedType(); RHSType = Context.getCanonicalType(RHSType).getUnqualifiedType(); - // We can't do assignment from/to atomics yet. - if (LHSType->isAtomicType()) - return Incompatible; // Common case: no conversion required. if (LHSType == RHSType) { @@ -5223,6 +5382,21 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, return Compatible; } + if (const AtomicType *AtomicTy = dyn_cast<AtomicType>(LHSType)) { + if (AtomicTy->getValueType() == RHSType) { + Kind = CK_NonAtomicToAtomic; + return Compatible; + } + } + + if (const AtomicType *AtomicTy = dyn_cast<AtomicType>(RHSType)) { + if (AtomicTy->getValueType() == LHSType) { + Kind = CK_AtomicToNonAtomic; + return Compatible; + } + } + + // If the left-hand side is a reference type, then we are in a // (rare!) case where we've allowed the use of references in C, // e.g., as a parameter type in a built-in function. In this case, @@ -5269,7 +5443,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 (getLangOptions().LaxVectorConversions && + if (getLangOpts().LaxVectorConversions && (Context.getTypeSize(LHSType) == Context.getTypeSize(RHSType))) { Kind = CK_BitCast; return IncompatibleVectors; @@ -5280,7 +5454,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, // Arithmetic conversions. if (LHSType->isArithmeticType() && RHSType->isArithmeticType() && - !(getLangOptions().CPlusPlus && LHSType->isEnumeralType())) { + !(getLangOpts().CPlusPlus && LHSType->isEnumeralType())) { Kind = PrepareScalarCast(RHS, LHSType); return Compatible; } @@ -5346,7 +5520,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, } // id -> T^ - if (getLangOptions().ObjC1 && RHSType->isObjCIdType()) { + if (getLangOpts().ObjC1 && RHSType->isObjCIdType()) { Kind = CK_AnyPointerToBlockPointerCast; return Compatible; } @@ -5368,7 +5542,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, Kind = CK_BitCast; Sema::AssignConvertType result = checkObjCPointerTypesForAssignment(*this, LHSType, RHSType); - if (getLangOptions().ObjCAutoRefCount && + if (getLangOpts().ObjCAutoRefCount && result == Compatible && !CheckObjCARCUnavailableWeakConversion(OrigLHSType, RHSType)) result = IncompatibleObjCWeakRef; @@ -5535,18 +5709,32 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Sema::AssignConvertType Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, bool Diagnose) { - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { if (!LHSType->isRecordType() && !LHSType->isAtomicType()) { // C++ 5.17p3: If the left operand is not of class type, the // expression is implicitly converted (C++ 4) to the // cv-unqualified type of the left operand. - ExprResult Res = PerformImplicitConversion(RHS.get(), - LHSType.getUnqualifiedType(), - AA_Assigning, Diagnose); + ExprResult Res; + if (Diagnose) { + Res = PerformImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(), + AA_Assigning); + } else { + ImplicitConversionSequence ICS = + TryImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(), + /*SuppressUserConversions=*/false, + /*AllowExplicit=*/false, + /*InOverloadResolution=*/false, + /*CStyle=*/false, + /*AllowObjCWritebackConversion=*/false); + if (ICS.isFailure()) + return Incompatible; + Res = PerformImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(), + ICS, AA_Assigning); + } if (Res.isInvalid()) return Incompatible; Sema::AssignConvertType result = Compatible; - if (getLangOptions().ObjCAutoRefCount && + if (getLangOpts().ObjCAutoRefCount && !CheckObjCARCUnavailableWeakConversion(LHSType, RHS.get()->getType())) result = IncompatibleObjCWeakRef; @@ -5609,6 +5797,15 @@ QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS, QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign) { + if (!IsCompAssign) { + LHS = DefaultFunctionArrayLvalueConversion(LHS.take()); + if (LHS.isInvalid()) + return QualType(); + } + RHS = DefaultFunctionArrayLvalueConversion(RHS.take()); + if (RHS.isInvalid()) + return QualType(); + // For conversion purposes, we ignore any qualifiers. // For example, "const float" and "float" are equivalent. QualType LHSType = @@ -5633,7 +5830,7 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, return RHSType; } - if (getLangOptions().LaxVectorConversions && + 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 @@ -5738,9 +5935,15 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS, if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); + if (!LHS.get()->getType()->isArithmeticType() || - !RHS.get()->getType()->isArithmeticType()) + !RHS.get()->getType()->isArithmeticType()) { + if (IsCompAssign && + LHS.get()->getType()->isAtomicType() && + RHS.get()->getType()->isArithmeticType()) + return compType; return InvalidOperands(Loc, LHS, RHS); + } // Check for division by zero. if (IsDiv && @@ -5784,7 +5987,7 @@ QualType Sema::CheckRemainderOperands( /// \brief Diagnose invalid arithmetic on two void pointers. static void diagnoseArithmeticOnTwoVoidPointers(Sema &S, SourceLocation Loc, Expr *LHSExpr, Expr *RHSExpr) { - S.Diag(Loc, S.getLangOptions().CPlusPlus + S.Diag(Loc, S.getLangOpts().CPlusPlus ? diag::err_typecheck_pointer_arith_void_type : diag::ext_gnu_void_ptr) << 1 /* two pointers */ << LHSExpr->getSourceRange() @@ -5794,7 +5997,7 @@ static void diagnoseArithmeticOnTwoVoidPointers(Sema &S, SourceLocation Loc, /// \brief Diagnose invalid arithmetic on a void pointer. static void diagnoseArithmeticOnVoidPointer(Sema &S, SourceLocation Loc, Expr *Pointer) { - S.Diag(Loc, S.getLangOptions().CPlusPlus + S.Diag(Loc, S.getLangOpts().CPlusPlus ? diag::err_typecheck_pointer_arith_void_type : diag::ext_gnu_void_ptr) << 0 /* one pointer */ << Pointer->getSourceRange(); @@ -5805,7 +6008,7 @@ static void diagnoseArithmeticOnTwoFunctionPointers(Sema &S, SourceLocation Loc, Expr *LHS, Expr *RHS) { assert(LHS->getType()->isAnyPointerType()); assert(RHS->getType()->isAnyPointerType()); - S.Diag(Loc, S.getLangOptions().CPlusPlus + S.Diag(Loc, S.getLangOpts().CPlusPlus ? diag::err_typecheck_pointer_arith_function_type : diag::ext_gnu_ptr_func_arith) << 1 /* two pointers */ << LHS->getType()->getPointeeType() @@ -5820,7 +6023,7 @@ static void diagnoseArithmeticOnTwoFunctionPointers(Sema &S, SourceLocation Loc, static void diagnoseArithmeticOnFunctionPointer(Sema &S, SourceLocation Loc, Expr *Pointer) { assert(Pointer->getType()->isAnyPointerType()); - S.Diag(Loc, S.getLangOptions().CPlusPlus + S.Diag(Loc, S.getLangOpts().CPlusPlus ? diag::err_typecheck_pointer_arith_function_type : diag::ext_gnu_ptr_func_arith) << 0 /* one pointer */ << Pointer->getType()->getPointeeType() @@ -5861,11 +6064,11 @@ static bool checkArithmeticOpPointerOperand(Sema &S, SourceLocation Loc, QualType PointeeTy = Operand->getType()->getPointeeType(); if (PointeeTy->isVoidType()) { diagnoseArithmeticOnVoidPointer(S, Loc, Operand); - return !S.getLangOptions().CPlusPlus; + return !S.getLangOpts().CPlusPlus; } if (PointeeTy->isFunctionType()) { diagnoseArithmeticOnFunctionPointer(S, Loc, Operand); - return !S.getLangOptions().CPlusPlus; + return !S.getLangOpts().CPlusPlus; } if (checkArithmeticIncompletePointerType(S, Loc, Operand)) return false; @@ -5900,7 +6103,7 @@ static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc, else if (!isLHSVoidPtr) diagnoseArithmeticOnVoidPointer(S, Loc, RHSExpr); else diagnoseArithmeticOnTwoVoidPointers(S, Loc, LHSExpr, RHSExpr); - return !S.getLangOptions().CPlusPlus; + return !S.getLangOpts().CPlusPlus; } bool isLHSFuncPtr = isLHSPointer && LHSPointeeTy->isFunctionType(); @@ -5911,7 +6114,7 @@ static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc, RHSExpr); else diagnoseArithmeticOnTwoFunctionPointers(S, Loc, LHSExpr, RHSExpr); - return !S.getLangOptions().CPlusPlus; + return !S.getLangOpts().CPlusPlus; } if (checkArithmeticIncompletePointerType(S, Loc, LHSExpr)) return false; @@ -5934,6 +6137,46 @@ static bool checkArithmethicPointerOnNonFragileABI(Sema &S, return false; } +/// diagnoseStringPlusInt - Emit a warning when adding an integer to a string +/// literal. +static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc, + Expr *LHSExpr, Expr *RHSExpr) { + StringLiteral* StrExpr = dyn_cast<StringLiteral>(LHSExpr->IgnoreImpCasts()); + Expr* IndexExpr = RHSExpr; + if (!StrExpr) { + StrExpr = dyn_cast<StringLiteral>(RHSExpr->IgnoreImpCasts()); + IndexExpr = LHSExpr; + } + + bool IsStringPlusInt = StrExpr && + IndexExpr->getType()->isIntegralOrUnscopedEnumerationType(); + if (!IsStringPlusInt) + return; + + llvm::APSInt index; + if (IndexExpr->EvaluateAsInt(index, Self.getASTContext())) { + unsigned StrLenWithNull = StrExpr->getLength() + 1; + if (index.isNonNegative() && + index <= llvm::APSInt(llvm::APInt(index.getBitWidth(), StrLenWithNull), + index.isUnsigned())) + return; + } + + SourceRange DiagRange(LHSExpr->getLocStart(), RHSExpr->getLocEnd()); + Self.Diag(OpLoc, diag::warn_string_plus_int) + << DiagRange << IndexExpr->IgnoreImpCasts()->getType(); + + // Only print a fixit for "str" + int, not for int + "str". + if (IndexExpr == RHSExpr) { + SourceLocation EndLoc = Self.PP.getLocForEndOfToken(RHSExpr->getLocEnd()); + Self.Diag(OpLoc, diag::note_string_plus_int_silence) + << FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&") + << FixItHint::CreateReplacement(SourceRange(OpLoc), "[") + << FixItHint::CreateInsertion(EndLoc, "]"); + } else + Self.Diag(OpLoc, diag::note_string_plus_int_silence); +} + /// \brief Emit error when two pointers are incompatible. static void diagnosePointerIncompatibility(Sema &S, SourceLocation Loc, Expr *LHSExpr, Expr *RHSExpr) { @@ -5945,7 +6188,8 @@ static void diagnosePointerIncompatibility(Sema &S, SourceLocation Loc, } QualType Sema::CheckAdditionOperands( // C99 6.5.6 - ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, QualType* CompLHSTy) { + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc, + QualType* CompLHSTy) { checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false); if (LHS.get()->getType()->isVectorType() || @@ -5959,6 +6203,10 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6 if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); + // Diagnose "string literal" '+' int. + if (Opc == BO_Add) + diagnoseStringPlusInt(*this, Loc, LHS.get(), RHS.get()); + // handle the common case first (both operands are arithmetic). if (LHS.get()->getType()->isArithmeticType() && RHS.get()->getType()->isArithmeticType()) { @@ -5966,6 +6214,12 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6 return compType; } + if (LHS.get()->getType()->isAtomicType() && + RHS.get()->getType()->isArithmeticType()) { + *CompLHSTy = LHS.get()->getType(); + return compType; + } + // Put any potential pointer into PExp Expr* PExp = LHS.get(), *IExp = RHS.get(); if (IExp->getType()->isAnyPointerType()) @@ -6026,6 +6280,12 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, return compType; } + if (LHS.get()->getType()->isAtomicType() && + RHS.get()->getType()->isArithmeticType()) { + *CompLHSTy = LHS.get()->getType(); + return compType; + } + // Either ptr - int or ptr - ptr. if (LHS.get()->getType()->isAnyPointerType()) { QualType lpointee = LHS.get()->getType()->getPointeeType(); @@ -6039,11 +6299,9 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, if (!checkArithmeticOpPointerOperand(*this, Loc, LHS.get())) return QualType(); - Expr *IExpr = RHS.get()->IgnoreParenCasts(); - UnaryOperator negRex(IExpr, UO_Minus, IExpr->getType(), VK_RValue, - OK_Ordinary, IExpr->getExprLoc()); // Check array bounds for pointer arithemtic - CheckArrayAccess(LHS.get()->IgnoreParenCasts(), &negRex); + CheckArrayAccess(LHS.get(), RHS.get(), /*ArraySubscriptExpr*/0, + /*AllowOnePastEnd*/true, /*IndexNegated*/true); if (CompLHSTy) *CompLHSTy = LHS.get()->getType(); return LHS.get()->getType(); @@ -6054,7 +6312,7 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, = RHS.get()->getType()->getAs<PointerType>()) { QualType rpointee = RHSPTy->getPointeeType(); - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { // Pointee types must be the same: C++ [expr.add] if (!Context.hasSameUnqualifiedType(lpointee, rpointee)) { diagnosePointerIncompatibility(*this, Loc, LHS.get(), RHS.get()); @@ -6131,7 +6389,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, // Print the bit representation of the signed integer as an unsigned // hexadecimal number. - llvm::SmallString<40> HexResult; + SmallString<40> HexResult; Result.toString(HexResult, 16, /*Signed =*/false, /*Literal =*/true); // If we are only missing a sign bit, this is less likely to result in actual @@ -6459,7 +6717,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, QualType RCanPointeeTy = RHSType->castAs<PointerType>()->getPointeeType().getCanonicalType(); - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { if (LCanPointeeTy == RCanPointeeTy) return ResultTy; if (!IsRelational && @@ -6515,7 +6773,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, return ResultTy; } - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { // Comparison of nullptr_t with itself. if (LHSType->isNullPtrType() && RHSType->isNullPtrType()) return ResultTy; @@ -6639,11 +6897,11 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, bool isError = false; if ((LHSIsNull && LHSType->isIntegerType()) || (RHSIsNull && RHSType->isIntegerType())) { - if (IsRelational && !getLangOptions().CPlusPlus) + if (IsRelational && !getLangOpts().CPlusPlus) DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_and_zero; - } else if (IsRelational && !getLangOptions().CPlusPlus) + } else if (IsRelational && !getLangOpts().CPlusPlus) DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer; - else if (getLangOptions().CPlusPlus) { + else if (getLangOpts().CPlusPlus) { DiagID = diag::err_typecheck_comparison_of_pointer_integer; isError = true; } else @@ -6681,6 +6939,26 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, return InvalidOperands(Loc, LHS, RHS); } + +// Return a signed type that is of identical size and number of elements. +// For floating point vectors, return an integer type of identical size +// and number of elements. +QualType Sema::GetSignedVectorType(QualType V) { + const VectorType *VTy = V->getAs<VectorType>(); + unsigned TypeSize = Context.getTypeSize(VTy->getElementType()); + if (TypeSize == Context.getTypeSize(Context.CharTy)) + return Context.getExtVectorType(Context.CharTy, VTy->getNumElements()); + else if (TypeSize == Context.getTypeSize(Context.ShortTy)) + return Context.getExtVectorType(Context.ShortTy, VTy->getNumElements()); + else if (TypeSize == Context.getTypeSize(Context.IntTy)) + return Context.getExtVectorType(Context.IntTy, VTy->getNumElements()); + else if (TypeSize == Context.getTypeSize(Context.LongTy)) + return Context.getExtVectorType(Context.LongTy, VTy->getNumElements()); + assert(TypeSize == Context.getTypeSize(Context.LongLongTy) && + "Unhandled vector element size in vector compare"); + return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements()); +} + /// CheckVectorCompareOperands - vector comparisons are a clang extension that /// operates on extended vector types. Instead of producing an IntTy result, /// like a scalar comparison, a vector comparison produces a vector of integer @@ -6695,7 +6973,6 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, return vType; QualType LHSType = LHS.get()->getType(); - QualType RHSType = RHS.get()->getType(); // If AltiVec, the comparison results in a numeric type, i.e. // bool for C++, int for C @@ -6706,8 +6983,10 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, // x == x, x != x, x < x, etc. These always evaluate to a constant, and // often indicate logic errors in the program. if (!LHSType->hasFloatingRepresentation()) { - if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHS.get()->IgnoreParens())) - if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHS.get()->IgnoreParens())) + if (DeclRefExpr* DRL + = dyn_cast<DeclRefExpr>(LHS.get()->IgnoreParenImpCasts())) + if (DeclRefExpr* DRR + = dyn_cast<DeclRefExpr>(RHS.get()->IgnoreParenImpCasts())) if (DRL->getDecl() == DRR->getDecl()) DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) @@ -6718,26 +6997,23 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, // Check for comparisons of floating point operands using != and ==. if (!IsRelational && LHSType->hasFloatingRepresentation()) { - assert (RHSType->hasFloatingRepresentation()); + assert (RHS.get()->getType()->hasFloatingRepresentation()); CheckFloatComparison(Loc, LHS.get(), RHS.get()); } + + // Return a signed type for the vector. + return GetSignedVectorType(LHSType); +} - // Return the type for the comparison, which is the same as vector type for - // integer vectors, or an integer type of identical size and number of - // elements for floating point vectors. - if (LHSType->hasIntegerRepresentation()) - return LHSType; - - const VectorType *VTy = LHSType->getAs<VectorType>(); - unsigned TypeSize = Context.getTypeSize(VTy->getElementType()); - if (TypeSize == Context.getTypeSize(Context.IntTy)) - return Context.getExtVectorType(Context.IntTy, VTy->getNumElements()); - if (TypeSize == Context.getTypeSize(Context.LongTy)) - return Context.getExtVectorType(Context.LongTy, VTy->getNumElements()); - - assert(TypeSize == Context.getTypeSize(Context.LongLongTy) && - "Unhandled vector element size in vector compare"); - return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements()); +QualType Sema::CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc) { + // Ensure that either both operands are of the same vector type, or + // one operand is of a vector type and the other is of its element type. + QualType vType = CheckVectorOperands(LHS, RHS, Loc, false); + if (vType.isNull() || vType->isFloatingType()) + return InvalidOperands(Loc, LHS, RHS); + + return GetSignedVectorType(LHS.get()->getType()); } inline QualType Sema::CheckBitwiseOperands( @@ -6770,6 +7046,10 @@ inline QualType Sema::CheckBitwiseOperands( inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc) { + // Check vector operands differently. + if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType()) + return CheckVectorLogicalOperands(LHS, RHS, Loc); + // Diagnose cases where the user write a logical and/or but probably meant a // bitwise one. We do this when the LHS is a non-bool integer and the RHS // is a constant. @@ -6782,10 +7062,10 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] // that isn't 0 or 1 (which indicate a potential logical operation that // happened to fold to true/false) then warn. // Parens on the RHS are ignored. - Expr::EvalResult Result; - if (RHS.get()->Evaluate(Result, Context) && !Result.HasSideEffects) - if ((getLangOptions().Bool && !RHS.get()->getType()->isBooleanType()) || - (Result.Val.getInt() != 0 && Result.Val.getInt() != 1)) { + llvm::APSInt Result; + if (RHS.get()->EvaluateAsInt(Result, Context)) + if ((getLangOpts().Bool && !RHS.get()->getType()->isBooleanType()) || + (Result != 0 && Result != 1)) { Diag(Loc, diag::warn_logical_instead_of_bitwise) << RHS.get()->getSourceRange() << (Opc == BO_LAnd ? "&&" : "||"); @@ -6794,7 +7074,7 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] << (Opc == BO_LAnd ? "&" : "|") << FixItHint::CreateReplacement(SourceRange( Loc, Lexer::getLocForEndOfToken(Loc, 0, getSourceManager(), - getLangOptions())), + getLangOpts())), Opc == BO_LAnd ? "&" : "|"); if (Opc == BO_LAnd) // Suggest replacing "Foo() && kNonZero" with "Foo()" @@ -6803,12 +7083,12 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] SourceRange( Lexer::getLocForEndOfToken(LHS.get()->getLocEnd(), 0, getSourceManager(), - getLangOptions()), + getLangOpts()), RHS.get()->getLocEnd())); } } - if (!Context.getLangOptions().CPlusPlus) { + if (!Context.getLangOpts().CPlusPlus) { LHS = UsualUnaryConversions(LHS.take()); if (LHS.isInvalid()) return QualType(); @@ -6851,63 +7131,68 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] /// depends on various declarations and thus must be treated specially. /// static bool IsReadonlyProperty(Expr *E, Sema &S) { - if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) { - const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E); - if (PropExpr->isImplicitProperty()) return false; + const ObjCPropertyRefExpr *PropExpr = dyn_cast<ObjCPropertyRefExpr>(E); + if (!PropExpr) return false; + if (PropExpr->isImplicitProperty()) return false; - ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty(); - QualType BaseType = PropExpr->isSuperReceiver() ? + ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty(); + QualType BaseType = PropExpr->isSuperReceiver() ? PropExpr->getSuperReceiverType() : PropExpr->getBase()->getType(); - if (const ObjCObjectPointerType *OPT = - BaseType->getAsObjCInterfacePointerType()) - if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl()) - if (S.isPropertyReadonly(PDecl, IFace)) - return true; - } - return false; -} - -static bool IsConstProperty(Expr *E, Sema &S) { - if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) { - const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E); - if (PropExpr->isImplicitProperty()) return false; - - ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty(); - QualType T = PDecl->getType(); - if (T->isReferenceType()) - T = T->getAs<ReferenceType>()->getPointeeType(); - CanQualType CT = S.Context.getCanonicalType(T); - return CT.isConstQualified(); - } + if (const ObjCObjectPointerType *OPT = + BaseType->getAsObjCInterfacePointerType()) + if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl()) + if (S.isPropertyReadonly(PDecl, IFace)) + return true; return false; } static bool IsReadonlyMessage(Expr *E, Sema &S) { - if (E->getStmtClass() != Expr::MemberExprClass) - return false; - const MemberExpr *ME = cast<MemberExpr>(E); - NamedDecl *Member = ME->getMemberDecl(); - if (isa<FieldDecl>(Member)) { - Expr *Base = ME->getBase()->IgnoreParenImpCasts(); - if (Base->getStmtClass() != Expr::ObjCMessageExprClass) - return false; - return cast<ObjCMessageExpr>(Base)->getMethodDecl() != 0; - } - return false; + const MemberExpr *ME = dyn_cast<MemberExpr>(E); + if (!ME) return false; + if (!isa<FieldDecl>(ME->getMemberDecl())) return false; + ObjCMessageExpr *Base = + dyn_cast<ObjCMessageExpr>(ME->getBase()->IgnoreParenImpCasts()); + if (!Base) return false; + return Base->getMethodDecl() != 0; +} + +/// Is the given expression (which must be 'const') a reference to a +/// variable which was originally non-const, but which has become +/// 'const' due to being captured within a block? +enum NonConstCaptureKind { NCCK_None, NCCK_Block, NCCK_Lambda }; +static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) { + assert(E->isLValue() && E->getType().isConstQualified()); + E = E->IgnoreParens(); + + // Must be a reference to a declaration from an enclosing scope. + DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E); + if (!DRE) return NCCK_None; + if (!DRE->refersToEnclosingLocal()) return NCCK_None; + + // The declaration must be a variable which is not declared 'const'. + VarDecl *var = dyn_cast<VarDecl>(DRE->getDecl()); + if (!var) return NCCK_None; + if (var->getType().isConstQualified()) return NCCK_None; + 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; + while (DC->getParent() != var->getDeclContext()) + DC = DC->getParent(); + return (isa<BlockDecl>(DC) ? NCCK_Block : NCCK_Lambda); } /// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If not, /// emit an error and return true. If so, return false. static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { + assert(!E->hasPlaceholderType(BuiltinType::PseudoObject)); SourceLocation OrigLoc = Loc; Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context, &Loc); if (IsLV == Expr::MLV_Valid && IsReadonlyProperty(E, S)) IsLV = Expr::MLV_ReadonlyProperty; - else if (Expr::MLV_ConstQualified && IsConstProperty(E, S)) - IsLV = Expr::MLV_Valid; else if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S)) IsLV = Expr::MLV_InvalidMessageExpression; if (IsLV == Expr::MLV_Valid) @@ -6919,9 +7204,19 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { case Expr::MLV_ConstQualified: Diag = diag::err_typecheck_assign_const; + // Use a specialized diagnostic when we're assigning to an object + // from an enclosing function or block. + if (NonConstCaptureKind NCCK = isReferenceToNonConstCapture(S, E)) { + if (NCCK == NCCK_Block) + Diag = diag::err_block_decl_ref_not_modifiable_lvalue; + else + Diag = diag::err_lambda_decl_ref_not_modifiable_lvalue; + break; + } + // In ARC, use some specialized diagnostics for occasions where we // infer 'const'. These are always pseudo-strong variables. - if (S.getLangOptions().ObjCAutoRefCount) { + if (S.getLangOpts().ObjCAutoRefCount) { DeclRefExpr *declRef = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()); if (declRef && isa<VarDecl>(declRef->getDecl())) { VarDecl *var = cast<VarDecl>(declRef->getDecl()); @@ -6935,7 +7230,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { // - self ObjCMethodDecl *method = S.getCurMethodDecl(); if (method && var == method->getSelfDecl()) - Diag = diag::err_typecheck_arr_assign_self; + Diag = method->isClassMethod() + ? diag::err_typecheck_arc_assign_self_class_method + : diag::err_typecheck_arc_assign_self; // - fast enumeration variables else @@ -6979,15 +7276,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { case Expr::MLV_DuplicateVectorComponents: Diag = diag::err_typecheck_duplicate_vector_components_not_mlvalue; break; - case Expr::MLV_NotBlockQualified: - Diag = diag::err_block_decl_ref_not_modifiable_lvalue; - break; case Expr::MLV_ReadonlyProperty: - Diag = diag::error_readonly_property_assignment; - break; case Expr::MLV_NoSetterProperty: - Diag = diag::error_nosetter_property_assignment; - break; + llvm_unreachable("readonly properties should be processed differently"); case Expr::MLV_InvalidMessageExpression: Diag = diag::error_readonly_message_assignment; break; @@ -7012,6 +7303,8 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, SourceLocation Loc, QualType CompoundType) { + assert(!LHSExpr->hasPlaceholderType(BuiltinType::PseudoObject)); + // Verify that LHS is a modifiable lvalue, and emit error if not. if (CheckForModifiableLvalue(LHSExpr, Loc, *this)) return QualType(); @@ -7022,14 +7315,6 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, AssignConvertType ConvTy; if (CompoundType.isNull()) { QualType LHSTy(LHSType); - // Simple assignment "x = y". - if (LHSExpr->getObjectKind() == OK_ObjCProperty) { - ExprResult LHSResult = Owned(LHSExpr); - ConvertPropertyForLValue(LHSResult, RHS, LHSTy); - if (LHSResult.isInvalid()) - return QualType(); - LHSExpr = LHSResult.take(); - } ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS); if (RHS.isInvalid()) return QualType(); @@ -7042,10 +7327,9 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, ConvTy = Compatible; if (ConvTy == Compatible && - getLangOptions().ObjCNonFragileABI && LHSType->isObjCObjectType()) - Diag(Loc, diag::err_assignment_requires_nonfragile_object) - << LHSType; + Diag(Loc, diag::err_objc_object_assignment) + << LHSType; // If the RHS is a unary plus or minus, check to see if they = and + are // right next to each other. If so, the user may have typo'd "x =+ 4" @@ -7072,7 +7356,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, if (ConvTy == Compatible) { if (LHSType.getObjCLifetime() == Qualifiers::OCL_Strong) checkRetainCycles(LHSExpr, RHS.get()); - else if (getLangOptions().ObjCAutoRefCount) + else if (getLangOpts().ObjCAutoRefCount) checkUnsafeExprAssigns(Loc, LHSExpr, RHS.get()); } } else { @@ -7093,7 +7377,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, // is converted to the type of the assignment expression (above). // C++ 5.17p1: the type of the assignment expression is that of its left // operand. - return (getLangOptions().CPlusPlus + return (getLangOpts().CPlusPlus ? LHSType : LHSType.getUnqualifiedType()); } @@ -7117,7 +7401,7 @@ static QualType CheckCommaOperands(Sema &S, ExprResult &LHS, ExprResult &RHS, if (LHS.isInvalid()) return QualType(); - if (!S.getLangOptions().CPlusPlus) { + if (!S.getLangOpts().CPlusPlus) { RHS = S.DefaultFunctionArrayLvalueConversion(RHS.take()); if (RHS.isInvalid()) return QualType(); @@ -7139,9 +7423,15 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, return S.Context.DependentTy; QualType ResType = Op->getType(); + // Atomic types can be used for increment / decrement where the non-atomic + // versions can, so ignore the _Atomic() specifier for the purpose of + // checking. + if (const AtomicType *ResAtomicType = ResType->getAs<AtomicType>()) + ResType = ResAtomicType->getValueType(); + assert(!ResType.isNull() && "no type for increment/decrement expression"); - if (S.getLangOptions().CPlusPlus && ResType->isBooleanType()) { + if (S.getLangOpts().CPlusPlus && ResType->isBooleanType()) { // Decrement of bool is not allowed. if (!IsInc) { S.Diag(OpLoc, diag::err_decrement_bool) << Op->getSourceRange(); @@ -7168,7 +7458,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, if (PR.isInvalid()) return QualType(); return CheckIncrementDecrementOperand(S, PR.take(), VK, OpLoc, IsInc, IsPrefix); - } else if (S.getLangOptions().AltiVec && ResType->isVectorType()) { + } else if (S.getLangOpts().AltiVec && ResType->isVectorType()) { // OK! ( C/C++ Language Extensions for CBEA(Version 2.6) 10.3 ) } else { S.Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement) @@ -7182,7 +7472,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, // In C++, a prefix increment is the same type as the operand. Otherwise // (in C or with postfix), the increment is the unqualified type of the // operand. - if (IsPrefix && S.getLangOptions().CPlusPlus) { + if (IsPrefix && S.getLangOpts().CPlusPlus) { VK = VK_LValue; return ResType; } else { @@ -7190,102 +7480,6 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, return ResType.getUnqualifiedType(); } } - -ExprResult Sema::ConvertPropertyForRValue(Expr *E) { - assert(E->getValueKind() == VK_LValue && - E->getObjectKind() == OK_ObjCProperty); - const ObjCPropertyRefExpr *PRE = E->getObjCProperty(); - - QualType T = E->getType(); - QualType ReceiverType; - if (PRE->isObjectReceiver()) - ReceiverType = PRE->getBase()->getType(); - else if (PRE->isSuperReceiver()) - ReceiverType = PRE->getSuperReceiverType(); - else - ReceiverType = Context.getObjCInterfaceType(PRE->getClassReceiver()); - - ExprValueKind VK = VK_RValue; - if (PRE->isImplicitProperty()) { - if (ObjCMethodDecl *GetterMethod = - PRE->getImplicitPropertyGetter()) { - T = getMessageSendResultType(ReceiverType, GetterMethod, - PRE->isClassReceiver(), - PRE->isSuperReceiver()); - VK = Expr::getValueKindForType(GetterMethod->getResultType()); - } - else { - Diag(PRE->getLocation(), diag::err_getter_not_found) - << PRE->getBase()->getType(); - } - } - else { - // lvalue-ness of an explicit property is determined by - // getter type. - QualType ResT = PRE->getGetterResultType(); - VK = Expr::getValueKindForType(ResT); - } - - E = ImplicitCastExpr::Create(Context, T, CK_GetObjCProperty, - E, 0, VK); - - ExprResult Result = MaybeBindToTemporary(E); - if (!Result.isInvalid()) - E = Result.take(); - - return Owned(E); -} - -void Sema::ConvertPropertyForLValue(ExprResult &LHS, ExprResult &RHS, - QualType &LHSTy) { - assert(LHS.get()->getValueKind() == VK_LValue && - LHS.get()->getObjectKind() == OK_ObjCProperty); - const ObjCPropertyRefExpr *PropRef = LHS.get()->getObjCProperty(); - - bool Consumed = false; - - if (PropRef->isImplicitProperty()) { - // If using property-dot syntax notation for assignment, and there is a - // setter, RHS expression is being passed to the setter argument. So, - // type conversion (and comparison) is RHS to setter's argument type. - if (const ObjCMethodDecl *SetterMD = PropRef->getImplicitPropertySetter()) { - ObjCMethodDecl::param_const_iterator P = SetterMD->param_begin(); - LHSTy = (*P)->getType(); - Consumed = (getLangOptions().ObjCAutoRefCount && - (*P)->hasAttr<NSConsumedAttr>()); - - // Otherwise, if the getter returns an l-value, just call that. - } else { - QualType Result = PropRef->getImplicitPropertyGetter()->getResultType(); - ExprValueKind VK = Expr::getValueKindForType(Result); - if (VK == VK_LValue) { - LHS = ImplicitCastExpr::Create(Context, LHS.get()->getType(), - CK_GetObjCProperty, LHS.take(), 0, VK); - return; - } - } - } else if (getLangOptions().ObjCAutoRefCount) { - const ObjCMethodDecl *setter - = PropRef->getExplicitProperty()->getSetterMethodDecl(); - if (setter) { - ObjCMethodDecl::param_const_iterator P = setter->param_begin(); - LHSTy = (*P)->getType(); - Consumed = (*P)->hasAttr<NSConsumedAttr>(); - } - } - - if ((getLangOptions().CPlusPlus && LHSTy->isRecordType()) || - getLangOptions().ObjCAutoRefCount) { - InitializedEntity Entity = - InitializedEntity::InitializeParameter(Context, LHSTy, Consumed); - ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), RHS); - if (!ArgE.isInvalid()) { - RHS = ArgE; - if (getLangOptions().ObjCAutoRefCount && !PropRef->isSuperReceiver()) - checkRetainCycles(const_cast<Expr*>(PropRef->getBase()), RHS.get()); - } - } -} /// getPrimaryDecl - Helper function for CheckAddressOfOperand(). @@ -7369,33 +7563,41 @@ static void diagnoseAddressOfInvalidType(Sema &S, SourceLocation Loc, /// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue. /// In C++, the operand might be an overloaded function name, in which case /// we allow the '&' but retain the overloaded-function type. -static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp, +static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp, SourceLocation OpLoc) { - if (OrigOp->isTypeDependent()) - return S.Context.DependentTy; - if (OrigOp->getType() == S.Context.OverloadTy) { - if (!isa<OverloadExpr>(OrigOp->IgnoreParens())) { - S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof) - << OrigOp->getSourceRange(); + if (const BuiltinType *PTy = OrigOp.get()->getType()->getAsPlaceholderType()){ + if (PTy->getKind() == BuiltinType::Overload) { + if (!isa<OverloadExpr>(OrigOp.get()->IgnoreParens())) { + S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof) + << OrigOp.get()->getSourceRange(); + return QualType(); + } + + return S.Context.OverloadTy; + } + + if (PTy->getKind() == BuiltinType::UnknownAny) + return S.Context.UnknownAnyTy; + + if (PTy->getKind() == BuiltinType::BoundMember) { + S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function) + << OrigOp.get()->getSourceRange(); return QualType(); } - - return S.Context.OverloadTy; - } - if (OrigOp->getType() == S.Context.UnknownAnyTy) - return S.Context.UnknownAnyTy; - if (OrigOp->getType() == S.Context.BoundMemberTy) { - S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function) - << OrigOp->getSourceRange(); - return QualType(); + + OrigOp = S.CheckPlaceholderExpr(OrigOp.take()); + if (OrigOp.isInvalid()) return QualType(); } - assert(!OrigOp->getType()->isPlaceholderType()); + if (OrigOp.get()->isTypeDependent()) + return S.Context.DependentTy; + + assert(!OrigOp.get()->getType()->isPlaceholderType()); // Make sure to ignore parentheses in subsequent checks - Expr *op = OrigOp->IgnoreParens(); + Expr *op = OrigOp.get()->IgnoreParens(); - if (S.getLangOptions().C99) { + if (S.getLangOpts().C99) { // Implement C99-only parts of addressof rules. if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) { if (uOp->getOpcode() == UO_Deref) @@ -7426,16 +7628,16 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp, // If the underlying expression isn't a decl ref, give up. if (!isa<DeclRefExpr>(op)) { S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function) - << OrigOp->getSourceRange(); + << OrigOp.get()->getSourceRange(); return QualType(); } DeclRefExpr *DRE = cast<DeclRefExpr>(op); CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl()); // The id-expression was parenthesized. - if (OrigOp != DRE) { + if (OrigOp.get() != DRE) { S.Diag(OpLoc, diag::err_parens_pointer_member_function) - << OrigOp->getSourceRange(); + << OrigOp.get()->getSourceRange(); // The method was named without a qualifier. } else if (!DRE->getQualifier()) { @@ -7449,10 +7651,15 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp, // C99 6.5.3.2p1 // The operand must be either an l-value or a function designator if (!op->getType()->isFunctionType()) { - // FIXME: emit more specific diag... - S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof) - << op->getSourceRange(); - return QualType(); + // Use a special diagnostic for loads from property references. + if (isa<PseudoObjectExpr>(op)) { + AddressOfError = AO_Property_Expansion; + } else { + // FIXME: emit more specific diag... + S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof) + << op->getSourceRange(); + return QualType(); + } } } else if (op->getObjectKind() == OK_BitField) { // C99 6.5.3.2p1 // The operand cannot be a bit-field @@ -7460,9 +7667,6 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp, } else if (op->getObjectKind() == OK_VectorComponent) { // The operand cannot be an element of a vector AddressOfError = AO_Vector_Element; - } else if (op->getObjectKind() == OK_ObjCProperty) { - // cannot take address of a property expression. - AddressOfError = AO_Property_Expansion; } else if (dcl) { // C99 6.5.3.2p1 // We have an lvalue with a decl. Make sure the decl is not declared // with the register storage-class specifier. @@ -7470,7 +7674,7 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp, // in C++ it is not error to take address of a register // variable (c++03 7.1.1P3) if (vd->getStorageClass() == SC_Register && - !S.getLangOptions().CPlusPlus) { + !S.getLangOpts().CPlusPlus) { AddressOfError = AO_Register_Variable; } } else if (isa<FunctionTemplateDecl>(dcl)) { @@ -7562,7 +7766,7 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK, VK = VK_LValue; // ...except that certain expressions are never l-values in C. - if (!S.getLangOptions().CPlusPlus && Result.isCForbiddenLValueType()) + if (!S.getLangOpts().CPlusPlus && Result.isCForbiddenLValueType()) VK = VK_RValue; return Result; @@ -7669,6 +7873,25 @@ static void DiagnoseSelfAssignment(Sema &S, Expr *LHSExpr, Expr *RHSExpr, ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr) { + if (getLangOpts().CPlusPlus0x && isa<InitListExpr>(RHSExpr)) { + // The syntax only allows initializer lists on the RHS of assignment, + // so we don't need to worry about accepting invalid code for + // non-assignment operators. + // C++11 5.17p9: + // The meaning of x = {v} [...] is that of x = T(v) [...]. The meaning + // of x = {} is x = T(). + InitializationKind Kind = + InitializationKind::CreateDirectList(RHSExpr->getLocStart()); + InitializedEntity Entity = + InitializedEntity::InitializeTemporary(LHSExpr->getType()); + InitializationSequence InitSeq(*this, Entity, Kind, &RHSExpr, 1); + ExprResult Init = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(&RHSExpr, 1)); + if (Init.isInvalid()) + return Init; + RHSExpr = Init.take(); + } + ExprResult LHS = Owned(LHSExpr), RHS = Owned(RHSExpr); QualType ResultTy; // Result type of the binary operator. // The following two variables are used for compound assignment operators @@ -7677,27 +7900,10 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, ExprValueKind VK = VK_RValue; ExprObjectKind OK = OK_Ordinary; - // Check if a 'foo<int>' involved in a binary op, identifies a single - // function unambiguously (i.e. an lvalue ala 13.4) - // But since an assignment can trigger target based overload, exclude it in - // our blind search. i.e: - // template<class T> void f(); template<class T, class U> void f(U); - // f<int> == 0; // resolve f<int> blindly - // void (*p)(int); p = f<int>; // resolve f<int> using target - if (Opc != BO_Assign) { - ExprResult resolvedLHS = CheckPlaceholderExpr(LHS.get()); - if (!resolvedLHS.isUsable()) return ExprError(); - LHS = move(resolvedLHS); - - ExprResult resolvedRHS = CheckPlaceholderExpr(RHS.get()); - if (!resolvedRHS.isUsable()) return ExprError(); - RHS = move(resolvedRHS); - } - switch (Opc) { case BO_Assign: ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType()); - if (getLangOptions().CPlusPlus && + if (getLangOpts().CPlusPlus && LHS.get()->getObjectKind() != OK_ObjCProperty) { VK = LHS.get()->getValueKind(); OK = LHS.get()->getObjectKind(); @@ -7719,7 +7925,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, ResultTy = CheckRemainderOperands(LHS, RHS, OpLoc); break; case BO_Add: - ResultTy = CheckAdditionOperands(LHS, RHS, OpLoc); + ResultTy = CheckAdditionOperands(LHS, RHS, OpLoc, Opc); break; case BO_Sub: ResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc); @@ -7762,7 +7968,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy); break; case BO_AddAssign: - CompResultTy = CheckAdditionOperands(LHS, RHS, OpLoc, &CompLHSTy); + CompResultTy = CheckAdditionOperands(LHS, RHS, OpLoc, Opc, &CompLHSTy); if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid()) ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy); break; @@ -7788,7 +7994,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, break; case BO_Comma: ResultTy = CheckCommaOperands(*this, LHS, RHS, OpLoc); - if (getLangOptions().CPlusPlus && !RHS.isInvalid()) { + if (getLangOpts().CPlusPlus && !RHS.isInvalid()) { VK = RHS.get()->getValueKind(); OK = RHS.get()->getObjectKind(); } @@ -7804,7 +8010,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, if (CompResultTy.isNull()) return Owned(new (Context) BinaryOperator(LHS.take(), RHS.take(), Opc, ResultTy, VK, OK, OpLoc)); - if (getLangOptions().CPlusPlus && LHS.get()->getObjectKind() != + if (getLangOpts().CPlusPlus && LHS.get()->getObjectKind() != OK_ObjCProperty) { VK = VK_LValue; OK = LHS.get()->getObjectKind(); @@ -7989,38 +8195,98 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, return BuildBinOp(S, TokLoc, Opc, LHSExpr, RHSExpr); } +/// Build an overloaded binary operator expression in the given scope. +static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc, + BinaryOperatorKind Opc, + Expr *LHS, Expr *RHS) { + // Find all of the overloaded operators visible from this + // point. We perform both an operator-name lookup from the local + // scope and an argument-dependent lookup based on the types of + // the arguments. + UnresolvedSet<16> Functions; + OverloadedOperatorKind OverOp + = BinaryOperator::getOverloadedOperator(Opc); + if (Sc && OverOp != OO_None) + S.LookupOverloadedOperatorName(OverOp, Sc, LHS->getType(), + RHS->getType(), Functions); + + // Build the (potentially-overloaded, potentially-dependent) + // binary operation. + return S.CreateOverloadedBinOp(OpLoc, Opc, Functions, LHS, RHS); +} + ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr) { - if (getLangOptions().CPlusPlus) { - bool UseBuiltinOperator; - - if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent()) { - UseBuiltinOperator = false; - } else if (Opc == BO_Assign && - LHSExpr->getObjectKind() == OK_ObjCProperty) { - UseBuiltinOperator = true; - } else { - UseBuiltinOperator = !LHSExpr->getType()->isOverloadableType() && - !RHSExpr->getType()->isOverloadableType(); + // We want to end up calling one of checkPseudoObjectAssignment + // (if the LHS is a pseudo-object), BuildOverloadedBinOp (if + // both expressions are overloadable or either is type-dependent), + // or CreateBuiltinBinOp (in any other case). We also want to get + // any placeholder types out of the way. + + // Handle pseudo-objects in the LHS. + if (const BuiltinType *pty = LHSExpr->getType()->getAsPlaceholderType()) { + // Assignments with a pseudo-object l-value need special analysis. + if (pty->getKind() == BuiltinType::PseudoObject && + BinaryOperator::isAssignmentOp(Opc)) + return checkPseudoObjectAssignment(S, OpLoc, Opc, LHSExpr, RHSExpr); + + // Don't resolve overloads if the other type is overloadable. + if (pty->getKind() == BuiltinType::Overload) { + // We can't actually test that if we still have a placeholder, + // though. Fortunately, none of the exceptions we see in that + // code below are valid when the LHS is an overload set. Note + // that an overload set can be dependently-typed, but it never + // instantiates to having an overloadable type. + ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr); + if (resolvedRHS.isInvalid()) return ExprError(); + RHSExpr = resolvedRHS.take(); + + if (RHSExpr->isTypeDependent() || + RHSExpr->getType()->isOverloadableType()) + return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); } + + ExprResult LHS = CheckPlaceholderExpr(LHSExpr); + if (LHS.isInvalid()) return ExprError(); + LHSExpr = LHS.take(); + } + + // Handle pseudo-objects in the RHS. + if (const BuiltinType *pty = RHSExpr->getType()->getAsPlaceholderType()) { + // An overload in the RHS can potentially be resolved by the type + // being assigned to. + if (Opc == BO_Assign && pty->getKind() == BuiltinType::Overload) { + if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent()) + return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); - if (!UseBuiltinOperator) { - // Find all of the overloaded operators visible from this - // point. We perform both an operator-name lookup from the local - // scope and an argument-dependent lookup based on the types of - // the arguments. - UnresolvedSet<16> Functions; - OverloadedOperatorKind OverOp - = BinaryOperator::getOverloadedOperator(Opc); - if (S && OverOp != OO_None) - LookupOverloadedOperatorName(OverOp, S, LHSExpr->getType(), - RHSExpr->getType(), Functions); + if (LHSExpr->getType()->isOverloadableType()) + return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); - // Build the (potentially-overloaded, potentially-dependent) - // binary operation. - return CreateOverloadedBinOp(OpLoc, Opc, Functions, LHSExpr, RHSExpr); + return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr); } + + // Don't resolve overloads if the other type is overloadable. + if (pty->getKind() == BuiltinType::Overload && + LHSExpr->getType()->isOverloadableType()) + return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); + + ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr); + if (!resolvedRHS.isUsable()) return ExprError(); + RHSExpr = resolvedRHS.take(); + } + + if (getLangOpts().CPlusPlus) { + // If either expression is type-dependent, always build an + // overloaded op. + if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent()) + return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); + + // Otherwise, build an overloaded op if either expression has an + // overloadable type. + if (LHSExpr->getType()->isOverloadableType() || + RHSExpr->getType()->isOverloadableType()) + return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); } // Build a built-in binary operation. @@ -8046,12 +8312,9 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, Opc == UO_PreDec); break; case UO_AddrOf: - resultType = CheckAddressOfOperand(*this, Input.get(), OpLoc); + resultType = CheckAddressOfOperand(*this, Input, OpLoc); break; case UO_Deref: { - ExprResult resolved = CheckPlaceholderExpr(Input.get()); - if (!resolved.isUsable()) return ExprError(); - Input = move(resolved); Input = DefaultFunctionArrayLvalueConversion(Input.take()); resultType = CheckIndirectionOperand(*this, Input.get(), VK, OpLoc); break; @@ -8066,18 +8329,13 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, if (resultType->isArithmeticType() || // C99 6.5.3.3p1 resultType->isVectorType()) break; - else if (getLangOptions().CPlusPlus && // C++ [expr.unary.op]p6-7 + else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6-7 resultType->isEnumeralType()) break; - else if (getLangOptions().CPlusPlus && // C++ [expr.unary.op]p6 + else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6 Opc == UO_Plus && resultType->isPointerType()) break; - else if (resultType->isPlaceholderType()) { - Input = CheckPlaceholderExpr(Input.take()); - if (Input.isInvalid()) return ExprError(); - return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take()); - } return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); @@ -8095,11 +8353,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, << resultType << Input.get()->getSourceRange(); else if (resultType->hasIntegerRepresentation()) break; - else if (resultType->isPlaceholderType()) { - Input = CheckPlaceholderExpr(Input.take()); - if (Input.isInvalid()) return ExprError(); - return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take()); - } else { + else { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); } @@ -8121,16 +8375,16 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, break; if (resultType->isScalarType()) { // C99 6.5.3.3p1: ok, fallthrough; - if (Context.getLangOptions().CPlusPlus) { + 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, ScalarTypeToBooleanCastKind(resultType)); } - } else if (resultType->isPlaceholderType()) { - Input = CheckPlaceholderExpr(Input.take()); - if (Input.isInvalid()) return ExprError(); - return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take()); + } else if (resultType->isExtVectorType()) { + // Vector logical not returns the signed variant of the operand type. + resultType = GetSignedVectorType(resultType); + break; } else { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); @@ -8143,11 +8397,17 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, case UO_Real: case UO_Imag: resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real); - // _Real and _Imag map ordinary l-values into ordinary l-values. + // _Real maps ordinary l-values into ordinary l-values. _Imag maps ordinary + // complex l-values to ordinary l-values and all other values to r-values. if (Input.isInvalid()) return ExprError(); - if (Input.get()->getValueKind() != VK_RValue && - Input.get()->getObjectKind() == OK_Ordinary) - VK = Input.get()->getValueKind(); + if (Opc == UO_Real || Input.get()->getType()->isAnyComplexType()) { + if (Input.get()->getValueKind() != VK_RValue && + Input.get()->getObjectKind() == OK_Ordinary) + 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()); + } break; case UO_Extension: resultType = Input.get()->getType(); @@ -8169,10 +8429,79 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, VK, OK, OpLoc)); } +/// \brief Determine whether the given expression is a qualified member +/// access expression, of a form that could be turned into a pointer to member +/// with the address-of operator. +static bool isQualifiedMemberAccess(Expr *E) { + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { + if (!DRE->getQualifier()) + return false; + + ValueDecl *VD = DRE->getDecl(); + if (!VD->isCXXClassMember()) + return false; + + if (isa<FieldDecl>(VD) || isa<IndirectFieldDecl>(VD)) + return true; + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(VD)) + return Method->isInstance(); + + return false; + } + + if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) { + if (!ULE->getQualifier()) + return false; + + for (UnresolvedLookupExpr::decls_iterator D = ULE->decls_begin(), + DEnd = ULE->decls_end(); + D != DEnd; ++D) { + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*D)) { + if (Method->isInstance()) + return true; + } else { + // Overload set does not contain methods. + break; + } + } + + return false; + } + + return false; +} + ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input) { - if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType() && - UnaryOperator::getOverloadedOperator(Opc) != OO_None) { + // First things first: handle placeholders so that the + // overloaded-operator check considers the right type. + if (const BuiltinType *pty = Input->getType()->getAsPlaceholderType()) { + // Increment and decrement of pseudo-object references. + if (pty->getKind() == BuiltinType::PseudoObject && + UnaryOperator::isIncrementDecrementOp(Opc)) + return checkPseudoObjectIncDec(S, OpLoc, Opc, Input); + + // extension is always a builtin operator. + if (Opc == UO_Extension) + return CreateBuiltinUnaryOp(OpLoc, Opc, Input); + + // & gets special logic for several kinds of placeholder. + // The builtin code knows what to do. + if (Opc == UO_AddrOf && + (pty->getKind() == BuiltinType::Overload || + pty->getKind() == BuiltinType::UnknownAny || + pty->getKind() == BuiltinType::BoundMember)) + return CreateBuiltinUnaryOp(OpLoc, Opc, Input); + + // Anything else needs to be handled now. + ExprResult Result = CheckPlaceholderExpr(Input); + if (Result.isInvalid()) return ExprError(); + Input = Result.take(); + } + + if (getLangOpts().CPlusPlus && Input->getType()->isOverloadableType() && + UnaryOperator::getOverloadedOperator(Opc) != OO_None && + !(Opc == UO_AddrOf && isQualifiedMemberAccess(Input))) { // Find all of the overloaded operators visible from this // point. We perform both an operator-name lookup from the local // scope and an argument-dependent lookup based on the types of @@ -8227,12 +8556,29 @@ static Expr *maybeRebuildARCConsumingStmt(Stmt *Statement) { return cleanups; } +void Sema::ActOnStartStmtExpr() { + PushExpressionEvaluationContext(ExprEvalContexts.back().Context); +} + +void Sema::ActOnStmtExprError() { + // Note that function is also called by TreeTransform when leaving a + // StmtExpr scope without rebuilding anything. + + DiscardCleanupsInEvaluationContext(); + PopExpressionEvaluationContext(); +} + ExprResult Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, SourceLocation RPLoc) { // "({..})" assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!"); CompoundStmt *Compound = cast<CompoundStmt>(SubStmt); + if (hasAnyUnrecoverableErrorsInThisFunction()) + DiscardCleanupsInEvaluationContext(); + assert(!ExprNeedsCleanups && "cleanups within StmtExpr not correctly bound!"); + PopExpressionEvaluationContext(); + bool isFileScope = (getCurFunctionOrMethodDecl() == 0) && (getCurBlock() == 0); if (isFileScope) @@ -8353,15 +8699,19 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, } else CurrentType = Context.DependentTy; + ExprResult IdxRval = DefaultLvalueConversion(static_cast<Expr*>(OC.U.E)); + if (IdxRval.isInvalid()) + return ExprError(); + Expr *Idx = IdxRval.take(); + // The expression must be an integral expression. // FIXME: An integral constant expression? - Expr *Idx = static_cast<Expr*>(OC.U.E); if (!Idx->isTypeDependent() && !Idx->isValueDependent() && !Idx->getType()->isIntegerType()) return ExprError(Diag(Idx->getLocStart(), diag::err_typecheck_subscript_not_integer) << Idx->getSourceRange()); - + // Record this array index. Comps.push_back(OffsetOfNode(OC.LocStart, Exprs.size(), OC.LocEnd)); Exprs.push_back(Idx); @@ -8500,11 +8850,11 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, } else { // The conditional expression is required to be a constant expression. llvm::APSInt condEval(32); - SourceLocation ExpLoc; - if (!CondExpr->isIntegerConstantExpr(condEval, Context, &ExpLoc)) - return ExprError(Diag(ExpLoc, - diag::err_typecheck_choose_expr_requires_constant) - << CondExpr->getSourceRange()); + ExprResult CondICE = VerifyIntegerConstantExpression(CondExpr, &condEval, + PDiag(diag::err_typecheck_choose_expr_requires_constant), false); + if (CondICE.isInvalid()) + return ExprError(); + CondExpr = CondICE.take(); // If the condition is > zero, then the AST type is the same as the LSHExpr. Expr *ActiveExpr = condEval.getZExtValue() ? LHSExpr : RHSExpr; @@ -8534,6 +8884,12 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) { PushDeclContext(CurScope, Block); else CurContext = Block; + + getCurBlock()->HasImplicitReturnType = true; + + // Enter a new evaluation context to insulate the block from any + // cleanups from the enclosing full-expression. + PushExpressionEvaluationContext(PotentiallyEvaluated); } void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { @@ -8585,7 +8941,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { // Don't allow returning a objc interface by value. if (RetTy->isObjCObjectType()) { - Diag(ParamInfo.getSourceRange().getBegin(), + Diag(ParamInfo.getLocStart(), diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; return; } @@ -8594,8 +8950,11 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { // return type. TODO: what should we do with declarators like: // ^ * { ... } // If the answer is "apply template argument deduction".... - if (RetTy != Context.DependentTy) + if (RetTy != Context.DependentTy) { CurBlock->ReturnType = RetTy; + CurBlock->TheDecl->setBlockMissingReturnType(false); + CurBlock->HasImplicitReturnType = false; + } // Push block parameters from the declarator if we had them. SmallVector<ParmVarDecl*, 8> Params; @@ -8605,7 +8964,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { if (Param->getIdentifier() == 0 && !Param->isImplicit() && !Param->isInvalidDecl() && - !getLangOptions().CPlusPlus) + !getLangOpts().CPlusPlus) Diag(Param->getLocation(), diag::err_parameter_name_omitted); Params.push_back(Param); } @@ -8617,7 +8976,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { I = Fn->arg_type_begin(), E = Fn->arg_type_end(); I != E; ++I) { ParmVarDecl *Param = BuildParmVarDeclForTypedef(CurBlock->TheDecl, - ParamInfo.getSourceRange().getBegin(), + ParamInfo.getLocStart(), *I); Params.push_back(Param); } @@ -8634,12 +8993,6 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { // Finally we can process decl attributes. ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo); - if (!isVariadic && CurBlock->TheDecl->getAttr<SentinelAttr>()) { - Diag(ParamInfo.getAttributes()->getLoc(), - diag::warn_attribute_sentinel_not_variadic) << 1; - // FIXME: remove the attribute. - } - // Put the parameter variables in scope. We can bail out immediately // if we don't have any. if (Params.empty()) @@ -8661,9 +9014,13 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { /// ActOnBlockError - If there is an error parsing a block, this callback /// is invoked to pop the information about the block from the action impl. void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) { + // Leave the expression-evaluation context. + DiscardCleanupsInEvaluationContext(); + PopExpressionEvaluationContext(); + // Pop off CurBlock, handle nested blocks. PopDeclContext(); - PopFunctionOrBlockScope(); + PopFunctionScopeInfo(); } /// ActOnBlockStmtExpr - This is called when the body of a block statement @@ -8674,6 +9031,12 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (!LangOpts.Blocks) Diag(CaretLoc, diag::err_blocks_disable); + // Leave the expression-evaluation context. + if (hasAnyUnrecoverableErrorsInThisFunction()) + DiscardCleanupsInEvaluationContext(); + assert(!ExprNeedsCleanups && "cleanups within block not correctly bound!"); + PopExpressionEvaluationContext(); + BlockScopeInfo *BSI = cast<BlockScopeInfo>(FunctionScopes.back()); PopDeclContext(); @@ -8686,8 +9049,18 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, QualType BlockTy; // Set the captured variables on the block. - BSI->TheDecl->setCaptures(Context, BSI->Captures.begin(), BSI->Captures.end(), - BSI->CapturesCXXThis); + // FIXME: Share capture structure between BlockDecl and CapturingScopeInfo! + SmallVector<BlockDecl::Capture, 4> Captures; + for (unsigned i = 0, e = BSI->Captures.size(); i != e; i++) { + CapturingScopeInfo::Capture &Cap = BSI->Captures[i]; + if (Cap.isThisCapture()) + continue; + BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture(), + Cap.isNested(), Cap.getCopyExpr()); + Captures.push_back(NewCap); + } + BSI->TheDecl->setCaptures(Context, Captures.begin(), Captures.end(), + BSI->CXXThisCaptureIndex != 0); // If the user wrote a function type in some form, try to use that. if (!BSI->FunctionType.isNull()) { @@ -8738,20 +9111,31 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, BSI->TheDecl->setBody(cast<CompoundStmt>(Body)); - for (BlockDecl::capture_const_iterator ci = BSI->TheDecl->capture_begin(), - ce = BSI->TheDecl->capture_end(); ci != ce; ++ci) { - const VarDecl *variable = ci->getVariable(); - QualType T = variable->getType(); - QualType::DestructionKind destructKind = T.isDestructedType(); - if (destructKind != QualType::DK_none) - getCurFunction()->setHasBranchProtectedScope(); - } - computeNRVO(Body, getCurBlock()); BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy); const AnalysisBasedWarnings::Policy &WP = AnalysisWarnings.getDefaultPolicy(); - PopFunctionOrBlockScope(&WP, Result->getBlockDecl(), Result); + PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result); + + // If the block isn't obviously global, i.e. it captures anything at + // all, then we need to do a few things in the surrounding context: + if (Result->getBlockDecl()->hasCaptures()) { + // First, this expression has a new cleanup object. + ExprCleanupObjects.push_back(Result->getBlockDecl()); + ExprNeedsCleanups = true; + + // 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(); + if (var->getType().isDestructedType() != QualType::DK_none) { + getCurFunction()->setHasBranchProtectedScope(); + break; + } + } + } return Owned(Result); } @@ -8859,7 +9243,7 @@ ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) { static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType, Expr *SrcExpr, FixItHint &Hint) { - if (!SemaRef.getLangOptions().ObjC1) + if (!SemaRef.getLangOpts().ObjC1) return; const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>(); @@ -8874,8 +9258,15 @@ static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType, return; } - // Strip off any parens and casts. - StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr->IgnoreParenCasts()); + // 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(); + 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; @@ -8893,13 +9284,13 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, // Decode the result (notice that AST's are still created for extensions). bool CheckInferredResultType = false; bool isInvalid = false; - unsigned DiagKind; + unsigned DiagKind = 0; FixItHint Hint; ConversionFixItGenerator ConvHints; bool MayHaveConvFixit = false; + bool MayHaveFunctionDiff = false; switch (ConvTy) { - default: llvm_unreachable("Unknown conversion type"); case Compatible: return false; case PointerToInt: DiagKind = diag::ext_typecheck_convert_pointer_int; @@ -8956,7 +9347,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, // expression, rather than a type), which should be done as part // of a larger effort to fix checkPointerTypesForAssignment for // C++ semantics. - if (getLangOptions().CPlusPlus && + if (getLangOpts().CPlusPlus && IsStringLiteralToNonConstPointerConversion(SrcExpr, DstType)) return false; DiagKind = diag::ext_typecheck_convert_discards_qualifiers; @@ -8986,6 +9377,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); MayHaveConvFixit = true; isInvalid = true; + MayHaveFunctionDiff = true; break; } @@ -9015,17 +9407,23 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, // If we can fix the conversion, suggest the FixIts. assert(ConvHints.isNull() || Hint.isNull()); if (!ConvHints.isNull()) { - for (llvm::SmallVector<FixItHint, 1>::iterator - HI = ConvHints.Hints.begin(), HE = ConvHints.Hints.end(); - HI != HE; ++HI) + for (std::vector<FixItHint>::iterator HI = ConvHints.Hints.begin(), + HE = ConvHints.Hints.end(); HI != HE; ++HI) FDiag << *HI; } else { FDiag << Hint; } if (MayHaveConvFixit) { FDiag << (unsigned) (ConvHints.Kind); } + if (MayHaveFunctionDiff) + HandleFunctionTypeMismatch(FDiag, SecondType, FirstType); + Diag(Loc, FDiag); + if (SecondType == Context.OverloadTy) + NoteAllOverloadCandidates(OverloadExpr::find(SrcExpr).Expression, + FirstType); + if (CheckInferredResultType) EmitRelatedResultTypeNote(SrcExpr); @@ -9034,77 +9432,213 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, return isInvalid; } -bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){ - llvm::APSInt ICEResult; - if (E->isIntegerConstantExpr(ICEResult, Context)) { +ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, + llvm::APSInt *Result) { + return VerifyIntegerConstantExpression(E, Result, + PDiag(diag::err_expr_not_ice) << LangOpts.CPlusPlus); +} + +ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, + PartialDiagnostic NotIceDiag, + bool AllowFold, + PartialDiagnostic FoldDiag) { + SourceLocation DiagLoc = E->getLocStart(); + + if (getLangOpts().CPlusPlus0x) { + // C++11 [expr.const]p5: + // If an expression of literal class type is used in a context where an + // integral constant expression is required, then that class type shall + // have a single non-explicit conversion function to an integral or + // unscoped enumeration type + ExprResult Converted; + if (NotIceDiag.getDiagID()) { + Converted = ConvertToIntegralOrEnumerationType( + DiagLoc, E, + PDiag(diag::err_ice_not_integral), + PDiag(diag::err_ice_incomplete_type), + PDiag(diag::err_ice_explicit_conversion), + PDiag(diag::note_ice_conversion_here), + PDiag(diag::err_ice_ambiguous_conversion), + PDiag(diag::note_ice_conversion_here), + PDiag(0), + /*AllowScopedEnumerations*/ false); + } else { + // The caller wants to silently enquire whether this is an ICE. Don't + // produce any diagnostics if it isn't. + Converted = ConvertToIntegralOrEnumerationType( + DiagLoc, E, PDiag(), PDiag(), PDiag(), PDiag(), + PDiag(), PDiag(), PDiag(), false); + } + if (Converted.isInvalid()) + return Converted; + E = Converted.take(); + if (!E->getType()->isIntegralOrUnscopedEnumerationType()) + return ExprError(); + } else if (!E->getType()->isIntegralOrUnscopedEnumerationType()) { + // An ICE must be of integral or unscoped enumeration type. + if (NotIceDiag.getDiagID()) + Diag(DiagLoc, NotIceDiag) << E->getSourceRange(); + return ExprError(); + } + + // Circumvent ICE checking in C++11 to avoid evaluating the expression twice + // in the non-ICE case. + if (!getLangOpts().CPlusPlus0x && E->isIntegerConstantExpr(Context)) { if (Result) - *Result = ICEResult; - return false; + *Result = E->EvaluateKnownConstInt(Context); + return Owned(E); } Expr::EvalResult EvalResult; + llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + EvalResult.Diag = &Notes; + + // Try to evaluate the expression, and produce diagnostics explaining why it's + // not a constant expression as a side-effect. + bool Folded = E->EvaluateAsRValue(EvalResult, Context) && + EvalResult.Val.isInt() && !EvalResult.HasSideEffects; + + // In C++11, we can rely on diagnostics being produced for any expression + // which is not a constant expression. If no diagnostics were produced, then + // this is a constant expression. + if (Folded && getLangOpts().CPlusPlus0x && Notes.empty()) { + if (Result) + *Result = EvalResult.Val.getInt(); + return Owned(E); + } - if (!E->Evaluate(EvalResult, Context) || !EvalResult.Val.isInt() || - EvalResult.HasSideEffects) { - Diag(E->getExprLoc(), diag::err_expr_not_ice) << E->getSourceRange(); + // If our only note is the usual "invalid subexpression" note, just point + // the caret at its location rather than producing an essentially + // redundant note. + if (Notes.size() == 1 && Notes[0].second.getDiagID() == + diag::note_invalid_subexpr_in_const_expr) { + DiagLoc = Notes[0].first; + Notes.clear(); + } - if (EvalResult.Diag) { - // We only show the note if it's not the usual "invalid subexpression" - // or if it's actually in a subexpression. - if (EvalResult.Diag != diag::note_invalid_subexpr_in_ice || - E->IgnoreParens() != EvalResult.DiagExpr->IgnoreParens()) - Diag(EvalResult.DiagLoc, EvalResult.Diag); + if (!Folded || !AllowFold) { + if (NotIceDiag.getDiagID()) { + Diag(DiagLoc, NotIceDiag) << E->getSourceRange(); + for (unsigned I = 0, N = Notes.size(); I != N; ++I) + Diag(Notes[I].first, Notes[I].second); } - return true; + return ExprError(); } - Diag(E->getExprLoc(), diag::ext_expr_not_ice) << - E->getSourceRange(); - - if (EvalResult.Diag && - Diags.getDiagnosticLevel(diag::ext_expr_not_ice, EvalResult.DiagLoc) - != DiagnosticsEngine::Ignored) - Diag(EvalResult.DiagLoc, EvalResult.Diag); + if (FoldDiag.getDiagID()) + Diag(DiagLoc, FoldDiag) << E->getSourceRange(); + else + Diag(DiagLoc, diag::ext_expr_not_ice) + << E->getSourceRange() << LangOpts.CPlusPlus; + for (unsigned I = 0, N = Notes.size(); I != N; ++I) + Diag(Notes[I].first, Notes[I].second); if (Result) *Result = EvalResult.Val.getInt(); - return false; + return Owned(E); +} + +namespace { + // Handle the case where we conclude a expression which we speculatively + // considered to be unevaluated is actually evaluated. + class TransformToPE : public TreeTransform<TransformToPE> { + typedef TreeTransform<TransformToPE> BaseTransform; + + public: + TransformToPE(Sema &SemaRef) : BaseTransform(SemaRef) { } + + // Make sure we redo semantic analysis + bool AlwaysRebuild() { return true; } + + // Make sure we handle LabelStmts correctly. + // FIXME: This does the right thing, but maybe we need a more general + // fix to TreeTransform? + StmtResult TransformLabelStmt(LabelStmt *S) { + S->getDecl()->setStmt(0); + return BaseTransform::TransformLabelStmt(S); + } + + // We need to special-case DeclRefExprs referring to FieldDecls which + // are not part of a member pointer formation; normal TreeTransforming + // doesn't catch this case because of the way we represent them in the AST. + // FIXME: This is a bit ugly; is it really the best way to handle this + // case? + // + // Error on DeclRefExprs referring to FieldDecls. + ExprResult TransformDeclRefExpr(DeclRefExpr *E) { + if (isa<FieldDecl>(E->getDecl()) && + SemaRef.ExprEvalContexts.back().Context != Sema::Unevaluated) + return SemaRef.Diag(E->getLocation(), + diag::err_invalid_non_static_member_use) + << E->getDecl() << E->getSourceRange(); + + return BaseTransform::TransformDeclRefExpr(E); + } + + // Exception: filter out member pointer formation + ExprResult TransformUnaryOperator(UnaryOperator *E) { + if (E->getOpcode() == UO_AddrOf && E->getType()->isMemberPointerType()) + return E; + + return BaseTransform::TransformUnaryOperator(E); + } + + ExprResult TransformLambdaExpr(LambdaExpr *E) { + // Lambdas never need to be transformed. + return E; + } + }; +} + +ExprResult Sema::TranformToPotentiallyEvaluated(Expr *E) { + assert(ExprEvalContexts.back().Context == Unevaluated && + "Should only transform unevaluated expressions"); + ExprEvalContexts.back().Context = + ExprEvalContexts[ExprEvalContexts.size()-2].Context; + if (ExprEvalContexts.back().Context == Unevaluated) + return E; + return TransformToPE(*this).TransformExpr(E); } void -Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { +Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, + Decl *LambdaContextDecl, + bool IsDecltype) { ExprEvalContexts.push_back( ExpressionEvaluationContextRecord(NewContext, - ExprTemporaries.size(), - ExprNeedsCleanups)); + ExprCleanupObjects.size(), + ExprNeedsCleanups, + LambdaContextDecl, + IsDecltype)); ExprNeedsCleanups = false; + if (!MaybeODRUseExprs.empty()) + std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs); } void Sema::PopExpressionEvaluationContext() { - // Pop the current expression evaluation context off the stack. - ExpressionEvaluationContextRecord Rec = ExprEvalContexts.back(); - ExprEvalContexts.pop_back(); - - if (Rec.Context == PotentiallyPotentiallyEvaluated) { - if (Rec.PotentiallyReferenced) { - // Mark any remaining declarations in the current position of the stack - // as "referenced". If they were not meant to be referenced, semantic - // analysis would have eliminated them (e.g., in ActOnCXXTypeId). - for (PotentiallyReferencedDecls::iterator - I = Rec.PotentiallyReferenced->begin(), - IEnd = Rec.PotentiallyReferenced->end(); - I != IEnd; ++I) - MarkDeclarationReferenced(I->first, I->second); - } - - if (Rec.PotentiallyDiagnosed) { - // Emit any pending diagnostics. - for (PotentiallyEmittedDiagnostics::iterator - I = Rec.PotentiallyDiagnosed->begin(), - IEnd = Rec.PotentiallyDiagnosed->end(); - I != IEnd; ++I) - Diag(I->first, I->second); + ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back(); + + if (!Rec.Lambdas.empty()) { + if (Rec.Context == Unevaluated) { + // C++11 [expr.prim.lambda]p2: + // A lambda-expression shall not appear in an unevaluated operand + // (Clause 5). + for (unsigned I = 0, N = Rec.Lambdas.size(); I != N; ++I) + Diag(Rec.Lambdas[I]->getLocStart(), + diag::err_lambda_unevaluated_operand); + } else { + // Mark the capture expressions odr-used. This was deferred + // during lambda expression creation. + for (unsigned I = 0, N = Rec.Lambdas.size(); I != N; ++I) { + LambdaExpr *Lambda = Rec.Lambdas[I]; + for (LambdaExpr::capture_init_iterator + C = Lambda->capture_init_begin(), + CEnd = Lambda->capture_init_end(); + C != CEnd; ++C) { + MarkDeclarationsReferencedInExpr(*C); + } + } } } @@ -9112,89 +9646,86 @@ void Sema::PopExpressionEvaluationContext() { // temporaries that we may have created as part of the evaluation of // the expression in that context: they aren't relevant because they // will never be constructed. - if (Rec.Context == Unevaluated) { - ExprTemporaries.erase(ExprTemporaries.begin() + Rec.NumTemporaries, - ExprTemporaries.end()); + if (Rec.Context == Unevaluated || Rec.Context == ConstantEvaluated) { + ExprCleanupObjects.erase(ExprCleanupObjects.begin() + Rec.NumCleanupObjects, + ExprCleanupObjects.end()); ExprNeedsCleanups = Rec.ParentNeedsCleanups; - + CleanupVarDeclMarking(); + std::swap(MaybeODRUseExprs, Rec.SavedMaybeODRUseExprs); // Otherwise, merge the contexts together. } else { ExprNeedsCleanups |= Rec.ParentNeedsCleanups; + MaybeODRUseExprs.insert(Rec.SavedMaybeODRUseExprs.begin(), + Rec.SavedMaybeODRUseExprs.end()); } - // Destroy the popped expression evaluation record. - Rec.Destroy(); + // Pop the current expression evaluation context off the stack. + ExprEvalContexts.pop_back(); } void Sema::DiscardCleanupsInEvaluationContext() { - ExprTemporaries.erase( - ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries, - ExprTemporaries.end()); + ExprCleanupObjects.erase( + ExprCleanupObjects.begin() + ExprEvalContexts.back().NumCleanupObjects, + ExprCleanupObjects.end()); ExprNeedsCleanups = false; + MaybeODRUseExprs.clear(); } -/// \brief Note that the given declaration was referenced in the source code. -/// -/// This routine should be invoke whenever a given declaration is referenced -/// in the source code, and where that reference occurred. If this declaration -/// reference means that the the declaration is used (C++ [basic.def.odr]p2, -/// C99 6.9p3), then the declaration will be marked as used. -/// -/// \param Loc the location where the declaration was referenced. -/// -/// \param D the declaration that has been referenced by the source code. -void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { - assert(D && "No declaration?"); - - D->setReferenced(); - - if (D->isUsed(false)) - return; - - // Mark a parameter or variable declaration "used", regardless of whether - // we're in a template or not. The reason for this is that unevaluated - // expressions (e.g. (void)sizeof()) constitute a use for warning purposes - // (-Wunused-variables and -Wunused-parameters) - if (isa<ParmVarDecl>(D) || - (isa<VarDecl>(D) && D->getDeclContext()->isFunctionOrMethod())) { - D->setUsed(); - return; - } - - if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) - return; +ExprResult Sema::HandleExprEvaluationContextForTypeof(Expr *E) { + if (!E->getType()->isVariablyModifiedType()) + return E; + return TranformToPotentiallyEvaluated(E); +} +static bool IsPotentiallyEvaluatedContext(Sema &SemaRef) { // Do not mark anything as "used" within a dependent context; wait for // an instantiation. - if (CurContext->isDependentContext()) - return; + if (SemaRef.CurContext->isDependentContext()) + return false; - switch (ExprEvalContexts.back().Context) { - case Unevaluated: + switch (SemaRef.ExprEvalContexts.back().Context) { + case Sema::Unevaluated: // We are in an expression that is not potentially evaluated; do nothing. - return; + // (Depending on how you read the standard, we actually do need to do + // something here for null pointer constants, but the standard's + // definition of a null pointer constant is completely crazy.) + return false; - case PotentiallyEvaluated: - // We are in a potentially-evaluated expression, so this declaration is - // "used"; handle this below. - break; + case Sema::ConstantEvaluated: + case Sema::PotentiallyEvaluated: + // We are in a potentially evaluated expression (or a constant-expression + // in C++03); we need to do implicit template instantiation, implicitly + // define class members, and mark most declarations as used. + return true; - case PotentiallyPotentiallyEvaluated: - // We are in an expression that may be potentially evaluated; queue this - // declaration reference until we know whether the expression is - // potentially evaluated. - ExprEvalContexts.back().addReferencedDecl(Loc, D); - return; - - case PotentiallyEvaluatedIfUsed: + case Sema::PotentiallyEvaluatedIfUsed: // Referenced declarations will only be used if the construct in the // containing expression is used. - return; + return false; } + llvm_unreachable("Invalid context"); +} + +/// \brief Mark a function referenced, and check whether it is odr-used +/// (C++ [basic.def.odr]p2, C99 6.9p3) +void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { + assert(Func && "No function?"); + + Func->setReferenced(); + + // Don't mark this function as used multiple times, unless it's a constexpr + // function which we need to instantiate. + if (Func->isUsed(false) && + !(Func->isConstexpr() && !Func->getBody() && + Func->isImplicitlyInstantiable())) + return; + + if (!IsPotentiallyEvaluatedContext(*this)) + return; // Note that this declaration has been used. - if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { - if (Constructor->isDefaulted()) { + if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Func)) { + if (Constructor->isDefaulted() && !Constructor->isDeleted()) { if (Constructor->isDefaultConstructor()) { if (Constructor->isTrivial()) return; @@ -9210,13 +9741,16 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { } MarkVTableUsed(Loc, Constructor->getParent()); - } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { - if (Destructor->isDefaulted() && !Destructor->isUsed(false)) + } else if (CXXDestructorDecl *Destructor = + dyn_cast<CXXDestructorDecl>(Func)) { + if (Destructor->isDefaulted() && !Destructor->isDeleted() && + !Destructor->isUsed(false)) DefineImplicitDestructor(Loc, Destructor); if (Destructor->isVirtual()) MarkVTableUsed(Loc, Destructor->getParent()); - } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) { - if (MethodDecl->isDefaulted() && MethodDecl->isOverloadedOperator() && + } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(Func)) { + if (MethodDecl->isDefaulted() && !MethodDecl->isDeleted() && + MethodDecl->isOverloadedOperator() && MethodDecl->getOverloadedOperator() == OO_Equal) { if (!MethodDecl->isUsed(false)) { if (MethodDecl->isCopyAssignmentOperator()) @@ -9224,90 +9758,703 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { else DefineImplicitMoveAssignment(Loc, MethodDecl); } + } else if (isa<CXXConversionDecl>(MethodDecl) && + MethodDecl->getParent()->isLambda()) { + CXXConversionDecl *Conversion = cast<CXXConversionDecl>(MethodDecl); + if (Conversion->isLambdaToBlockPointerConversion()) + DefineImplicitLambdaToBlockPointerConversion(Loc, Conversion); + else + DefineImplicitLambdaToFunctionPointerConversion(Loc, Conversion); } else if (MethodDecl->isVirtual()) MarkVTableUsed(Loc, MethodDecl->getParent()); } - if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { - // Recursive functions should be marked when used from another function. - if (CurContext == Function) return; - - // Implicit instantiation of function templates and member functions of - // class templates. - if (Function->isImplicitlyInstantiable()) { - bool AlreadyInstantiated = false; - if (FunctionTemplateSpecializationInfo *SpecInfo - = Function->getTemplateSpecializationInfo()) { - if (SpecInfo->getPointOfInstantiation().isInvalid()) - SpecInfo->setPointOfInstantiation(Loc); - else if (SpecInfo->getTemplateSpecializationKind() - == TSK_ImplicitInstantiation) - AlreadyInstantiated = true; - } else if (MemberSpecializationInfo *MSInfo - = Function->getMemberSpecializationInfo()) { - if (MSInfo->getPointOfInstantiation().isInvalid()) - MSInfo->setPointOfInstantiation(Loc); - else if (MSInfo->getTemplateSpecializationKind() - == TSK_ImplicitInstantiation) - AlreadyInstantiated = true; + + // Recursive functions should be marked when used from another function. + // FIXME: Is this really right? + if (CurContext == Func) return; + + // Implicit instantiation of function templates and member functions of + // class templates. + if (Func->isImplicitlyInstantiable()) { + bool AlreadyInstantiated = false; + SourceLocation PointOfInstantiation = Loc; + if (FunctionTemplateSpecializationInfo *SpecInfo + = Func->getTemplateSpecializationInfo()) { + if (SpecInfo->getPointOfInstantiation().isInvalid()) + SpecInfo->setPointOfInstantiation(Loc); + else if (SpecInfo->getTemplateSpecializationKind() + == TSK_ImplicitInstantiation) { + AlreadyInstantiated = true; + PointOfInstantiation = SpecInfo->getPointOfInstantiation(); + } + } else if (MemberSpecializationInfo *MSInfo + = Func->getMemberSpecializationInfo()) { + if (MSInfo->getPointOfInstantiation().isInvalid()) + MSInfo->setPointOfInstantiation(Loc); + else if (MSInfo->getTemplateSpecializationKind() + == TSK_ImplicitInstantiation) { + AlreadyInstantiated = true; + PointOfInstantiation = MSInfo->getPointOfInstantiation(); } + } - if (!AlreadyInstantiated) { - if (isa<CXXRecordDecl>(Function->getDeclContext()) && - cast<CXXRecordDecl>(Function->getDeclContext())->isLocalClass()) - PendingLocalImplicitInstantiations.push_back(std::make_pair(Function, - Loc)); + if (!AlreadyInstantiated || Func->isConstexpr()) { + if (isa<CXXRecordDecl>(Func->getDeclContext()) && + cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass()) + PendingLocalImplicitInstantiations.push_back( + std::make_pair(Func, PointOfInstantiation)); + else if (Func->isConstexpr()) + // Do not defer instantiations of constexpr functions, to avoid the + // expression evaluator needing to call back into Sema if it sees a + // call to such a function. + InstantiateFunctionDefinition(PointOfInstantiation, Func); + else { + PendingInstantiations.push_back(std::make_pair(Func, + PointOfInstantiation)); + // Notify the consumer that a function was implicitly instantiated. + Consumer.HandleCXXImplicitFunctionInstantiation(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) { + if (!i->isUsed(false) && i->isImplicitlyInstantiable()) + MarkFunctionReferenced(Loc, *i); + } + } + + // Keep track of used but undefined functions. + if (!Func->isPure() && !Func->hasBody() && + Func->getLinkage() != ExternalLinkage) { + SourceLocation &old = UndefinedInternals[Func->getCanonicalDecl()]; + if (old.isInvalid()) old = Loc; + } + + Func->setUsed(true); +} + +static void +diagnoseUncapturableValueReference(Sema &S, SourceLocation loc, + VarDecl *var, DeclContext *DC) { + DeclContext *VarDC = var->getDeclContext(); + + // If the parameter still belongs to the translation unit, then + // we're actually just using one parameter in the declaration of + // the next. + if (isa<ParmVarDecl>(var) && + isa<TranslationUnitDecl>(VarDC)) + return; + + // For C code, don't diagnose about capture if we're not actually in code + // right now; it's impossible to write a non-constant expression outside of + // function context, so we'll get other (more useful) diagnostics later. + // + // For C++, things get a bit more nasty... it would be nice to suppress this + // diagnostic for certain cases like using a local variable in an array bound + // for a member of a local class, but the correct predicate is not obvious. + if (!S.getLangOpts().CPlusPlus && !S.CurContext->isFunctionOrMethod()) + return; + + if (isa<CXXMethodDecl>(VarDC) && + cast<CXXRecordDecl>(VarDC->getParent())->isLambda()) { + S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_lambda) + << var->getIdentifier(); + } else if (FunctionDecl *fn = dyn_cast<FunctionDecl>(VarDC)) { + S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_function) + << var->getIdentifier() << fn->getDeclName(); + } else if (isa<BlockDecl>(VarDC)) { + S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_block) + << var->getIdentifier(); + } else { + // FIXME: Is there any other context where a local variable can be + // declared? + S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_context) + << var->getIdentifier(); + } + + S.Diag(var->getLocation(), diag::note_local_variable_declared_here) + << var->getIdentifier(); + + // FIXME: Add additional diagnostic info about class etc. which prevents + // capture. +} + +/// \brief Capture the given variable in the given lambda expression. +static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI, + VarDecl *Var, QualType FieldType, + QualType DeclRefType, + SourceLocation Loc) { + CXXRecordDecl *Lambda = LSI->Lambda; + + // Build the non-static data member. + FieldDecl *Field + = FieldDecl::Create(S.Context, Lambda, Loc, Loc, 0, FieldType, + S.Context.getTrivialTypeSourceInfo(FieldType, Loc), + 0, false, false); + Field->setImplicit(true); + Field->setAccess(AS_private); + Lambda->addDecl(Field); + + // C++11 [expr.prim.lambda]p21: + // When the lambda-expression is evaluated, the entities that + // are captured by copy are used to direct-initialize each + // corresponding non-static data member of the resulting closure + // object. (For array members, the array elements are + // direct-initialized in increasing subscript order.) These + // initializations are performed in the (unspecified) order in + // which the non-static data members are declared. + + // Introduce a new evaluation context for the initialization, so + // that temporaries introduced as part of the capture are retained + // to be re-"exported" from the lambda expression itself. + S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); + + // C++ [expr.prim.labda]p12: + // An entity captured by a lambda-expression is odr-used (3.2) in + // the scope containing the lambda-expression. + Expr *Ref = new (S.Context) DeclRefExpr(Var, false, DeclRefType, + VK_LValue, Loc); + Var->setReferenced(true); + Var->setUsed(true); + + // When the field has array type, create index variables for each + // dimension of the array. We use these index variables to subscript + // the source array, and other clients (e.g., CodeGen) will perform + // the necessary iteration with these index variables. + SmallVector<VarDecl *, 4> IndexVariables; + QualType BaseType = FieldType; + QualType SizeType = S.Context.getSizeType(); + LSI->ArrayIndexStarts.push_back(LSI->ArrayIndexVars.size()); + while (const ConstantArrayType *Array + = S.Context.getAsConstantArrayType(BaseType)) { + // Create the iteration variable for this array index. + IdentifierInfo *IterationVarName = 0; + { + SmallString<8> Str; + llvm::raw_svector_ostream OS(Str); + OS << "__i" << IndexVariables.size(); + IterationVarName = &S.Context.Idents.get(OS.str()); + } + VarDecl *IterationVar + = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, + IterationVarName, SizeType, + S.Context.getTrivialTypeSourceInfo(SizeType, Loc), + SC_None, SC_None); + IndexVariables.push_back(IterationVar); + LSI->ArrayIndexVars.push_back(IterationVar); + + // Create a reference to the iteration variable. + ExprResult IterationVarRef + = S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc); + assert(!IterationVarRef.isInvalid() && + "Reference to invented variable cannot fail!"); + IterationVarRef = S.DefaultLvalueConversion(IterationVarRef.take()); + 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); + if (Subscript.isInvalid()) { + S.CleanupVarDeclMarking(); + S.DiscardCleanupsInEvaluationContext(); + S.PopExpressionEvaluationContext(); + return ExprError(); + } + + Ref = Subscript.take(); + BaseType = Array->getElementType(); + } + + // Construct the entity that we will be initializing. For an array, this + // will be first element in the array, which may require several levels + // of array-subscript entities. + SmallVector<InitializedEntity, 4> Entities; + Entities.reserve(1 + IndexVariables.size()); + Entities.push_back( + InitializedEntity::InitializeLambdaCapture(Var, Field, Loc)); + for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I) + Entities.push_back(InitializedEntity::InitializeElement(S.Context, + 0, + Entities.back())); + + InitializationKind InitKind + = InitializationKind::CreateDirect(Loc, Loc, Loc); + InitializationSequence Init(S, Entities.back(), InitKind, &Ref, 1); + ExprResult Result(true); + if (!Init.Diagnose(S, Entities.back(), InitKind, &Ref, 1)) + Result = Init.Perform(S, Entities.back(), InitKind, + MultiExprArg(S, &Ref, 1)); + + // If this initialization requires any cleanups (e.g., due to a + // default argument to a copy constructor), note that for the + // lambda. + if (S.ExprNeedsCleanups) + LSI->ExprNeedsCleanups = true; + + // Exit the expression evaluation context used for the capture. + S.CleanupVarDeclMarking(); + S.DiscardCleanupsInEvaluationContext(); + S.PopExpressionEvaluationContext(); + return Result; +} + +bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc, + TryCaptureKind Kind, SourceLocation EllipsisLoc, + bool BuildAndDiagnose, + QualType &CaptureType, + QualType &DeclRefType) { + bool Nested = false; + + DeclContext *DC = CurContext; + if (Var->getDeclContext() == DC) return true; + if (!Var->hasLocalStorage()) return true; + + bool HasBlocksAttr = Var->hasAttr<BlocksAttr>(); + + // Walk up the stack to determine whether we can capture the variable, + // performing the "simple" checks that don't depend on type. We stop when + // we've either hit the declared scope of the variable or find an existing + // capture of that variable. + CaptureType = Var->getType(); + DeclRefType = CaptureType.getNonReferenceType(); + bool Explicit = (Kind != TryCapture_Implicit); + unsigned FunctionScopesIndex = FunctionScopes.size() - 1; + do { + // Only block literals and lambda expressions can capture; other + // scopes don't work. + DeclContext *ParentDC; + if (isa<BlockDecl>(DC)) + ParentDC = DC->getParent(); + else if (isa<CXXMethodDecl>(DC) && + cast<CXXMethodDecl>(DC)->getOverloadedOperator() == OO_Call && + cast<CXXRecordDecl>(DC->getParent())->isLambda()) + ParentDC = DC->getParent()->getParent(); + else { + if (BuildAndDiagnose) + diagnoseUncapturableValueReference(*this, Loc, Var, DC); + return true; + } + + CapturingScopeInfo *CSI = + cast<CapturingScopeInfo>(FunctionScopes[FunctionScopesIndex]); + + // Check whether we've already captured it. + if (CSI->CaptureMap.count(Var)) { + // If we found a capture, any subcaptures are nested. + Nested = true; + + // Retrieve the capture type for this variable. + CaptureType = CSI->getCapture(Var).getCaptureType(); + + // Compute the type of an expression that refers to this variable. + DeclRefType = CaptureType.getNonReferenceType(); + + const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var); + if (Cap.isCopyCapture() && + !(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable)) + DeclRefType.addConst(); + break; + } + + bool IsBlock = isa<BlockScopeInfo>(CSI); + bool IsLambda = !IsBlock; + + // Lambdas are not allowed to capture unnamed variables + // (e.g. anonymous unions). + // FIXME: The C++11 rule don't actually state this explicitly, but I'm + // assuming that's the intent. + if (IsLambda && !Var->getDeclName()) { + if (BuildAndDiagnose) { + Diag(Loc, diag::err_lambda_capture_anonymous_var); + Diag(Var->getLocation(), diag::note_declared_at); + } + return true; + } + + // Prohibit variably-modified types; they're difficult to deal with. + if (Var->getType()->isVariablyModifiedType()) { + if (BuildAndDiagnose) { + if (IsBlock) + Diag(Loc, diag::err_ref_vm_type); else - PendingInstantiations.push_back(std::make_pair(Function, Loc)); + Diag(Loc, diag::err_lambda_capture_vm_type) << Var->getDeclName(); + Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); } + return true; + } + + // Lambdas are not allowed to capture __block variables; they don't + // support the expected semantics. + if (IsLambda && HasBlocksAttr) { + if (BuildAndDiagnose) { + Diag(Loc, diag::err_lambda_capture_block) + << Var->getDeclName(); + Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + } + return true; + } + + if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None && !Explicit) { + // No capture-default + if (BuildAndDiagnose) { + Diag(Loc, diag::err_lambda_impcap) << Var->getDeclName(); + Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getLocStart(), + diag::note_lambda_decl); + } + return true; + } + + FunctionScopesIndex--; + DC = ParentDC; + Explicit = false; + } while (!Var->getDeclContext()->Equals(DC)); + + // Walk back down the scope stack, computing the type of the capture at + // each step, checking type-specific requirements, and adding captures if + // requested. + for (unsigned I = ++FunctionScopesIndex, N = FunctionScopes.size(); I != N; + ++I) { + CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[I]); + + // Compute the type of the capture and of a reference to the capture within + // this scope. + if (isa<BlockScopeInfo>(CSI)) { + Expr *CopyExpr = 0; + bool ByRef = false; + + // Blocks are not allowed to capture arrays. + if (CaptureType->isArrayType()) { + if (BuildAndDiagnose) { + Diag(Loc, diag::err_ref_array_type); + Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + } + return true; + } + + // Forbid the block-capture of autoreleasing variables. + if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) { + if (BuildAndDiagnose) { + Diag(Loc, diag::err_arc_autoreleasing_capture) + << /*block*/ 0; + Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + } + return true; + } + + if (HasBlocksAttr || CaptureType->isReferenceType()) { + // Block capture by reference does not change the capture or + // declaration reference types. + ByRef = true; + } else { + // Block capture by copy introduces 'const'. + CaptureType = CaptureType.getNonReferenceType().withConst(); + DeclRefType = CaptureType; + + if (getLangOpts().CPlusPlus && BuildAndDiagnose) { + if (const RecordType *Record = DeclRefType->getAs<RecordType>()) { + // The capture logic needs the destructor, so make sure we mark it. + // Usually this is unnecessary because most local variables have + // their destructors marked at declaration time, but parameters are + // an exception because it's technically only the call site that + // actually requires the destructor. + if (isa<ParmVarDecl>(Var)) + FinalizeVarWithDestructor(Var, Record); + + // According to the blocks spec, the capture of a variable from + // the stack requires a const copy constructor. This is not true + // of the copy/move done to move a __block variable to the heap. + Expr *DeclRef = new (Context) DeclRefExpr(Var, false, + DeclRefType.withConst(), + VK_LValue, Loc); + ExprResult Result + = PerformCopyInitialization( + InitializedEntity::InitializeBlock(Var->getLocation(), + CaptureType, false), + Loc, Owned(DeclRef)); + + // Build a full-expression copy expression if initialization + // succeeded and used a non-trivial constructor. Recover from + // errors by pretending that the copy isn't necessary. + if (!Result.isInvalid() && + !cast<CXXConstructExpr>(Result.get())->getConstructor() + ->isTrivial()) { + Result = MaybeCreateExprWithCleanups(Result); + CopyExpr = Result.take(); + } + } + } + } + + // Actually capture the variable. + if (BuildAndDiagnose) + CSI->addCapture(Var, HasBlocksAttr, ByRef, Nested, Loc, + SourceLocation(), CaptureType, CopyExpr); + Nested = true; + continue; + } + + LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI); + + // Determine whether we are capturing by reference or by value. + bool ByRef = false; + if (I == N - 1 && Kind != TryCapture_Implicit) { + ByRef = (Kind == TryCapture_ExplicitByRef); + } else { + ByRef = (LSI->ImpCaptureStyle == LambdaScopeInfo::ImpCap_LambdaByref); + } + + // Compute the type of the field that will capture this variable. + if (ByRef) { + // C++11 [expr.prim.lambda]p15: + // An entity is captured by reference if it is implicitly or + // explicitly captured but not captured by copy. It is + // unspecified whether additional unnamed non-static data + // members are declared in the closure type for entities + // captured by reference. + // + // FIXME: It is not clear whether we want to build an lvalue reference + // to the DeclRefType or to CaptureType.getNonReferenceType(). GCC appears + // to do the former, while EDG does the latter. Core issue 1249 will + // clarify, but for now we follow GCC because it's a more permissive and + // easily defensible position. + CaptureType = Context.getLValueReferenceType(DeclRefType); } else { - // Walk redefinitions, as some of them may be instantiable. - for (FunctionDecl::redecl_iterator i(Function->redecls_begin()), - e(Function->redecls_end()); i != e; ++i) { - if (!i->isUsed(false) && i->isImplicitlyInstantiable()) - MarkDeclarationReferenced(Loc, *i); + // C++11 [expr.prim.lambda]p14: + // For each entity captured by copy, an unnamed non-static + // data member is declared in the closure type. The + // declaration order of these members is unspecified. The type + // of such a data member is the type of the corresponding + // captured entity if the entity is not a reference to an + // object, or the referenced type otherwise. [Note: If the + // captured entity is a reference to a function, the + // corresponding data member is also a reference to a + // function. - end note ] + if (const ReferenceType *RefType = CaptureType->getAs<ReferenceType>()){ + if (!RefType->getPointeeType()->isFunctionType()) + CaptureType = RefType->getPointeeType(); + } + + // Forbid the lambda copy-capture of autoreleasing variables. + if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) { + if (BuildAndDiagnose) { + Diag(Loc, diag::err_arc_autoreleasing_capture) << /*lambda*/ 1; + Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + } + return true; } } - // Keep track of used but undefined functions. - if (!Function->isPure() && !Function->hasBody() && - Function->getLinkage() != ExternalLinkage) { - SourceLocation &old = UndefinedInternals[Function->getCanonicalDecl()]; - if (old.isInvalid()) old = Loc; + // Capture this variable in the lambda. + Expr *CopyExpr = 0; + if (BuildAndDiagnose) { + ExprResult Result = captureInLambda(*this, LSI, Var, CaptureType, + DeclRefType, Loc); + if (!Result.isInvalid()) + CopyExpr = Result.take(); + } + + // Compute the type of a reference to this captured variable. + if (ByRef) + DeclRefType = CaptureType.getNonReferenceType(); + else { + // C++ [expr.prim.lambda]p5: + // The closure type for a lambda-expression has a public inline + // function call operator [...]. This function call operator is + // declared const (9.3.1) if and only if the lambda-expression’s + // parameter-declaration-clause is not followed by mutable. + DeclRefType = CaptureType.getNonReferenceType(); + if (!LSI->Mutable && !CaptureType->isReferenceType()) + DeclRefType.addConst(); } + + // Add the capture. + if (BuildAndDiagnose) + CSI->addCapture(Var, /*IsBlock=*/false, ByRef, Nested, Loc, + EllipsisLoc, CaptureType, CopyExpr); + Nested = true; + } - Function->setUsed(true); - return; + return false; +} + +bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc, + TryCaptureKind Kind, SourceLocation EllipsisLoc) { + QualType CaptureType; + QualType DeclRefType; + return tryCaptureVariable(Var, Loc, Kind, EllipsisLoc, + /*BuildAndDiagnose=*/true, CaptureType, + DeclRefType); +} + +QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) { + QualType CaptureType; + QualType DeclRefType; + + // Determine whether we can capture this variable. + if (tryCaptureVariable(Var, Loc, TryCapture_Implicit, SourceLocation(), + /*BuildAndDiagnose=*/false, CaptureType, DeclRefType)) + return QualType(); + + return DeclRefType; +} + +static void MarkVarDeclODRUsed(Sema &SemaRef, VarDecl *Var, + SourceLocation Loc) { + // Keep track of used but undefined variables. + // FIXME: We shouldn't suppress this warning for static data members. + if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly && + Var->getLinkage() != ExternalLinkage && + !(Var->isStaticDataMember() && Var->hasInit())) { + SourceLocation &old = SemaRef.UndefinedInternals[Var->getCanonicalDecl()]; + if (old.isInvalid()) old = Loc; } - if (VarDecl *Var = dyn_cast<VarDecl>(D)) { - // Implicit instantiation of static data members of class templates. - if (Var->isStaticDataMember() && - Var->getInstantiatedFromStaticDataMember()) { - MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); - assert(MSInfo && "Missing member specialization information?"); - if (MSInfo->getPointOfInstantiation().isInvalid() && - MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) { - MSInfo->setPointOfInstantiation(Loc); + SemaRef.tryCaptureVariable(Var, Loc); + + Var->setUsed(true); +} + +void Sema::UpdateMarkingForLValueToRValue(Expr *E) { + // Per C++11 [basic.def.odr], a variable is odr-used "unless it is + // an object that satisfies the requirements for appearing in a + // constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) + // is immediately applied." This function handles the lvalue-to-rvalue + // conversion part. + MaybeODRUseExprs.erase(E->IgnoreParens()); +} + +ExprResult Sema::ActOnConstantExpression(ExprResult Res) { + if (!Res.isUsable()) + return Res; + + // If a constant-expression is a reference to a variable where we delay + // deciding whether it is an odr-use, just assume we will apply the + // lvalue-to-rvalue conversion. In the one case where this doesn't happen + // (a non-type template argument), we have special handling anyway. + UpdateMarkingForLValueToRValue(Res.get()); + return Res; +} + +void Sema::CleanupVarDeclMarking() { + for (llvm::SmallPtrSetIterator<Expr*> i = MaybeODRUseExprs.begin(), + e = MaybeODRUseExprs.end(); + i != e; ++i) { + VarDecl *Var; + SourceLocation Loc; + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(*i)) { + Var = cast<VarDecl>(DRE->getDecl()); + Loc = DRE->getLocation(); + } else if (MemberExpr *ME = dyn_cast<MemberExpr>(*i)) { + Var = cast<VarDecl>(ME->getMemberDecl()); + Loc = ME->getMemberLoc(); + } else { + llvm_unreachable("Unexpcted expression"); + } + + MarkVarDeclODRUsed(*this, Var, Loc); + } + + MaybeODRUseExprs.clear(); +} + +// Mark a VarDecl referenced, and perform the necessary handling to compute +// odr-uses. +static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, + VarDecl *Var, Expr *E) { + Var->setReferenced(); + + if (!IsPotentiallyEvaluatedContext(SemaRef)) + return; + + // Implicit instantiation of static data members of class templates. + if (Var->isStaticDataMember() && Var->getInstantiatedFromStaticDataMember()) { + MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); + assert(MSInfo && "Missing member specialization information?"); + bool AlreadyInstantiated = !MSInfo->getPointOfInstantiation().isInvalid(); + if (MSInfo->getTemplateSpecializationKind() == TSK_ImplicitInstantiation && + (!AlreadyInstantiated || + Var->isUsableInConstantExpressions(SemaRef.Context))) { + if (!AlreadyInstantiated) { // This is a modification of an existing AST node. Notify listeners. - if (ASTMutationListener *L = getASTMutationListener()) + if (ASTMutationListener *L = SemaRef.getASTMutationListener()) L->StaticDataMemberInstantiated(Var); - PendingInstantiations.push_back(std::make_pair(Var, Loc)); + MSInfo->setPointOfInstantiation(Loc); } - } + SourceLocation PointOfInstantiation = MSInfo->getPointOfInstantiation(); + if (Var->isUsableInConstantExpressions(SemaRef.Context)) + // Do not defer instantiations of variables which could be used in a + // constant expression. + SemaRef.InstantiateStaticDataMemberDefinition(PointOfInstantiation,Var); + else + SemaRef.PendingInstantiations.push_back( + std::make_pair(Var, PointOfInstantiation)); + } + } + + // Per C++11 [basic.def.odr], a variable is odr-used "unless it is + // an object that satisfies the requirements for appearing in a + // constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) + // is immediately applied." We check the first part here, and + // Sema::UpdateMarkingForLValueToRValue deals with the second part. + // Note that we use the C++11 definition everywhere because nothing in + // C++03 depends on whether we get the C++03 version correct. This does not + // apply to references, since they are not objects. + const VarDecl *DefVD; + if (E && !isa<ParmVarDecl>(Var) && !Var->getType()->isReferenceType() && + Var->isUsableInConstantExpressions(SemaRef.Context) && + Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE()) + SemaRef.MaybeODRUseExprs.insert(E); + else + MarkVarDeclODRUsed(SemaRef, Var, Loc); +} - // Keep track of used but undefined variables. We make a hole in - // the warning for static const data members with in-line - // initializers. - if (Var->hasDefinition() == VarDecl::DeclarationOnly - && Var->getLinkage() != ExternalLinkage - && !(Var->isStaticDataMember() && Var->hasInit())) { - SourceLocation &old = UndefinedInternals[Var->getCanonicalDecl()]; - if (old.isInvalid()) old = Loc; - } +/// \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); +} - D->setUsed(true); +static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, + Decl *D, Expr *E) { + if (VarDecl *Var = dyn_cast<VarDecl>(D)) { + DoMarkVarDeclReferenced(SemaRef, Loc, Var, E); return; } + + SemaRef.MarkAnyDeclReferenced(Loc, D); +} + +/// \brief Perform reference-marking and odr-use handling for a DeclRefExpr. +void Sema::MarkDeclRefReferenced(DeclRefExpr *E) { + MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E); +} + +/// \brief Perform reference-marking and odr-use handling for a MemberExpr. +void Sema::MarkMemberReferenced(MemberExpr *E) { + MarkExprReferenced(*this, E->getMemberLoc(), E->getMemberDecl(), 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. +void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D) { + if (VarDecl *VD = dyn_cast<VarDecl>(D)) + MarkVariableReferenced(Loc, VD); + else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + MarkFunctionReferenced(Loc, FD); + else + D->setReferenced(); } namespace { @@ -9331,7 +10478,8 @@ namespace { bool MarkReferencedDecls::TraverseTemplateArgument( const TemplateArgument &Arg) { if (Arg.getKind() == TemplateArgument::Declaration) { - S.MarkDeclarationReferenced(Loc, Arg.getAsDecl()); + if (Decl *D = Arg.getAsDecl()) + S.MarkAnyDeclReferenced(Loc, D); } return Inherited::TraverseTemplateArgument(Arg); @@ -9357,38 +10505,51 @@ namespace { /// potentially-evaluated subexpressions as "referenced". class EvaluatedExprMarker : public EvaluatedExprVisitor<EvaluatedExprMarker> { Sema &S; + bool SkipLocalVariables; public: typedef EvaluatedExprVisitor<EvaluatedExprMarker> Inherited; - explicit EvaluatedExprMarker(Sema &S) : Inherited(S.Context), S(S) { } + EvaluatedExprMarker(Sema &S, bool SkipLocalVariables) + : Inherited(S.Context), S(S), SkipLocalVariables(SkipLocalVariables) { } void VisitDeclRefExpr(DeclRefExpr *E) { - S.MarkDeclarationReferenced(E->getLocation(), E->getDecl()); + // If we were asked not to visit local variables, don't. + if (SkipLocalVariables) { + if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) + if (VD->hasLocalStorage()) + return; + } + + S.MarkDeclRefReferenced(E); } void VisitMemberExpr(MemberExpr *E) { - S.MarkDeclarationReferenced(E->getMemberLoc(), E->getMemberDecl()); + S.MarkMemberReferenced(E); Inherited::VisitMemberExpr(E); } + void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { + S.MarkFunctionReferenced(E->getLocStart(), + const_cast<CXXDestructorDecl*>(E->getTemporary()->getDestructor())); + Visit(E->getSubExpr()); + } + void VisitCXXNewExpr(CXXNewExpr *E) { - if (E->getConstructor()) - S.MarkDeclarationReferenced(E->getLocStart(), E->getConstructor()); if (E->getOperatorNew()) - S.MarkDeclarationReferenced(E->getLocStart(), E->getOperatorNew()); + S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorNew()); if (E->getOperatorDelete()) - S.MarkDeclarationReferenced(E->getLocStart(), E->getOperatorDelete()); + S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete()); Inherited::VisitCXXNewExpr(E); } - + void VisitCXXDeleteExpr(CXXDeleteExpr *E) { if (E->getOperatorDelete()) - S.MarkDeclarationReferenced(E->getLocStart(), E->getOperatorDelete()); + S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete()); QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType()); if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) { CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl()); - S.MarkDeclarationReferenced(E->getLocStart(), + S.MarkFunctionReferenced(E->getLocStart(), S.LookupDestructor(Record)); } @@ -9396,24 +10557,31 @@ namespace { } void VisitCXXConstructExpr(CXXConstructExpr *E) { - S.MarkDeclarationReferenced(E->getLocStart(), E->getConstructor()); + S.MarkFunctionReferenced(E->getLocStart(), E->getConstructor()); Inherited::VisitCXXConstructExpr(E); } - void VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { - S.MarkDeclarationReferenced(E->getLocation(), E->getDecl()); - } - void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { Visit(E->getExpr()); } + + void VisitImplicitCastExpr(ImplicitCastExpr *E) { + Inherited::VisitImplicitCastExpr(E); + + if (E->getCastKind() == CK_LValueToRValue) + S.UpdateMarkingForLValueToRValue(E->getSubExpr()); + } }; } /// \brief Mark any declarations that appear within this expression or any /// potentially-evaluated subexpressions as "referenced". -void Sema::MarkDeclarationsReferencedInExpr(Expr *E) { - EvaluatedExprMarker(*this).Visit(E); +/// +/// \param SkipLocalVariables If true, don't mark local variables as +/// 'referenced'. +void Sema::MarkDeclarationsReferencedInExpr(Expr *E, + bool SkipLocalVariables) { + EvaluatedExprMarker(*this, SkipLocalVariables).Visit(E); } /// \brief Emit a diagnostic that describes an effect on the run-time behavior @@ -9439,6 +10607,10 @@ bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement, // The argument will never be evaluated, so don't complain. break; + case ConstantEvaluated: + // Relevant diagnostics should be produced by constant evaluation. + break; + case PotentiallyEvaluated: case PotentiallyEvaluatedIfUsed: if (Statement && getCurFunctionOrMethodDecl()) { @@ -9449,10 +10621,6 @@ bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement, Diag(Loc, PD); return true; - - case PotentiallyPotentiallyEvaluated: - ExprEvalContexts.back().addDiagnostic(Loc, PD); - break; } return false; @@ -9463,6 +10631,13 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc, if (ReturnType->isVoidType() || !ReturnType->isIncompleteType()) return false; + // If we're inside a decltype's expression, don't check for a valid return + // type or construct temporaries until we know whether this is the last call. + if (ExprEvalContexts.back().IsDecltype) { + ExprEvalContexts.back().DelayedDecltypeCalls.push_back(CE); + return false; + } + PartialDiagnostic Note = FD ? PDiag(diag::note_function_with_incomplete_return_type_declared_here) << FD->getDeclName() : PDiag(); @@ -9522,7 +10697,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { Diag(Loc, diagnostic) << E->getSourceRange(); - SourceLocation Open = E->getSourceRange().getBegin(); + SourceLocation Open = E->getLocStart(); SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd()); Diag(Loc, diag::note_condition_assign_silence) << FixItHint::CreateInsertion(Open, "(") @@ -9556,9 +10731,10 @@ void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) { SourceLocation Loc = opE->getOperatorLoc(); Diag(Loc, diag::warn_equality_with_extra_parens) << E->getSourceRange(); + SourceRange ParenERange = ParenE->getSourceRange(); Diag(Loc, diag::note_equality_comparison_silence) - << FixItHint::CreateRemoval(ParenE->getSourceRange().getBegin()) - << FixItHint::CreateRemoval(ParenE->getSourceRange().getEnd()); + << FixItHint::CreateRemoval(ParenERange.getBegin()) + << FixItHint::CreateRemoval(ParenERange.getEnd()); Diag(Loc, diag::note_equality_comparison_to_assign) << FixItHint::CreateReplacement(Loc, "="); } @@ -9574,7 +10750,7 @@ ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) { E = result.take(); if (!E->isTypeDependent()) { - if (getLangOptions().CPlusPlus) + if (getLangOpts().CPlusPlus) return CheckCXXBooleanCondition(E); // C++ 6.4p4 ExprResult ERes = DefaultFunctionArrayLvalueConversion(E); @@ -9613,7 +10789,6 @@ namespace { ExprResult VisitStmt(Stmt *S) { llvm_unreachable("unexpected statement!"); - return ExprError(); } ExprResult VisitExpr(Expr *E) { @@ -9662,7 +10837,7 @@ namespace { E->setType(VD->getType()); assert(E->getValueKind() == VK_RValue); - if (S.getLangOptions().CPlusPlus && + if (S.getLangOpts().CPlusPlus && !(isa<CXXMethodDecl>(VD) && cast<CXXMethodDecl>(VD)->isInstance())) E->setValueKind(VK_LValue); @@ -9706,7 +10881,6 @@ namespace { ExprResult VisitStmt(Stmt *S) { llvm_unreachable("unexpected statement!"); - return ExprError(); } ExprResult VisitExpr(Expr *E) { @@ -9870,20 +11044,39 @@ ExprResult RebuildUnknownAnyExpr::VisitObjCMessageExpr(ObjCMessageExpr *E) { ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *E) { // The only case we should ever see here is a function-to-pointer decay. - assert(E->getCastKind() == CK_FunctionToPointerDecay); - assert(E->getValueKind() == VK_RValue); - assert(E->getObjectKind() == OK_Ordinary); + if (E->getCastKind() == CK_FunctionToPointerDecay) { + assert(E->getValueKind() == VK_RValue); + assert(E->getObjectKind() == OK_Ordinary); + + E->setType(DestType); + + // Rebuild the sub-expression as the pointee (function) type. + DestType = DestType->castAs<PointerType>()->getPointeeType(); + + ExprResult Result = Visit(E->getSubExpr()); + if (!Result.isUsable()) return ExprError(); + + E->setSubExpr(Result.take()); + return S.Owned(E); + } else if (E->getCastKind() == CK_LValueToRValue) { + assert(E->getValueKind() == VK_RValue); + assert(E->getObjectKind() == OK_Ordinary); - E->setType(DestType); + assert(isa<BlockPointerType>(E->getType())); - // Rebuild the sub-expression as the pointee (function) type. - DestType = DestType->castAs<PointerType>()->getPointeeType(); + E->setType(DestType); - ExprResult Result = Visit(E->getSubExpr()); - if (!Result.isUsable()) return ExprError(); + // The sub-expression has to be a lvalue reference, so rebuild it as such. + DestType = S.Context.getLValueReferenceType(DestType); - E->setSubExpr(Result.take()); - return S.Owned(E); + ExprResult Result = Visit(E->getSubExpr()); + if (!Result.isUsable()) return ExprError(); + + E->setSubExpr(Result.take()); + return S.Owned(E); + } else { + llvm_unreachable("Unhandled cast type!"); + } } ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) { @@ -9915,7 +11108,7 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) { } // Function references aren't l-values in C. - if (!S.getLangOptions().CPlusPlus) + if (!S.getLangOpts().CPlusPlus) ValueKind = VK_RValue; // - variables @@ -9957,6 +11150,10 @@ ExprResult Sema::checkUnknownAnyCast(SourceRange TypeRange, QualType CastType, return CastExpr; } +ExprResult Sema::forceUnknownAnyToType(Expr *E, QualType ToType) { + return RebuildUnknownAnyExpr(*this, ToType).Visit(E); +} + static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) { Expr *orig = E; unsigned diagID = diag::err_uncasted_use_of_unknown_any; @@ -10003,11 +11200,13 @@ static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) { /// Check for operands with placeholder types and complain if found. /// Returns true if there was an error and no recovery was possible. ExprResult Sema::CheckPlaceholderExpr(Expr *E) { - // Placeholder types are always *exactly* the appropriate builtin type. - QualType type = E->getType(); + const BuiltinType *placeholderType = E->getType()->getAsPlaceholderType(); + if (!placeholderType) return Owned(E); + + switch (placeholderType->getKind()) { // Overloaded expressions. - if (type == Context.OverloadTy) { + case BuiltinType::Overload: { // Try to resolve a single function template specialization. // This is obligatory. ExprResult result = Owned(E); @@ -10023,19 +11222,37 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { } // Bound member functions. - if (type == Context.BoundMemberTy) { + case BuiltinType::BoundMember: { ExprResult result = Owned(E); tryToRecoverWithCall(result, PDiag(diag::err_bound_member_function), /*complain*/ true); return result; - } + } + + // ARC unbridged casts. + case BuiltinType::ARCUnbridgedCast: { + Expr *realCast = stripARCUnbridgedCast(E); + diagnoseARCUnbridgedCast(realCast); + return Owned(realCast); + } // Expressions of unknown type. - if (type == Context.UnknownAnyTy) + case BuiltinType::UnknownAny: return diagnoseUnknownAnyExpr(*this, E); - assert(!type->isPlaceholderType()); - return Owned(E); + // Pseudo-objects. + case BuiltinType::PseudoObject: + return checkPseudoObjectRValue(E); + + // Everything else should be impossible. +#define BUILTIN_TYPE(Id, SingletonId) \ + case BuiltinType::Id: +#define PLACEHOLDER_TYPE(Id, SingletonId) +#include "clang/AST/BuiltinTypes.def" + break; + } + + llvm_unreachable("invalid placeholder type!"); } bool Sema::CheckCaseExpression(Expr *E) { @@ -10045,3 +11262,28 @@ bool Sema::CheckCaseExpression(Expr *E) { return E->getType()->isIntegralOrEnumerationType(); return false; } + +/// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals. +ExprResult +Sema::ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { + assert((Kind == tok::kw___objc_yes || Kind == tok::kw___objc_no) && + "Unknown Objective-C Boolean value!"); + QualType ObjCBoolLiteralQT = Context.ObjCBuiltinBoolTy; + // signed char is the default type for boolean literals. Use 'BOOL' + // instead, if BOOL typedef is visible in its scope instead. + Decl *TD = + LookupSingleName(TUScope, &Context.Idents.get("BOOL"), + SourceLocation(), LookupOrdinaryName); + if (TypedefDecl *BoolTD = dyn_cast_or_null<TypedefDecl>(TD)) { + QualType QT = BoolTD->getUnderlyingType(); + if (!QT->isIntegralOrUnscopedEnumerationType()) { + Diag(OpLoc, diag::warn_bool_for_boolean_literal) << QT; + Diag(BoolTD->getLocation(), diag::note_previous_declaration); + } + else + ObjCBoolLiteralQT = QT; + } + + return Owned(new (Context) ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes, + ObjCBoolLiteralQT, OpLoc)); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp index 3300444..31a8115 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp @@ -20,6 +20,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/TemplateDeduction.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/CharUnits.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" @@ -28,6 +29,8 @@ #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" +#include "TypeLocBuilder.h" +#include "llvm/ADT/APInt.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -265,6 +268,22 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, return ParsedType(); } +ParsedType Sema::getDestructorType(const DeclSpec& DS, ParsedType ObjectType) { + if (DS.getTypeSpecType() == DeclSpec::TST_error || !ObjectType) + return ParsedType(); + assert(DS.getTypeSpecType() == DeclSpec::TST_decltype + && "only get destructor types from declspecs"); + QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); + QualType SearchType = GetTypeFromParser(ObjectType); + if (SearchType->isDependentType() || Context.hasSameUnqualifiedType(SearchType, T)) { + return ParsedType::make(T); + } + + Diag(DS.getTypeSpecTypeLoc(), diag::err_destructor_expr_type_mismatch) + << T << SearchType; + return ParsedType(); +} + /// \brief Build a C++ typeid expression with a type operand. ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc, @@ -293,7 +312,6 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc, Expr *E, SourceLocation RParenLoc) { - bool isUnevaluatedOperand = true; if (E && !E->isTypeDependent()) { if (E->getType()->isPlaceholderType()) { ExprResult result = CheckPlaceholderExpr(E); @@ -315,7 +333,11 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, // polymorphic class type [...] [the] expression is an unevaluated // operand. [...] if (RecordD->isPolymorphic() && E->Classify(Context).isGLValue()) { - isUnevaluatedOperand = false; + // The subexpression is potentially evaluated; switch the context + // and recheck the subexpression. + ExprResult Result = TranformToPotentiallyEvaluated(E); + if (Result.isInvalid()) return ExprError(); + E = Result.take(); // We require a vtable to query the type at run time. MarkVTableUsed(TypeidLoc, RecordD); @@ -335,12 +357,6 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, } } - // If this is an unevaluated operand, clear out the set of - // declaration references we have been computing and eliminate any - // temporaries introduced in its computation. - if (isUnevaluatedOperand) - ExprEvalContexts.back().Context = Unevaluated; - return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(), E, SourceRange(TypeidLoc, RParenLoc))); @@ -525,7 +541,7 @@ Sema::ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *Ex) { ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, bool IsThrownVarInScope) { // Don't report an error if 'throw' is used in system headers. - if (!getLangOptions().CXXExceptions && + if (!getLangOpts().CXXExceptions && !getSourceManager().isInSystemHeader(OpLoc)) Diag(OpLoc, diag::err_exceptions_disabled) << "throw"; @@ -621,37 +637,23 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E, if (isPointer) return Owned(E); - // If the class has a non-trivial destructor, we must be able to call it. - if (RD->hasTrivialDestructor()) + // If the class has a destructor, we must be able to call it. + if (RD->hasIrrelevantDestructor()) return Owned(E); - CXXDestructorDecl *Destructor - = const_cast<CXXDestructorDecl*>(LookupDestructor(RD)); + CXXDestructorDecl *Destructor = LookupDestructor(RD); if (!Destructor) return Owned(E); - MarkDeclarationReferenced(E->getExprLoc(), Destructor); + MarkFunctionReferenced(E->getExprLoc(), Destructor); CheckDestructorAccess(E->getExprLoc(), Destructor, PDiag(diag::err_access_dtor_exception) << Ty); + DiagnoseUseOfDecl(Destructor, E->getExprLoc()); return Owned(E); } -QualType Sema::getAndCaptureCurrentThisType() { - // Ignore block scopes: we can capture through them. - // Ignore nested enum scopes: we'll diagnose non-constant expressions - // where they're invalid, and other uses are legitimate. - // Don't ignore nested class scopes: you can't use 'this' in a local class. - DeclContext *DC = CurContext; - unsigned NumBlocks = 0; - while (true) { - if (isa<BlockDecl>(DC)) { - DC = cast<BlockDecl>(DC)->getDeclContext(); - ++NumBlocks; - } else if (isa<EnumDecl>(DC)) - DC = cast<EnumDecl>(DC)->getDeclContext(); - else break; - } - +QualType Sema::getCurrentThisType() { + DeclContext *DC = getFunctionLevelDeclContext(); QualType ThisTy; if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) { if (method && method->isInstance()) @@ -666,23 +668,74 @@ QualType Sema::getAndCaptureCurrentThisType() { ThisTy = Context.getPointerType(Context.getRecordType(RD)); } - // Mark that we're closing on 'this' in all the block scopes we ignored. - if (!ThisTy.isNull()) - for (unsigned idx = FunctionScopes.size() - 1; - NumBlocks; --idx, --NumBlocks) - cast<BlockScopeInfo>(FunctionScopes[idx])->CapturesCXXThis = true; - return ThisTy; } +void Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit) { + // We don't need to capture this in an unevaluated context. + if (ExprEvalContexts.back().Context == Unevaluated && !Explicit) + return; + + // Otherwise, check that we can capture 'this'. + unsigned NumClosures = 0; + for (unsigned idx = FunctionScopes.size() - 1; idx != 0; idx--) { + if (CapturingScopeInfo *CSI = + dyn_cast<CapturingScopeInfo>(FunctionScopes[idx])) { + if (CSI->CXXThisCaptureIndex != 0) { + // 'this' is already being captured; there isn't anything more to do. + break; + } + + if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByref || + CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByval || + CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_Block || + Explicit) { + // This closure can capture 'this'; continue looking upwards. + NumClosures++; + Explicit = false; + continue; + } + // This context can't implicitly capture 'this'; fail out. + Diag(Loc, diag::err_this_capture) << Explicit; + return; + } + break; + } + + // Mark that we're implicitly capturing 'this' in all the scopes we skipped. + // FIXME: We need to delay this marking in PotentiallyPotentiallyEvaluated + // contexts. + for (unsigned idx = FunctionScopes.size() - 1; + NumClosures; --idx, --NumClosures) { + CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]); + Expr *ThisExpr = 0; + QualType ThisTy = getCurrentThisType(); + if (LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI)) { + // For lambda expressions, build a field and an initializing expression. + CXXRecordDecl *Lambda = LSI->Lambda; + FieldDecl *Field + = FieldDecl::Create(Context, Lambda, Loc, Loc, 0, ThisTy, + Context.getTrivialTypeSourceInfo(ThisTy, Loc), + 0, false, false); + Field->setImplicit(true); + Field->setAccess(AS_private); + Lambda->addDecl(Field); + ThisExpr = new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/true); + } + bool isNested = NumClosures > 1; + CSI->addThisCapture(isNested, Loc, ThisTy, ThisExpr); + } +} + ExprResult Sema::ActOnCXXThis(SourceLocation Loc) { /// C++ 9.3.2: In the body of a non-static member function, the keyword this /// is a non-lvalue expression whose value is the address of the object for /// which the function is called. - QualType ThisTy = getAndCaptureCurrentThisType(); + QualType ThisTy = getCurrentThisType(); if (ThisTy.isNull()) return Diag(Loc, diag::err_invalid_this_use); + CheckCXXThisCapture(Loc); return Owned(new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false)); } @@ -715,10 +768,10 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, unsigned NumExprs = exprs.size(); Expr **Exprs = (Expr**)exprs.get(); SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc(); - SourceRange FullRange = SourceRange(TyBeginLoc, RParenLoc); if (Ty->isDependentType() || - CallExpr::hasAnyTypeDependentArguments(Exprs, NumExprs)) { + CallExpr::hasAnyTypeDependentArguments( + llvm::makeArrayRef(Exprs, NumExprs))) { exprs.release(); return Owned(CXXUnresolvedConstructExpr::Create(Context, TInfo, @@ -727,39 +780,64 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, RParenLoc)); } - if (Ty->isArrayType()) - return ExprError(Diag(TyBeginLoc, - diag::err_value_init_for_array_type) << FullRange); - if (!Ty->isVoidType() && - RequireCompleteType(TyBeginLoc, Ty, - PDiag(diag::err_invalid_incomplete_type_use) - << FullRange)) - return ExprError(); - - if (RequireNonAbstractType(TyBeginLoc, Ty, - diag::err_allocation_of_abstract_type)) - return ExprError(); - + bool ListInitialization = LParenLoc.isInvalid(); + assert((!ListInitialization || (NumExprs == 1 && isa<InitListExpr>(Exprs[0]))) + && "List initialization must have initializer list as expression."); + SourceRange FullRange = SourceRange(TyBeginLoc, + ListInitialization ? Exprs[0]->getSourceRange().getEnd() : RParenLoc); // C++ [expr.type.conv]p1: // If the expression list is a single expression, the type conversion // expression is equivalent (in definedness, and if defined in meaning) to the // corresponding cast expression. - if (NumExprs == 1) { + if (NumExprs == 1 && !ListInitialization) { Expr *Arg = Exprs[0]; exprs.release(); return BuildCXXFunctionalCastExpr(TInfo, LParenLoc, Arg, RParenLoc); } + QualType ElemTy = Ty; + if (Ty->isArrayType()) { + if (!ListInitialization) + return ExprError(Diag(TyBeginLoc, + diag::err_value_init_for_array_type) << FullRange); + ElemTy = Context.getBaseElementType(Ty); + } + + if (!Ty->isVoidType() && + RequireCompleteType(TyBeginLoc, ElemTy, + PDiag(diag::err_invalid_incomplete_type_use) + << FullRange)) + return ExprError(); + + if (RequireNonAbstractType(TyBeginLoc, Ty, + diag::err_allocation_of_abstract_type)) + return ExprError(); + InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo); InitializationKind Kind - = NumExprs ? InitializationKind::CreateDirect(TyBeginLoc, - LParenLoc, RParenLoc) + = NumExprs ? ListInitialization + ? InitializationKind::CreateDirectList(TyBeginLoc) + : InitializationKind::CreateDirect(TyBeginLoc, + LParenLoc, RParenLoc) : InitializationKind::CreateValue(TyBeginLoc, LParenLoc, RParenLoc); InitializationSequence InitSeq(*this, Entity, Kind, Exprs, NumExprs); ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(exprs)); + if (!Result.isInvalid() && ListInitialization && + isa<InitListExpr>(Result.get())) { + // If the list-initialization doesn't involve a constructor call, we'll get + // the initializer-list (with corrected type) back, but that's not what we + // want, since it will be treated as an initializer list in further + // processing. Explicitly insert a cast here. + InitListExpr *List = cast<InitListExpr>(Result.take()); + Result = Owned(CXXFunctionalCastExpr::Create(Context, List->getType(), + Expr::getValueKindForType(TInfo->getType()), + TInfo, TyBeginLoc, CK_NoOp, + List, /*Path=*/0, RParenLoc)); + } + // FIXME: Improve AST representation? return move(Result); } @@ -820,18 +898,29 @@ static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc, return (del->getNumParams() == 2); } -/// ActOnCXXNew - Parsed a C++ 'new' expression (C++ 5.3.4), as in e.g.: +/// \brief Parsed a C++ 'new' expression (C++ 5.3.4). + +/// E.g.: /// @code new (memory) int[size][4] @endcode /// or /// @code ::new Foo(23, "hello") @endcode -/// For the interpretation of this heap of arguments, consult the base version. +/// +/// \param StartLoc The first location of the expression. +/// \param UseGlobal True if 'new' was prefixed with '::'. +/// \param PlacementLParen Opening paren of the placement arguments. +/// \param PlacementArgs Placement new arguments. +/// \param PlacementRParen Closing paren of the placement arguments. +/// \param TypeIdParens If the type is in parens, the source range. +/// \param D The type to be allocated, as well as array dimensions. +/// \param ConstructorLParen Opening paren of the constructor args, empty if +/// initializer-list syntax is used. +/// \param ConstructorArgs Constructor/initialization arguments. +/// \param ConstructorRParen Closing paren of the constructor args. ExprResult Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, SourceRange TypeIdParens, - Declarator &D, SourceLocation ConstructorLParen, - MultiExprArg ConstructorArgs, - SourceLocation ConstructorRParen) { + Declarator &D, Expr *Initializer) { bool TypeContainsAuto = D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto; Expr *ArraySize = 0; @@ -861,11 +950,11 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr; if (Expr *NumElts = (Expr *)Array.NumElts) { - if (!NumElts->isTypeDependent() && !NumElts->isValueDependent() && - !NumElts->isIntegerConstantExpr(Context)) { - Diag(D.getTypeObject(I).Loc, diag::err_new_array_nonconst) - << NumElts->getSourceRange(); - return ExprError(); + if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) { + Array.NumElts = VerifyIntegerConstantExpression(NumElts, 0, + PDiag(diag::err_new_array_nonconst)).take(); + if (!Array.NumElts) + return ExprError(); } } } @@ -876,6 +965,10 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, if (D.isInvalidType()) return ExprError(); + SourceRange DirectInitRange; + if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) + DirectInitRange = List->getSourceRange(); + return BuildCXXNew(StartLoc, UseGlobal, PlacementLParen, move(PlacementArgs), @@ -884,12 +977,30 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, AllocType, TInfo, ArraySize, - ConstructorLParen, - move(ConstructorArgs), - ConstructorRParen, + DirectInitRange, + Initializer, TypeContainsAuto); } +static bool isLegalArrayNewInitializer(CXXNewExpr::InitializationStyle Style, + Expr *Init) { + if (!Init) + return true; + if (ParenListExpr *PLE = dyn_cast<ParenListExpr>(Init)) + return PLE->getNumExprs() == 0; + if (isa<ImplicitValueInitExpr>(Init)) + return true; + else if (CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) + return !CCE->isListInitialization() && + CCE->getConstructor()->isDefaultConstructor(); + else if (Style == CXXNewExpr::ListInit) { + assert(isa<InitListExpr>(Init) && + "Shouldn't create list CXXConstructExprs for arrays."); + return true; + } + return false; +} + ExprResult Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, @@ -899,37 +1010,76 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, QualType AllocType, TypeSourceInfo *AllocTypeInfo, Expr *ArraySize, - SourceLocation ConstructorLParen, - MultiExprArg ConstructorArgs, - SourceLocation ConstructorRParen, + SourceRange DirectInitRange, + Expr *Initializer, bool TypeMayContainAuto) { SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange(); + CXXNewExpr::InitializationStyle initStyle; + if (DirectInitRange.isValid()) { + assert(Initializer && "Have parens but no initializer."); + initStyle = CXXNewExpr::CallInit; + } else if (Initializer && isa<InitListExpr>(Initializer)) + initStyle = CXXNewExpr::ListInit; + else { + // In template instantiation, the initializer could be a CXXDefaultArgExpr + // unwrapped from a CXXConstructExpr that was implicitly built. There is no + // particularly sane way we can handle this (especially since it can even + // occur for array new), so we throw the initializer away and have it be + // rebuilt. + if (Initializer && isa<CXXDefaultArgExpr>(Initializer)) + Initializer = 0; + assert((!Initializer || isa<ImplicitValueInitExpr>(Initializer) || + isa<CXXConstructExpr>(Initializer)) && + "Initializer expression that cannot have been implicitly created."); + initStyle = CXXNewExpr::NoInit; + } + + Expr **Inits = &Initializer; + unsigned NumInits = Initializer ? 1 : 0; + if (initStyle == CXXNewExpr::CallInit) { + if (ParenListExpr *List = dyn_cast<ParenListExpr>(Initializer)) { + Inits = List->getExprs(); + NumInits = List->getNumExprs(); + } else if (CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Initializer)){ + if (!isa<CXXTemporaryObjectExpr>(CCE)) { + // Can happen in template instantiation. Since this is just an implicit + // construction, we just take it apart and rebuild it. + Inits = CCE->getArgs(); + NumInits = CCE->getNumArgs(); + } + } + } + // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. if (TypeMayContainAuto && AllocType->getContainedAutoType()) { - if (ConstructorArgs.size() == 0) + if (initStyle == CXXNewExpr::NoInit || NumInits == 0) return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg) << AllocType << TypeRange); - if (ConstructorArgs.size() != 1) { - Expr *FirstBad = ConstructorArgs.get()[1]; - return ExprError(Diag(FirstBad->getSourceRange().getBegin(), + if (initStyle == CXXNewExpr::ListInit) + return ExprError(Diag(Inits[0]->getLocStart(), + diag::err_auto_new_requires_parens) + << AllocType << TypeRange); + if (NumInits > 1) { + Expr *FirstBad = Inits[1]; + return ExprError(Diag(FirstBad->getLocStart(), diag::err_auto_new_ctor_multiple_expressions) << AllocType << TypeRange); } + Expr *Deduce = Inits[0]; TypeSourceInfo *DeducedType = 0; - if (!DeduceAutoType(AllocTypeInfo, ConstructorArgs.get()[0], DeducedType)) + if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) == + DAR_Failed) return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure) - << AllocType - << ConstructorArgs.get()[0]->getType() - << TypeRange - << ConstructorArgs.get()[0]->getSourceRange()); + << AllocType << Deduce->getType() + << TypeRange << Deduce->getSourceRange()); if (!DeducedType) return ExprError(); AllocTypeInfo = DeducedType; AllocType = AllocTypeInfo->getType(); } - + // Per C++0x [expr.new]p5, the type being constructed may be a // typedef of an array type. if (!ArraySize) { @@ -945,8 +1095,14 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange)) return ExprError(); + if (initStyle == CXXNewExpr::ListInit && isStdInitializerList(AllocType, 0)) { + Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(), + diag::warn_dangling_std_initializer_list) + << /*at end of FE*/0 << Inits[0]->getSourceRange(); + } + // In ARC, infer 'retaining' for the allocated - if (getLangOptions().ObjCAutoRefCount && + if (getLangOpts().ObjCAutoRefCount && AllocType.getObjCLifetime() == Qualifiers::OCL_None && AllocType->isObjCLifetimeType()) { AllocType = Context.getLifetimeQualifiedType(AllocType, @@ -955,53 +1111,73 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, QualType ResultType = Context.getPointerType(AllocType); - // C++ 5.3.4p6: "The expression in a direct-new-declarator shall have integral - // or enumeration type with a non-negative value." + // C++98 5.3.4p6: "The expression in a direct-new-declarator shall have + // integral or enumeration type with a non-negative value." + // C++11 [expr.new]p6: The expression [...] shall be of integral or unscoped + // enumeration type, or a class type for which a single non-explicit + // conversion function to integral or unscoped enumeration type exists. if (ArraySize && !ArraySize->isTypeDependent()) { - - QualType SizeType = ArraySize->getType(); - - ExprResult ConvertedSize - = ConvertToIntegralOrEnumerationType(StartLoc, ArraySize, - PDiag(diag::err_array_size_not_integral), - PDiag(diag::err_array_size_incomplete_type) - << ArraySize->getSourceRange(), - PDiag(diag::err_array_size_explicit_conversion), - PDiag(diag::note_array_size_conversion), - PDiag(diag::err_array_size_ambiguous_conversion), - PDiag(diag::note_array_size_conversion), - PDiag(getLangOptions().CPlusPlus0x? 0 - : diag::ext_array_size_conversion)); + ExprResult ConvertedSize = ConvertToIntegralOrEnumerationType( + StartLoc, ArraySize, + PDiag(diag::err_array_size_not_integral) << getLangOpts().CPlusPlus0x, + PDiag(diag::err_array_size_incomplete_type) + << ArraySize->getSourceRange(), + PDiag(diag::err_array_size_explicit_conversion), + PDiag(diag::note_array_size_conversion), + PDiag(diag::err_array_size_ambiguous_conversion), + PDiag(diag::note_array_size_conversion), + PDiag(getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_array_size_conversion : + diag::ext_array_size_conversion), + /*AllowScopedEnumerations*/ false); if (ConvertedSize.isInvalid()) return ExprError(); ArraySize = ConvertedSize.take(); - SizeType = ArraySize->getType(); + QualType SizeType = ArraySize->getType(); if (!SizeType->isIntegralOrUnscopedEnumerationType()) return ExprError(); - // Let's see if this is a constant < 0. If so, we reject it out of hand. - // We don't care about special rules, so we tell the machinery it's not - // evaluated - it gives us a result in more cases. + // C++98 [expr.new]p7: + // The expression in a direct-new-declarator shall have integral type + // with a non-negative value. + // + // Let's see if this is a constant < 0. If so, we reject it out of + // hand. Otherwise, if it's not a constant, we must have an unparenthesized + // array type. + // + // Note: such a construct has well-defined semantics in C++11: it throws + // std::bad_array_new_length. if (!ArraySize->isValueDependent()) { llvm::APSInt Value; - if (ArraySize->isIntegerConstantExpr(Value, Context, 0, false)) { + // We've already performed any required implicit conversion to integer or + // unscoped enumeration type. + if (ArraySize->isIntegerConstantExpr(Value, Context)) { if (Value < llvm::APSInt( llvm::APInt::getNullValue(Value.getBitWidth()), - Value.isUnsigned())) - return ExprError(Diag(ArraySize->getSourceRange().getBegin(), - diag::err_typecheck_negative_array_size) - << ArraySize->getSourceRange()); - - if (!AllocType->isDependentType()) { - unsigned ActiveSizeBits - = ConstantArrayType::getNumAddressingBits(Context, AllocType, Value); - if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) { - Diag(ArraySize->getSourceRange().getBegin(), - diag::err_array_too_large) - << Value.toString(10) + Value.isUnsigned())) { + if (getLangOpts().CPlusPlus0x) + Diag(ArraySize->getLocStart(), + diag::warn_typecheck_negative_array_new_size) << ArraySize->getSourceRange(); - return ExprError(); + else + return ExprError(Diag(ArraySize->getLocStart(), + diag::err_typecheck_negative_array_size) + << ArraySize->getSourceRange()); + } else if (!AllocType->isDependentType()) { + unsigned ActiveSizeBits = + ConstantArrayType::getNumAddressingBits(Context, AllocType, Value); + if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) { + if (getLangOpts().CPlusPlus0x) + Diag(ArraySize->getLocStart(), + diag::warn_array_new_too_large) + << Value.toString(10) + << ArraySize->getSourceRange(); + else + return ExprError(Diag(ArraySize->getLocStart(), + diag::err_array_too_large) + << Value.toString(10) + << ArraySize->getSourceRange()); } } } else if (TypeIdParens.isValid()) { @@ -1016,7 +1192,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, } // ARC: warn about ABI issues. - if (getLangOptions().ObjCAutoRefCount) { + if (getLangOpts().ObjCAutoRefCount) { QualType BaseAllocType = Context.getBaseElementType(AllocType); if (BaseAllocType.hasStrongOrWeakObjCLifetime()) Diag(StartLoc, diag::warn_err_new_delete_object_array) @@ -1033,7 +1209,8 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, unsigned NumPlaceArgs = PlacementArgs.size(); if (!AllocType->isDependentType() && - !Expr::hasAnyTypeDependentArguments(PlaceArgs, NumPlaceArgs) && + !Expr::hasAnyTypeDependentArguments( + llvm::makeArrayRef(PlaceArgs, NumPlaceArgs)) && FindAllocationFunctions(StartLoc, SourceRange(PlacementLParen, PlacementRParen), UseGlobal, AllocType, ArraySize, PlaceArgs, @@ -1063,114 +1240,123 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, NumPlaceArgs = AllPlaceArgs.size(); if (NumPlaceArgs > 0) PlaceArgs = &AllPlaceArgs[0]; - } - bool Init = ConstructorLParen.isValid(); - // --- Choosing a constructor --- - CXXConstructorDecl *Constructor = 0; - bool HadMultipleCandidates = false; - Expr **ConsArgs = (Expr**)ConstructorArgs.get(); - unsigned NumConsArgs = ConstructorArgs.size(); - ASTOwningVector<Expr*> ConvertedConstructorArgs(*this); + DiagnoseSentinelCalls(OperatorNew, PlacementLParen, + PlaceArgs, NumPlaceArgs); - // Array 'new' can't have any initializers. - if (NumConsArgs && (ResultType->isArrayType() || ArraySize)) { - SourceRange InitRange(ConsArgs[0]->getLocStart(), - ConsArgs[NumConsArgs - 1]->getLocEnd()); + // FIXME: Missing call to CheckFunctionCall or equivalent + } - Diag(StartLoc, diag::err_new_array_init_args) << InitRange; - return ExprError(); + // Warn if the type is over-aligned and is being allocated by global operator + // new. + if (NumPlaceArgs == 0 && OperatorNew && + (OperatorNew->isImplicit() || + getSourceManager().isInSystemHeader(OperatorNew->getLocStart()))) { + if (unsigned Align = Context.getPreferredTypeAlign(AllocType.getTypePtr())){ + unsigned SuitableAlign = Context.getTargetInfo().getSuitableAlign(); + if (Align > SuitableAlign) + Diag(StartLoc, diag::warn_overaligned_type) + << AllocType + << unsigned(Align / Context.getCharWidth()) + << unsigned(SuitableAlign / Context.getCharWidth()); + } + } + + QualType InitType = AllocType; + // Array 'new' can't have any initializers except empty parentheses. + // Initializer lists are also allowed, in C++11. Rely on the parser for the + // dialect distinction. + if (ResultType->isArrayType() || ArraySize) { + if (!isLegalArrayNewInitializer(initStyle, Initializer)) { + SourceRange InitRange(Inits[0]->getLocStart(), + Inits[NumInits - 1]->getLocEnd()); + Diag(StartLoc, diag::err_new_array_init_args) << InitRange; + return ExprError(); + } + if (InitListExpr *ILE = dyn_cast_or_null<InitListExpr>(Initializer)) { + // We do the initialization typechecking against the array type + // corresponding to the number of initializers + 1 (to also check + // default-initialization). + unsigned NumElements = ILE->getNumInits() + 1; + InitType = Context.getConstantArrayType(AllocType, + llvm::APInt(Context.getTypeSize(Context.getSizeType()), NumElements), + ArrayType::Normal, 0); + } } if (!AllocType->isDependentType() && - !Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) { - // C++0x [expr.new]p15: + !Expr::hasAnyTypeDependentArguments( + llvm::makeArrayRef(Inits, NumInits))) { + // C++11 [expr.new]p15: // A new-expression that creates an object of type T initializes that // object as follows: InitializationKind Kind // - If the new-initializer is omitted, the object is default- // initialized (8.5); if no initialization is performed, // the object has indeterminate value - = !Init? InitializationKind::CreateDefault(TypeRange.getBegin()) + = initStyle == CXXNewExpr::NoInit + ? InitializationKind::CreateDefault(TypeRange.getBegin()) // - Otherwise, the new-initializer is interpreted according to the // initialization rules of 8.5 for direct-initialization. - : InitializationKind::CreateDirect(TypeRange.getBegin(), - ConstructorLParen, - ConstructorRParen); + : initStyle == CXXNewExpr::ListInit + ? InitializationKind::CreateDirectList(TypeRange.getBegin()) + : InitializationKind::CreateDirect(TypeRange.getBegin(), + DirectInitRange.getBegin(), + DirectInitRange.getEnd()); InitializedEntity Entity - = InitializedEntity::InitializeNew(StartLoc, AllocType); - InitializationSequence InitSeq(*this, Entity, Kind, ConsArgs, NumConsArgs); + = InitializedEntity::InitializeNew(StartLoc, InitType); + InitializationSequence InitSeq(*this, Entity, Kind, Inits, NumInits); ExprResult FullInit = InitSeq.Perform(*this, Entity, Kind, - move(ConstructorArgs)); + MultiExprArg(Inits, NumInits)); if (FullInit.isInvalid()) return ExprError(); - // FullInit is our initializer; walk through it to determine if it's a - // constructor call, which CXXNewExpr handles directly. - if (Expr *FullInitExpr = (Expr *)FullInit.get()) { - if (CXXBindTemporaryExpr *Binder - = dyn_cast<CXXBindTemporaryExpr>(FullInitExpr)) - FullInitExpr = Binder->getSubExpr(); - if (CXXConstructExpr *Construct - = dyn_cast<CXXConstructExpr>(FullInitExpr)) { - Constructor = Construct->getConstructor(); - HadMultipleCandidates = Construct->hadMultipleCandidates(); - for (CXXConstructExpr::arg_iterator A = Construct->arg_begin(), - AEnd = Construct->arg_end(); - A != AEnd; ++A) - ConvertedConstructorArgs.push_back(*A); - } else { - // Take the converted initializer. - ConvertedConstructorArgs.push_back(FullInit.release()); - } - } else { - // No initialization required. - } + // FullInit is our initializer; strip off CXXBindTemporaryExprs, because + // we don't want the initialized object to be destructed. + if (CXXBindTemporaryExpr *Binder = + dyn_cast_or_null<CXXBindTemporaryExpr>(FullInit.get())) + FullInit = Owned(Binder->getSubExpr()); - // Take the converted arguments and use them for the new expression. - NumConsArgs = ConvertedConstructorArgs.size(); - ConsArgs = (Expr **)ConvertedConstructorArgs.take(); + Initializer = FullInit.take(); } // Mark the new and delete operators as referenced. if (OperatorNew) - MarkDeclarationReferenced(StartLoc, OperatorNew); + MarkFunctionReferenced(StartLoc, OperatorNew); if (OperatorDelete) - MarkDeclarationReferenced(StartLoc, OperatorDelete); + MarkFunctionReferenced(StartLoc, OperatorDelete); // C++0x [expr.new]p17: // If the new expression creates an array of objects of class type, // access and ambiguity control are done for the destructor. - if (ArraySize && Constructor) { - if (CXXDestructorDecl *dtor = LookupDestructor(Constructor->getParent())) { - MarkDeclarationReferenced(StartLoc, dtor); - CheckDestructorAccess(StartLoc, dtor, - PDiag(diag::err_access_dtor) - << Context.getBaseElementType(AllocType)); + QualType BaseAllocType = Context.getBaseElementType(AllocType); + if (ArraySize && !BaseAllocType->isDependentType()) { + if (const RecordType *BaseRecordType = BaseAllocType->getAs<RecordType>()) { + if (CXXDestructorDecl *dtor = LookupDestructor( + cast<CXXRecordDecl>(BaseRecordType->getDecl()))) { + MarkFunctionReferenced(StartLoc, dtor); + CheckDestructorAccess(StartLoc, dtor, + PDiag(diag::err_access_dtor) + << BaseAllocType); + DiagnoseUseOfDecl(dtor, StartLoc); + } } } PlacementArgs.release(); - ConstructorArgs.release(); return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew, - PlaceArgs, NumPlaceArgs, TypeIdParens, - ArraySize, Constructor, Init, - ConsArgs, NumConsArgs, - HadMultipleCandidates, OperatorDelete, UsualArrayDeleteWantsSize, + PlaceArgs, NumPlaceArgs, TypeIdParens, + ArraySize, initStyle, Initializer, ResultType, AllocTypeInfo, - StartLoc, - Init ? ConstructorRParen : - TypeRange.getEnd(), - ConstructorLParen, ConstructorRParen)); + StartLoc, DirectInitRange)); } -/// CheckAllocatedType - Checks that a type is suitable as the allocated type +/// \brief Checks that a type is suitable as the allocated type /// in a new-expression. -/// dimension off and stores the size expression in ArraySize. bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc, SourceRange R) { // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an @@ -1195,7 +1381,7 @@ bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc, else if (unsigned AddressSpace = AllocType.getAddressSpace()) return Diag(Loc, diag::err_address_space_qualified_new) << AllocType.getUnqualifiedType() << AddressSpace; - else if (getLangOptions().ObjCAutoRefCount) { + else if (getLangOpts().ObjCAutoRefCount) { if (const ArrayType *AT = Context.getAsArrayType(AllocType)) { QualType BaseAllocType = Context.getBaseElementType(AT); if (BaseAllocType.getObjCLifetime() == Qualifiers::OCL_None && @@ -1283,7 +1469,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // We don't need an operator delete if we're running under // -fno-exceptions. - if (!getLangOptions().Exceptions) { + if (!getLangOpts().Exceptions) { OperatorDelete = 0; return false; } @@ -1401,7 +1587,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // as a placement deallocation function, would have been // selected as a match for the allocation function, the program // is ill-formed. - if (NumPlaceArgs && getLangOptions().CPlusPlus0x && + if (NumPlaceArgs && getLangOpts().CPlusPlus0x && isNonPlacementDeallocationFunction(OperatorDelete)) { Diag(StartLoc, diag::err_placement_new_non_placement_delete) << SourceRange(PlaceArgs[0]->getLocStart(), @@ -1447,14 +1633,16 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) { AddTemplateOverloadCandidate(FnTemplate, Alloc.getPair(), - /*ExplicitTemplateArgs=*/0, Args, NumArgs, + /*ExplicitTemplateArgs=*/0, + llvm::makeArrayRef(Args, NumArgs), Candidates, /*SuppressUserConversions=*/false); continue; } FunctionDecl *Fn = cast<FunctionDecl>(D); - AddOverloadCandidate(Fn, Alloc.getPair(), Args, NumArgs, Candidates, + AddOverloadCandidate(Fn, Alloc.getPair(), + llvm::makeArrayRef(Args, NumArgs), Candidates, /*SuppressUserConversions=*/false); } @@ -1464,7 +1652,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, case OR_Success: { // Got one! FunctionDecl *FnDecl = Best->Function; - MarkDeclarationReferenced(StartLoc, FnDecl); + 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.) @@ -1484,9 +1672,13 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, Args[i] = Result.takeAs<Expr>(); } + Operator = FnDecl; - CheckAllocationAccess(StartLoc, Range, R.getNamingClass(), Best->FoundDecl, - Diagnose); + + if (CheckAllocationAccess(StartLoc, Range, R.getNamingClass(), + Best->FoundDecl, Diagnose) == AR_inaccessible) + return true; + return false; } @@ -1494,7 +1686,8 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, if (Diagnose) { Diag(StartLoc, diag::err_ovl_no_viable_function_in_call) << Name << Range; - Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + Candidates.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); } return true; @@ -1502,7 +1695,8 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, if (Diagnose) { Diag(StartLoc, diag::err_ovl_ambiguous_call) << Name << Range; - Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs); + Candidates.NoteCandidates(*this, OCD_ViableCandidates, + llvm::makeArrayRef(Args, NumArgs)); } return true; @@ -1513,7 +1707,8 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, << Name << getDeletedOrUnavailableSuffix(Best->Function) << Range; - Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + Candidates.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); } return true; } @@ -1568,7 +1763,7 @@ void Sema::DeclareGlobalNewDelete() { // lookup. // Note that the C++0x versions of operator delete are deallocation functions, // and thus are implicitly noexcept. - if (!StdBadAlloc && !getLangOptions().CPlusPlus0x) { + if (!StdBadAlloc && !getLangOpts().CPlusPlus0x) { // The "std::bad_alloc" class has not yet been declared, so build it // implicitly. StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class, @@ -1583,7 +1778,7 @@ void Sema::DeclareGlobalNewDelete() { QualType VoidPtr = Context.getPointerType(Context.VoidTy); QualType SizeT = Context.getSizeType(); - bool AssumeSaneOperatorNew = getLangOptions().AssumeSaneOperatorNew; + bool AssumeSaneOperatorNew = getLangOpts().AssumeSaneOperatorNew; DeclareGlobalAllocationFunction( Context.DeclarationNames.getCXXOperatorName(OO_New), @@ -1631,20 +1826,20 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, bool HasBadAllocExceptionSpec = (Name.getCXXOverloadedOperator() == OO_New || Name.getCXXOverloadedOperator() == OO_Array_New); - if (HasBadAllocExceptionSpec && !getLangOptions().CPlusPlus0x) { + if (HasBadAllocExceptionSpec && !getLangOpts().CPlusPlus0x) { assert(StdBadAlloc && "Must have std::bad_alloc declared"); BadAllocType = Context.getTypeDeclType(getStdBadAlloc()); } FunctionProtoType::ExtProtoInfo EPI; if (HasBadAllocExceptionSpec) { - if (!getLangOptions().CPlusPlus0x) { + if (!getLangOpts().CPlusPlus0x) { EPI.ExceptionSpecType = EST_Dynamic; EPI.NumExceptions = 1; EPI.Exceptions = &BadAllocType; } } else { - EPI.ExceptionSpecType = getLangOptions().CPlusPlus0x ? + EPI.ExceptionSpecType = getLangOpts().CPlusPlus0x ? EST_BasicNoexcept : EST_DynamicNone; } @@ -1704,13 +1899,15 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, if (Operator->isDeleted()) { if (Diagnose) { Diag(StartLoc, diag::err_deleted_function_use); - Diag(Operator->getLocation(), diag::note_unavailable_here) << true; + NoteDeletedFunction(Operator); } return true; } - CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(), - Matches[0], Diagnose); + if (CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(), + Matches[0], Diagnose) == AR_inaccessible) + return true; + return false; // We found multiple suitable operators; complain about the ambiguity. @@ -1777,6 +1974,9 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, bool UsualArrayDeleteWantsSize = false; if (!Ex.get()->isTypeDependent()) { + // Perform lvalue-to-rvalue cast, if needed. + Ex = DefaultLvalueConversion(Ex.take()); + QualType Type = Ex.get()->getType(); if (const RecordType *Record = Type->getAs<RecordType>()) { @@ -1864,8 +2064,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // (5.2.11) of the pointer expression before it is used as the operand // of the delete-expression. ] if (!Context.hasSameType(Ex.get()->getType(), Context.VoidPtrTy)) - Ex = Owned(ImplicitCastExpr::Create(Context, Context.VoidPtrTy, CK_NoOp, - Ex.take(), 0, VK_RValue)); + Ex = Owned(ImplicitCastExpr::Create(Context, Context.VoidPtrTy, + CK_BitCast, Ex.take(), 0, VK_RValue)); if (Pointee->isArrayType() && !ArrayForm) { Diag(StartLoc, diag::warn_delete_array_type) @@ -1898,9 +2098,9 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, UsualArrayDeleteWantsSize = (OperatorDelete->getNumParams() == 2); } - if (!PointeeRD->hasTrivialDestructor()) + if (!PointeeRD->hasIrrelevantDestructor()) if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) { - MarkDeclarationReferenced(StartLoc, + MarkFunctionReferenced(StartLoc, const_cast<CXXDestructorDecl*>(Dtor)); DiagnoseUseOfDecl(Dtor, StartLoc); } @@ -1929,7 +2129,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, } } - } else if (getLangOptions().ObjCAutoRefCount && + } else if (getLangOpts().ObjCAutoRefCount && PointeeElem->isObjCLifetimeType() && (PointeeElem.getObjCLifetime() == Qualifiers::OCL_Strong || PointeeElem.getObjCLifetime() == Qualifiers::OCL_Weak) && @@ -1949,7 +2149,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, return ExprError(); } - MarkDeclarationReferenced(StartLoc, OperatorDelete); + MarkFunctionReferenced(StartLoc, OperatorDelete); // Check access and ambiguity of operator delete and destructor. if (PointeeRD) { @@ -1986,11 +2186,16 @@ ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, << ConditionVar->getSourceRange()); ExprResult Condition = - Owned(DeclRefExpr::Create(Context, NestedNameSpecifierLoc(), - ConditionVar, - ConditionVar->getLocation(), - ConditionVar->getType().getNonReferenceType(), + Owned(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); if (Condition.isInvalid()) @@ -2071,8 +2276,9 @@ static ExprResult BuildCXXCastArgument(Sema &S, CastLoc, ConstructorArgs)) return ExprError(); - S.CheckConstructorAccess(CastLoc, Constructor, Constructor->getAccess(), - S.PDiag(diag::err_access_ctor)); + S.CheckConstructorAccess(CastLoc, Constructor, + InitializedEntity::InitializeTemporary(Ty), + Constructor->getAccess()); ExprResult Result = S.BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method), @@ -2089,10 +2295,17 @@ static ExprResult BuildCXXCastArgument(Sema &S, assert(!From->getType()->isPointerType() && "Arg can't have pointer type!"); // Create an implicit call expr that calls it. - ExprResult Result = S.BuildCXXMemberCallExpr(From, FoundDecl, Method, + CXXConversionDecl *Conv = cast<CXXConversionDecl>(Method); + ExprResult Result = S.BuildCXXMemberCallExpr(From, FoundDecl, Conv, HadMultipleCandidates); 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())); S.CheckMemberOperatorAccess(CastLoc, From, /*arg*/ 0, FoundDecl); @@ -2126,6 +2339,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, FunctionDecl *FD = ICS.UserDefined.ConversionFunction; CastKind CastKind; QualType BeforeToType; + assert(FD && "FIXME: aggregate initialization from init list"); if (const CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(FD)) { CastKind = CK_UserDefinedConversion; @@ -2243,7 +2457,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, if (!Fn) return ExprError(); - if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin())) + if (DiagnoseUseOfDecl(Fn, From->getLocStart())) return ExprError(); From = FixOverloadedFunctionReference(From, Found, Fn); @@ -2256,20 +2470,14 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, // Nothing to do. break; - case ICK_Lvalue_To_Rvalue: - // Should this get its own ICK? - if (From->getObjectKind() == OK_ObjCProperty) { - ExprResult FromRes = ConvertPropertyForRValue(From); - if (FromRes.isInvalid()) - return ExprError(); - From = FromRes.take(); - if (!From->isGLValue()) break; - } - + case ICK_Lvalue_To_Rvalue: { + assert(From->getObjectKind() != OK_ObjCProperty); FromType = FromType.getUnqualifiedType(); - From = ImplicitCastExpr::Create(Context, FromType, CK_LValueToRValue, - From, 0, VK_RValue); + ExprResult FromRes = DefaultLvalueConversion(From); + assert(!FromRes.isInvalid() && "Can't perform deduced conversion?!"); + From = FromRes.take(); break; + } case ICK_Array_To_Pointer: FromType = Context.getArrayDecayedType(FromType); @@ -2358,12 +2566,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, if (SCS.IncompatibleObjC && Action != AA_Casting) { // Diagnose incompatible Objective-C conversions if (Action == AA_Initializing || Action == AA_Assigning) - Diag(From->getSourceRange().getBegin(), + Diag(From->getLocStart(), diag::ext_typecheck_convert_incompatible_pointer) << ToType << From->getType() << Action << From->getSourceRange() << 0; else - Diag(From->getSourceRange().getBegin(), + Diag(From->getLocStart(), diag::ext_typecheck_convert_incompatible_pointer) << From->getType() << ToType << Action << From->getSourceRange() << 0; @@ -2372,14 +2580,14 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, ToType->isObjCObjectPointerType()) EmitRelatedResultTypeNote(From); } - else if (getLangOptions().ObjCAutoRefCount && + else if (getLangOpts().ObjCAutoRefCount && !CheckObjCARCUnavailableWeakConversion(ToType, From->getType())) { if (Action == AA_Initializing) - Diag(From->getSourceRange().getBegin(), + Diag(From->getLocStart(), diag::err_arc_weak_unavailable_assign); else - Diag(From->getSourceRange().getBegin(), + Diag(From->getLocStart(), diag::err_arc_convesion_of_weak_unavailable) << (Action == AA_Casting) << From->getType() << ToType << From->getSourceRange(); @@ -2546,7 +2754,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, CK_NoOp, VK, /*BasePath=*/0, CCK).take(); if (SCS.DeprecatedStringLiteralToCharPtr && - !getLangOptions().WritableStrings) + !getLangOpts().WritableStrings) Diag(From->getLocStart(), diag::warn_deprecated_string_literal_conversion) << ToType.getNonReferenceType(); @@ -2557,6 +2765,13 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, llvm_unreachable("Improper third standard conversion"); } + // If this conversion sequence involved a scalar -> atomic conversion, perform + // that conversion now. + if (const AtomicType *ToAtomic = ToType->getAs<AtomicType>()) + if (Context.hasSameType(ToAtomic->getValueType(), From->getType())) + From = ImpCastExprToType(From, ToType, CK_NonAtomicToAtomic, VK_RValue, 0, + CCK).take(); + return Owned(From); } @@ -2645,6 +2860,9 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, case UTT_IsAbstract: // Fall-through + // These traits require a complete type. + case UTT_IsFinal: + // These trait expressions are designed to help implement predicates in // [meta.unary.prop] despite not being named the same. They are specified // by both GCC and the Embarcadero C++ compiler, and require the complete @@ -2770,6 +2988,10 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) return RD->isAbstract(); return false; + case UTT_IsFinal: + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->hasAttr<FinalAttr>(); + return false; case UTT_IsSigned: return T->isSignedIntegerType(); case UTT_IsUnsigned: @@ -3020,6 +3242,126 @@ ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait BTT, return BuildBinaryTypeTrait(BTT, KWLoc, LhsTSInfo, RhsTSInfo, RParen); } +static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, + ArrayRef<TypeSourceInfo *> Args, + SourceLocation RParenLoc) { + switch (Kind) { + case clang::TT_IsTriviallyConstructible: { + // C++11 [meta.unary.prop]: + // is_trivially_constructible is defined as: + // + // is_constructible<T, Args...>::value is true and the variable + // definition for is_constructible, as defined below, is known to call no + // operation that is not trivial. + // + // The predicate condition for a template specialization + // is_constructible<T, Args...> shall be satisfied if and only if the + // following variable definition would be well-formed for some invented + // 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; + } + + bool SawVoid = false; + for (unsigned I = 0, N = Args.size(); I != N; ++I) { + if (Args[I]->getType()->isVoidType()) { + SawVoid = true; + continue; + } + + if (!Args[I]->getType()->isIncompleteType() && + S.RequireCompleteType(KWLoc, Args[I]->getType(), + diag::err_incomplete_type_used_in_type_trait_expr)) + return false; + } + + // If any argument was 'void', of course it won't type-check. + if (SawVoid) + return false; + + llvm::SmallVector<OpaqueValueExpr, 2> OpaqueArgExprs; + llvm::SmallVector<Expr *, 2> ArgExprs; + ArgExprs.reserve(Args.size() - 1); + for (unsigned I = 1, N = Args.size(); I != N; ++I) { + QualType T = Args[I]->getType(); + if (T->isObjectType() || T->isFunctionType()) + T = S.Context.getRValueReferenceType(T); + OpaqueArgExprs.push_back( + OpaqueValueExpr(Args[I]->getTypeLoc().getLocStart(), + T.getNonLValueExprType(S.Context), + Expr::getValueKindForType(T))); + ArgExprs.push_back(&OpaqueArgExprs.back()); + } + + // Perform the initialization in an unevaluated context within a SFINAE + // trap at translation unit scope. + EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated); + Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/true); + Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl()); + InitializedEntity To(InitializedEntity::InitializeTemporary(Args[0])); + InitializationKind InitKind(InitializationKind::CreateDirect(KWLoc, KWLoc, + RParenLoc)); + InitializationSequence Init(S, To, InitKind, + ArgExprs.begin(), ArgExprs.size()); + if (Init.Failed()) + return false; + + ExprResult Result = Init.Perform(S, To, InitKind, + MultiExprArg(ArgExprs.data(), + ArgExprs.size())); + if (Result.isInvalid() || SFINAE.hasErrorOccurred()) + return false; + + // The initialization succeeded; not make sure there are no non-trivial + // calls. + return !Result.get()->hasNonTrivialCall(S.Context); + } + } + + return false; +} + +ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc, + ArrayRef<TypeSourceInfo *> Args, + SourceLocation RParenLoc) { + bool Dependent = false; + for (unsigned I = 0, N = Args.size(); I != N; ++I) { + if (Args[I]->getType()->isDependentType()) { + Dependent = true; + break; + } + } + + bool Value = false; + if (!Dependent) + Value = evaluateTypeTrait(*this, Kind, KWLoc, Args, RParenLoc); + + return TypeTraitExpr::Create(Context, Context.BoolTy, KWLoc, Kind, + Args, RParenLoc, Value); +} + +ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, + ArrayRef<ParsedType> Args, + SourceLocation RParenLoc) { + llvm::SmallVector<TypeSourceInfo *, 4> ConvertedArgs; + ConvertedArgs.reserve(Args.size()); + + for (unsigned I = 0, N = Args.size(); I != N; ++I) { + TypeSourceInfo *TInfo; + QualType T = GetTypeFromParser(Args[I], &TInfo); + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(T, KWLoc); + + ConvertedArgs.push_back(TInfo); + } + + return BuildTypeTrait(Kind, KWLoc, ConvertedArgs, RParenLoc); +} + static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, QualType LhsT, QualType RhsT, SourceLocation KeyLoc) { @@ -3097,8 +3439,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, InitializationKind Kind(InitializationKind::CreateCopy(KeyLoc, SourceLocation())); - // Perform the initialization within a SFINAE trap at translation unit - // scope. + // Perform the initialization in an unevaluated context within a SFINAE + // trap at translation unit scope. + EnterExpressionEvaluationContext Unevaluated(Self, Sema::Unevaluated); Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true); Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl()); InitializationSequence Init(Self, To, Kind, &FromPtr, 1); @@ -3108,6 +3451,54 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, ExprResult Result = Init.Perform(Self, To, Kind, MultiExprArg(&FromPtr, 1)); return !Result.isInvalid() && !SFINAE.hasErrorOccurred(); } + + case BTT_IsTriviallyAssignable: { + // C++11 [meta.unary.prop]p3: + // is_trivially_assignable is defined as: + // is_assignable<T, U>::value is true and the assignment, as defined by + // is_assignable, is known to call no operation that is not trivial + // + // is_assignable is defined as: + // The expression declval<T>() = declval<U>() is well-formed when + // treated as an unevaluated operand (Clause 5). + // + // For both, T and U shall be complete types, (possibly cv-qualified) + // void, or arrays of unknown bound. + if (!LhsT->isVoidType() && !LhsT->isIncompleteArrayType() && + Self.RequireCompleteType(KeyLoc, LhsT, + diag::err_incomplete_type_used_in_type_trait_expr)) + return false; + if (!RhsT->isVoidType() && !RhsT->isIncompleteArrayType() && + Self.RequireCompleteType(KeyLoc, RhsT, + diag::err_incomplete_type_used_in_type_trait_expr)) + return false; + + // cv void is never assignable. + if (LhsT->isVoidType() || RhsT->isVoidType()) + return false; + + // Build expressions that emulate the effect of declval<T>() and + // declval<U>(). + if (LhsT->isObjectType() || LhsT->isFunctionType()) + LhsT = Self.Context.getRValueReferenceType(LhsT); + if (RhsT->isObjectType() || RhsT->isFunctionType()) + RhsT = Self.Context.getRValueReferenceType(RhsT); + OpaqueValueExpr Lhs(KeyLoc, LhsT.getNonLValueExprType(Self.Context), + Expr::getValueKindForType(LhsT)); + OpaqueValueExpr Rhs(KeyLoc, RhsT.getNonLValueExprType(Self.Context), + Expr::getValueKindForType(RhsT)); + + // Attempt the assignment in an unevaluated context within a SFINAE + // trap at translation unit scope. + 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); + if (Result.isInvalid() || SFINAE.hasErrorOccurred()) + return false; + + return !Result.get()->hasNonTrivialCall(Self.Context); + } } llvm_unreachable("Unknown type trait or not implemented"); } @@ -3121,7 +3512,7 @@ ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT, QualType RhsT = RhsTSInfo->getType(); if (BTT == BTT_TypeCompatible) { - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { Diag(KWLoc, diag::err_types_compatible_p_in_cplusplus) << SourceRange(KWLoc, RParen); return ExprError(); @@ -3140,6 +3531,7 @@ ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT, 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; } return Owned(new (Context) BinaryTypeTraitExpr(KWLoc, BTT, LhsTSInfo, @@ -3180,18 +3572,16 @@ static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT, case ATT_ArrayExtent: { llvm::APSInt Value; uint64_t Dim; - if (DimExpr->isIntegerConstantExpr(Value, Self.Context, 0, false)) { - if (Value < llvm::APSInt(Value.getBitWidth(), Value.isUnsigned())) { - Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) << - DimExpr->getSourceRange(); - return false; - } - Dim = Value.getLimitedValue(); - } else { - Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) << - DimExpr->getSourceRange(); - return false; + if (Self.VerifyIntegerConstantExpression(DimExpr, &Value, + Self.PDiag(diag::err_dimension_expr_not_constant_integer), + false).isInvalid()) + return 0; + if (Value.isSigned() && Value.isNegative()) { + Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) + << DimExpr->getSourceRange(); + return 0; } + Dim = Value.getLimitedValue(); if (T->isArrayType()) { unsigned D = 0; @@ -3540,7 +3930,7 @@ static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS break; RHS = move(RHSRes); if (Best->Function) - Self.MarkDeclarationReferenced(QuestionLoc, Best->Function); + Self.MarkFunctionReferenced(QuestionLoc, Best->Function); return false; } @@ -3832,7 +4222,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, if (NonStandardCompositeType) *NonStandardCompositeType = false; - assert(getLangOptions().CPlusPlus && "This function assumes C++"); + assert(getLangOpts().CPlusPlus && "This function assumes C++"); QualType T1 = E1->getType(), T2 = E2->getType(); if (!T1->isAnyPointerType() && !T1->isMemberPointerType() && @@ -4042,7 +4432,7 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { // In ARC, calls that return a retainable type can return retained, // in which case we have to insert a consuming cast. - if (getLangOptions().ObjCAutoRefCount && + if (getLangOpts().ObjCAutoRefCount && E->getType()->isObjCRetainableType()) { bool ReturnsRetained; @@ -4077,6 +4467,12 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { } else if (isa<StmtExpr>(E)) { ReturnsRetained = true; + // We hit this case with the lambda conversion-to-block optimization; + // we don't want any extra casts here. + } else if (isa<CastExpr>(E) && + isa<BlockExpr>(cast<CastExpr>(E)->getSubExpr())) { + return Owned(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. @@ -4084,11 +4480,13 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { ObjCMethodDecl *D = 0; if (ObjCMessageExpr *Send = dyn_cast<ObjCMessageExpr>(E)) { D = Send->getMethodDecl(); - } else { - CastExpr *CE = cast<CastExpr>(E); - assert(CE->getCastKind() == CK_GetObjCProperty); - const ObjCPropertyRefExpr *PRE = CE->getSubExpr()->getObjCProperty(); - D = (PRE->isImplicitProperty() ? PRE->getImplicitPropertyGetter() : 0); + } else if (ObjCNumericLiteral *NumLit = dyn_cast<ObjCNumericLiteral>(E)) { + D = NumLit->getObjCNumericLiteralMethod(); + } else if (ObjCArrayLiteral *ArrayLit = dyn_cast<ObjCArrayLiteral>(E)) { + D = ArrayLit->getArrayWithObjectsMethod(); + } else if (ObjCDictionaryLiteral *DictLit + = dyn_cast<ObjCDictionaryLiteral>(E)) { + D = DictLit->getDictWithObjectsMethod(); } ReturnsRetained = (D && D->hasAttr<NSReturnsRetainedAttr>()); @@ -4101,6 +4499,10 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { return Owned(E); } + // Don't reclaim an object of Class type. + if (!ReturnsRetained && E->getType()->isObjCARCImplicitlyUnretainedType()) + return Owned(E); + ExprNeedsCleanups = true; CastKind ck = (ReturnsRetained ? CK_ARCConsumeObject @@ -4109,51 +4511,60 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { VK_RValue)); } - if (!getLangOptions().CPlusPlus) + if (!getLangOpts().CPlusPlus) return Owned(E); - const RecordType *RT = E->getType()->getAs<RecordType>(); - if (!RT) - return Owned(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; + while (!RT) { + switch (T->getTypeClass()) { + case Type::Record: + RT = cast<RecordType>(T); + break; + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + case Type::DependentSizedArray: + T = cast<ArrayType>(T)->getElementType().getTypePtr(); + break; + default: + return Owned(E); + } + } - // That should be enough to guarantee that this type is complete. - // If it has a trivial destructor, we can avoid the extra copy. + // That should be enough to guarantee that this type is complete, if we're + // not processing a decltype expression. CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - if (RD->isInvalidDecl() || RD->hasTrivialDestructor()) + if (RD->isInvalidDecl() || RD->isDependentContext()) return Owned(E); - CXXDestructorDecl *Destructor = LookupDestructor(RD); + bool IsDecltype = ExprEvalContexts.back().IsDecltype; + CXXDestructorDecl *Destructor = IsDecltype ? 0 : LookupDestructor(RD); - CXXTemporary *Temp = CXXTemporary::Create(Context, Destructor); if (Destructor) { - MarkDeclarationReferenced(E->getExprLoc(), Destructor); + MarkFunctionReferenced(E->getExprLoc(), Destructor); CheckDestructorAccess(E->getExprLoc(), Destructor, PDiag(diag::err_access_dtor_temp) << E->getType()); + DiagnoseUseOfDecl(Destructor, E->getExprLoc()); + + // If destructor is trivial, we can avoid the extra copy. + if (Destructor->isTrivial()) + return Owned(E); - ExprTemporaries.push_back(Temp); + // We need a cleanup, but we don't need to remember the temporary. ExprNeedsCleanups = true; } - return Owned(CXXBindTemporaryExpr::Create(Context, Temp, E)); -} -Expr *Sema::MaybeCreateExprWithCleanups(Expr *SubExpr) { - assert(SubExpr && "sub expression can't be null!"); - - unsigned FirstTemporary = ExprEvalContexts.back().NumTemporaries; - assert(ExprTemporaries.size() >= FirstTemporary); - assert(ExprNeedsCleanups || ExprTemporaries.size() == FirstTemporary); - if (!ExprNeedsCleanups) - return SubExpr; + CXXTemporary *Temp = CXXTemporary::Create(Context, Destructor); + CXXBindTemporaryExpr *Bind = CXXBindTemporaryExpr::Create(Context, Temp, E); - Expr *E = ExprWithCleanups::Create(Context, SubExpr, - ExprTemporaries.begin() + FirstTemporary, - ExprTemporaries.size() - FirstTemporary); - ExprTemporaries.erase(ExprTemporaries.begin() + FirstTemporary, - ExprTemporaries.end()); - ExprNeedsCleanups = false; + if (IsDecltype) + ExprEvalContexts.back().DelayedDecltypeBinds.push_back(Bind); - return E; + return Owned(Bind); } ExprResult @@ -4164,9 +4575,32 @@ Sema::MaybeCreateExprWithCleanups(ExprResult SubExpr) { return Owned(MaybeCreateExprWithCleanups(SubExpr.take())); } +Expr *Sema::MaybeCreateExprWithCleanups(Expr *SubExpr) { + assert(SubExpr && "sub expression can't be null!"); + + CleanupVarDeclMarking(); + + unsigned FirstCleanup = ExprEvalContexts.back().NumCleanupObjects; + assert(ExprCleanupObjects.size() >= FirstCleanup); + assert(ExprNeedsCleanups || ExprCleanupObjects.size() == FirstCleanup); + if (!ExprNeedsCleanups) + return SubExpr; + + ArrayRef<ExprWithCleanups::CleanupObject> Cleanups + = llvm::makeArrayRef(ExprCleanupObjects.begin() + FirstCleanup, + ExprCleanupObjects.size() - FirstCleanup); + + Expr *E = ExprWithCleanups::Create(Context, SubExpr, Cleanups); + DiscardCleanupsInEvaluationContext(); + + return E; +} + Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) { assert(SubStmt && "sub statement can't be null!"); + CleanupVarDeclMarking(); + if (!ExprNeedsCleanups) return SubStmt; @@ -4182,6 +4616,95 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) { return MaybeCreateExprWithCleanups(E); } +/// Process the expression contained within a decltype. For such expressions, +/// certain semantic checks on temporaries are delayed until this point, and +/// are omitted for the 'topmost' call in the decltype expression. If the +/// topmost call bound a temporary, strip that temporary off the expression. +ExprResult Sema::ActOnDecltypeExpression(Expr *E) { + ExpressionEvaluationContextRecord &Rec = ExprEvalContexts.back(); + assert(Rec.IsDecltype && "not in a decltype expression"); + + // C++11 [expr.call]p11: + // If a function call is a prvalue of object type, + // -- if the function call is either + // -- the operand of a decltype-specifier, or + // -- the right operand of a comma operator that is the operand of a + // decltype-specifier, + // a temporary object is not introduced for the prvalue. + + // Recursively rebuild ParenExprs and comma expressions to strip out the + // outermost CXXBindTemporaryExpr, if any. + if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) { + ExprResult SubExpr = ActOnDecltypeExpression(PE->getSubExpr()); + if (SubExpr.isInvalid()) + return ExprError(); + if (SubExpr.get() == PE->getSubExpr()) + return Owned(E); + return ActOnParenExpr(PE->getLParen(), PE->getRParen(), SubExpr.take()); + } + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { + if (BO->getOpcode() == BO_Comma) { + ExprResult RHS = ActOnDecltypeExpression(BO->getRHS()); + 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())); + } + } + + CXXBindTemporaryExpr *TopBind = dyn_cast<CXXBindTemporaryExpr>(E); + if (TopBind) + E = TopBind->getSubExpr(); + + // Disable the special decltype handling now. + Rec.IsDecltype = false; + + // Perform the semantic checks we delayed until this point. + CallExpr *TopCall = dyn_cast<CallExpr>(E); + for (unsigned I = 0, N = Rec.DelayedDecltypeCalls.size(); I != N; ++I) { + CallExpr *Call = Rec.DelayedDecltypeCalls[I]; + if (Call == TopCall) + continue; + + if (CheckCallReturnType(Call->getCallReturnType(), + Call->getLocStart(), + Call, Call->getDirectCallee())) + return ExprError(); + } + + // Now all relevant types are complete, check the destructors are accessible + // and non-deleted, and annotate them on the temporaries. + for (unsigned I = 0, N = Rec.DelayedDecltypeBinds.size(); I != N; ++I) { + CXXBindTemporaryExpr *Bind = Rec.DelayedDecltypeBinds[I]; + if (Bind == TopBind) + continue; + + CXXTemporary *Temp = Bind->getTemporary(); + + CXXRecordDecl *RD = + Bind->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); + CXXDestructorDecl *Destructor = LookupDestructor(RD); + Temp->setDestructor(Destructor); + + MarkFunctionReferenced(E->getExprLoc(), Destructor); + CheckDestructorAccess(E->getExprLoc(), Destructor, + PDiag(diag::err_access_dtor_temp) + << E->getType()); + DiagnoseUseOfDecl(Destructor, E->getExprLoc()); + + // We need a cleanup, but we don't need to remember the temporary. + ExprNeedsCleanups = true; + } + + // Possibly strip off the top CXXBindTemporaryExpr. + return Owned(E); +} + ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, ParsedType &ObjectType, @@ -4191,6 +4714,10 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc, if (Result.isInvalid()) return ExprError(); Base = Result.get(); + Result = CheckPlaceholderExpr(Base); + if (Result.isInvalid()) return ExprError(); + Base = Result.take(); + QualType BaseType = Base->getType(); MayBePseudoDestructor = false; if (BaseType->isDependentType()) { @@ -4232,21 +4759,26 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc, } } - if (BaseType->isPointerType()) + if (BaseType->isPointerType() || BaseType->isObjCObjectPointerType()) BaseType = BaseType->getPointeeType(); } - // We could end up with various non-record types here, such as extended - // vector types or Objective-C interfaces. Just return early and let - // ActOnMemberReferenceExpr do the work. - if (!BaseType->isRecordType()) { - // C++ [basic.lookup.classref]p2: - // [...] If the type of the object expression is of pointer to scalar - // type, the unqualified-id is looked up in the context of the complete - // postfix-expression. - // - // This also indicates that we should be parsing a - // pseudo-destructor-name. + // Objective-C properties allow "." access on Objective-C pointer types, + // so adjust the base type to the object type itself. + if (BaseType->isObjCObjectPointerType()) + BaseType = BaseType->getPointeeType(); + + // C++ [basic.lookup.classref]p2: + // [...] If the type of the object expression is of pointer to scalar + // type, the unqualified-id is looked up in the context of the complete + // postfix-expression. + // + // This also indicates that we could be parsing a pseudo-destructor-name. + // Note that Objective-C class and object types can be pseudo-destructor + // expressions or normal member (ivar or property) access expressions. + if (BaseType->isObjCObjectOrInterfaceType()) { + MayBePseudoDestructor = true; + } else if (!BaseType->isRecordType()) { ObjectType = ParsedType(); MayBePseudoDestructor = true; return Owned(Base); @@ -4281,40 +4813,60 @@ ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc, /*RPLoc*/ ExpectedLParenLoc); } -ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - const CXXScopeSpec &SS, - TypeSourceInfo *ScopeTypeInfo, - SourceLocation CCLoc, - SourceLocation TildeLoc, - PseudoDestructorTypeStorage Destructed, - bool HasTrailingLParen) { - TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo(); +static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base, + tok::TokenKind& OpKind, SourceLocation OpLoc) { + if (Base->hasPlaceholderType()) { + ExprResult result = S.CheckPlaceholderExpr(Base); + if (result.isInvalid()) return true; + Base = result.take(); + } + ObjectType = Base->getType(); // C++ [expr.pseudo]p2: // The left-hand side of the dot operator shall be of scalar type. The // left-hand side of the arrow operator shall be of pointer to scalar type. // This scalar type is the object type. - QualType ObjectType = Base->getType(); + // Note that this is rather different from the normal handling for the + // arrow operator. if (OpKind == tok::arrow) { if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) { ObjectType = Ptr->getPointeeType(); } else if (!Base->isTypeDependent()) { // The user wrote "p->" when she probably meant "p."; fix it. - Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) << ObjectType << true << FixItHint::CreateReplacement(OpLoc, "."); - if (isSFINAEContext()) - return ExprError(); + if (S.isSFINAEContext()) + return true; OpKind = tok::period; } } + return false; +} + +ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + const CXXScopeSpec &SS, + TypeSourceInfo *ScopeTypeInfo, + SourceLocation CCLoc, + SourceLocation TildeLoc, + PseudoDestructorTypeStorage Destructed, + bool HasTrailingLParen) { + TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo(); + + QualType ObjectType; + if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc)) + return ExprError(); + if (!ObjectType->isDependentType() && !ObjectType->isScalarType()) { - Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar) - << ObjectType << Base->getSourceRange(); + if (getLangOpts().MicrosoftMode && ObjectType->isVoidType()) + Diag(OpLoc, diag::ext_pseudo_dtor_on_void) << Base->getSourceRange(); + else + Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar) + << ObjectType << Base->getSourceRange(); return ExprError(); } @@ -4410,25 +4962,9 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) && "Invalid second type name in pseudo-destructor"); - // C++ [expr.pseudo]p2: - // The left-hand side of the dot operator shall be of scalar type. The - // left-hand side of the arrow operator shall be of pointer to scalar type. - // This scalar type is the object type. - QualType ObjectType = Base->getType(); - if (OpKind == tok::arrow) { - if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) { - ObjectType = Ptr->getPointeeType(); - } else if (!ObjectType->isDependentType()) { - // The user wrote "p->" when she probably meant "p."; fix it. - Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) - << ObjectType << true - << FixItHint::CreateReplacement(OpLoc, "."); - if (isSFINAEContext()) - return ExprError(); - - OpKind = tok::period; - } - } + QualType ObjectType; + if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc)) + return ExprError(); // Compute the object type that we should use for name lookup purposes. Only // record types and dependent types matter. @@ -4476,6 +5012,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, TemplateId->getTemplateArgs(), TemplateId->NumArgs); TypeResult T = ActOnTemplateIdType(TemplateId->SS, + TemplateId->TemplateKWLoc, TemplateId->Template, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, @@ -4525,6 +5062,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, TemplateId->getTemplateArgs(), TemplateId->NumArgs); TypeResult T = ActOnTemplateIdType(TemplateId->SS, + TemplateId->TemplateKWLoc, TemplateId->Template, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, @@ -4548,9 +5086,60 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, Destructed, HasTrailingLParen); } +ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + SourceLocation TildeLoc, + const DeclSpec& DS, + bool HasTrailingLParen) { + QualType ObjectType; + if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc)) + return ExprError(); + + QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); + + TypeLocBuilder TLB; + DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T); + DecltypeTL.setNameLoc(DS.getTypeSpecTypeLoc()); + TypeSourceInfo *DestructedTypeInfo = TLB.getTypeSourceInfo(Context, T); + PseudoDestructorTypeStorage Destructed(DestructedTypeInfo); + + return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, CXXScopeSpec(), + 0, SourceLocation(), TildeLoc, + Destructed, HasTrailingLParen); +} + ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, - CXXMethodDecl *Method, + CXXConversionDecl *Method, bool HadMultipleCandidates) { + if (Method->getParent()->isLambda() && + Method->getConversionType()->isBlockPointerType()) { + // This is a lambda coversion to block pointer; check if the argument + // is a LambdaExpr. + Expr *SubE = E; + CastExpr *CE = dyn_cast<CastExpr>(SubE); + if (CE && CE->getCastKind() == CK_NoOp) + SubE = CE->getSubExpr(); + SubE = SubE->IgnoreParens(); + if (CXXBindTemporaryExpr *BE = dyn_cast<CXXBindTemporaryExpr>(SubE)) + SubE = BE->getSubExpr(); + if (isa<LambdaExpr>(SubE)) { + // For the conversion to block pointer on a lambda expression, we + // construct a special BlockLiteral instead; this doesn't really make + // a difference in ARC, but outside of ARC the resulting block literal + // follows the normal lifetime rules for block literals instead of being + // autoreleased. + DiagnosticErrorTrap Trap(Diags); + ExprResult Exp = BuildBlockForLambdaConversion(E->getExprLoc(), + E->getExprLoc(), + Method, E); + if (Exp.isInvalid()) + Diag(E->getExprLoc(), diag::note_lambda_to_block_conv); + return Exp; + } + } + + ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/0, FoundDecl, Method); if (Exp.isInvalid()) @@ -4558,7 +5147,7 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, MemberExpr *ME = new (Context) MemberExpr(Exp.take(), /*IsArrow=*/false, Method, - SourceLocation(), Method->getType(), + SourceLocation(), Context.BoundMemberTy, VK_RValue, OK_Ordinary); if (HadMultipleCandidates) ME->setHadMultipleCandidates(true); @@ -4567,7 +5156,7 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, ExprValueKind VK = Expr::getValueKindForType(ResultType); ResultType = ResultType.getNonLValueExprType(Context); - MarkDeclarationReferenced(Exp.get()->getLocStart(), Method); + MarkFunctionReferenced(Exp.get()->getLocStart(), Method); CXXMemberCallExpr *CE = new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, VK, Exp.get()->getLocEnd()); @@ -4589,6 +5178,12 @@ ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation, /// Perform the conversions required for an expression used in a /// context that ignores the result. ExprResult Sema::IgnoredValueConversions(Expr *E) { + if (E->hasPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(E); + if (result.isInvalid()) return Owned(E); + E = result.take(); + } + // C99 6.3.2.1: // [Except in specific positions,] an lvalue that does not have // array type is converted to the value stored in the @@ -4598,22 +5193,14 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) { // are r-values, but we still want to do function-to-pointer decay // on them. This is both technically correct and convenient for // some clients. - if (!getLangOptions().CPlusPlus && E->getType()->isFunctionType()) + if (!getLangOpts().CPlusPlus && E->getType()->isFunctionType()) return DefaultFunctionArrayConversion(E); return Owned(E); } - // We always want to do this on ObjC property references. - if (E->getObjectKind() == OK_ObjCProperty) { - ExprResult Res = ConvertPropertyForRValue(E); - if (Res.isInvalid()) return Owned(E); - E = Res.take(); - if (E->isRValue()) return Owned(E); - } - // Otherwise, this rule does not apply in C++, at least not for the moment. - if (getLangOptions().CPlusPlus) return Owned(E); + if (getLangOpts().CPlusPlus) return Owned(E); // GCC seems to also exclude expressions of incomplete enum type. if (const EnumType *T = E->getType()->getAs<EnumType>()) { @@ -4644,6 +5231,15 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE) { if (DiagnoseUnexpandedParameterPack(FullExpr.get())) return ExprError(); + // Top-level message sends default to 'id' when we're in a debugger. + if (getLangOpts().DebuggerCastResultToId && + FullExpr.get()->getType() == Context.UnknownAnyTy && + isa<ObjCMessageExpr>(FullExpr.get())) { + FullExpr = forceUnknownAnyToType(FullExpr.take(), Context.getObjCIdType()); + if (FullExpr.isInvalid()) + return ExprError(); + } + FullExpr = CheckPlaceholderExpr(FullExpr.take()); if (FullExpr.isInvalid()) return ExprError(); @@ -4662,17 +5258,58 @@ StmtResult Sema::ActOnFinishFullStmt(Stmt *FullStmt) { return MaybeCreateStmtWithCleanups(FullStmt); } -bool Sema::CheckMicrosoftIfExistsSymbol(CXXScopeSpec &SS, - UnqualifiedId &Name) { - DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name); +Sema::IfExistsResult +Sema::CheckMicrosoftIfExistsSymbol(Scope *S, + CXXScopeSpec &SS, + const DeclarationNameInfo &TargetNameInfo) { DeclarationName TargetName = TargetNameInfo.getName(); if (!TargetName) - return false; - + return IER_DoesNotExist; + + // If the name itself is dependent, then the result is dependent. + if (TargetName.isDependentName()) + return IER_Dependent; + // Do the redeclaration lookup in the current scope. LookupResult R(*this, TargetNameInfo, Sema::LookupAnyName, Sema::NotForRedeclaration); + LookupParsedName(R, S, &SS); R.suppressDiagnostics(); - LookupParsedName(R, getCurScope(), &SS); - return !R.empty(); + + switch (R.getResultKind()) { + case LookupResult::Found: + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: + case LookupResult::Ambiguous: + return IER_Exists; + + case LookupResult::NotFound: + return IER_DoesNotExist; + + case LookupResult::NotFoundInCurrentInstantiation: + return IER_Dependent; + } + + llvm_unreachable("Invalid LookupResult Kind!"); +} + +Sema::IfExistsResult +Sema::CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc, + bool IsIfExists, CXXScopeSpec &SS, + UnqualifiedId &Name) { + DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name); + + // Check for unexpanded parameter packs. + SmallVector<UnexpandedParameterPack, 4> Unexpanded; + collectUnexpandedParameterPacks(SS, Unexpanded); + collectUnexpandedParameterPacks(TargetNameInfo, Unexpanded); + if (!Unexpanded.empty()) { + DiagnoseUnexpandedParameterPacks(KeywordLoc, + IsIfExists? UPPC_IfExists + : UPPC_IfNotExists, + Unexpanded); + return IER_Error; + } + + return CheckMicrosoftIfExistsSymbol(S, SS, TargetNameInfo); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp index 26867c2..26b88a2 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp @@ -56,7 +56,7 @@ enum IMAKind { /// The reference may be an implicit instance member access. IMA_Mixed, - /// The reference may be to an instance member, but it is invalid if + /// The reference may be to an instance member, but it might be invalid if /// so, because the context is not an instance method. IMA_Mixed_StaticContext, @@ -74,6 +74,11 @@ enum IMAKind { /// context is not an instance method. IMA_Unresolved_StaticContext, + // The reference refers to a field which is not a member of the containing + // class, which is allowed because we're in C++11 mode and the context is + // unevaluated. + IMA_Field_Uneval_Context, + /// All possible referrents are instance members and the current /// context is not an instance method. IMA_Error_StaticContext, @@ -86,7 +91,7 @@ enum IMAKind { /// The given lookup names class member(s) and is not being used for /// an address-of-member expression. Classify the type of access /// according to whether it's possible that this reference names an -/// instance member. This is best-effort; it is okay to +/// instance member. This is best-effort in dependent contexts; it is okay to /// conservatively answer "yes", in which case some errors will simply /// not be caught until template-instantiation. static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, @@ -112,14 +117,14 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, // Collect all the declaring classes of instance members we find. bool hasNonInstance = false; - bool hasField = false; + bool isField = false; llvm::SmallPtrSet<CXXRecordDecl*, 4> Classes; for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { NamedDecl *D = *I; if (D->isCXXInstanceMember()) { if (dyn_cast<FieldDecl>(D)) - hasField = true; + isField = true; CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext()); Classes.insert(R->getCanonicalDecl()); @@ -133,27 +138,28 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, if (Classes.empty()) return IMA_Static; + bool IsCXX11UnevaluatedField = false; + if (SemaRef.getLangOpts().CPlusPlus0x && isField) { + // C++11 [expr.prim.general]p12: + // An id-expression that denotes a non-static data member or non-static + // member function of a class can only be used: + // (...) + // - if that id-expression denotes a non-static data member and it + // appears in an unevaluated operand. + const Sema::ExpressionEvaluationContextRecord& record + = SemaRef.ExprEvalContexts.back(); + if (record.Context == Sema::Unevaluated) + IsCXX11UnevaluatedField = true; + } + // If the current context is not an instance method, it can't be // an implicit member reference. if (isStaticContext) { if (hasNonInstance) - return IMA_Mixed_StaticContext; - - if (SemaRef.getLangOptions().CPlusPlus0x && hasField) { - // C++0x [expr.prim.general]p10: - // An id-expression that denotes a non-static data member or non-static - // member function of a class can only be used: - // (...) - // - if that id-expression denotes a non-static data member and it - // appears in an unevaluated operand. - const Sema::ExpressionEvaluationContextRecord& record - = SemaRef.ExprEvalContexts.back(); - bool isUnevaluatedExpression = (record.Context == Sema::Unevaluated); - if (isUnevaluatedExpression) - return IMA_Mixed_StaticContext; - } - - return IMA_Error_StaticContext; + return IMA_Mixed_StaticContext; + + return IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context + : IMA_Error_StaticContext; } CXXRecordDecl *contextClass; @@ -169,76 +175,93 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, // ...if C is not X or a base class of X, the class member access expression // is ill-formed. if (R.getNamingClass() && - contextClass != R.getNamingClass()->getCanonicalDecl() && + contextClass->getCanonicalDecl() != + R.getNamingClass()->getCanonicalDecl() && contextClass->isProvablyNotDerivedFrom(R.getNamingClass())) - return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated); + return hasNonInstance ? IMA_Mixed_Unrelated : + IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context : + IMA_Error_Unrelated; // If we can prove that the current context is unrelated to all the // declaring classes, it can't be an implicit member reference (in // which case it's an error if any of those members are selected). if (IsProvablyNotDerivedFrom(SemaRef, contextClass, Classes)) - return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated); + return hasNonInstance ? IMA_Mixed_Unrelated : + IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context : + IMA_Error_Unrelated; return (hasNonInstance ? IMA_Mixed : IMA_Instance); } /// Diagnose a reference to a field with no object available. -static void DiagnoseInstanceReference(Sema &SemaRef, +static void diagnoseInstanceReference(Sema &SemaRef, const CXXScopeSpec &SS, - NamedDecl *rep, + NamedDecl *Rep, const DeclarationNameInfo &nameInfo) { SourceLocation Loc = nameInfo.getLoc(); SourceRange Range(Loc); if (SS.isSet()) Range.setBegin(SS.getRange().getBegin()); - - if (isa<FieldDecl>(rep) || isa<IndirectFieldDecl>(rep)) { - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(SemaRef.CurContext)) { - if (MD->isStatic()) { - // "invalid use of member 'x' in static member function" - SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method) + + DeclContext *FunctionLevelDC = SemaRef.getFunctionLevelDeclContext(); + CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FunctionLevelDC); + CXXRecordDecl *ContextClass = Method ? Method->getParent() : 0; + CXXRecordDecl *RepClass = dyn_cast<CXXRecordDecl>(Rep->getDeclContext()); + + bool InStaticMethod = Method && Method->isStatic(); + bool IsField = isa<FieldDecl>(Rep) || isa<IndirectFieldDecl>(Rep); + + if (IsField && InStaticMethod) + // "invalid use of member 'x' in static member function" + SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method) << Range << nameInfo.getName(); - return; - } - } - + else if (ContextClass && RepClass && SS.isEmpty() && !InStaticMethod && + !RepClass->Equals(ContextClass) && RepClass->Encloses(ContextClass)) + // Unqualified lookup in a non-static member function found a member of an + // enclosing class. + SemaRef.Diag(Loc, diag::err_nested_non_static_member_use) + << IsField << RepClass << nameInfo.getName() << ContextClass << Range; + else if (IsField) SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use) - << nameInfo.getName() << Range; - return; - } - - SemaRef.Diag(Loc, diag::err_member_call_without_object) << Range; + << nameInfo.getName() << Range; + else + SemaRef.Diag(Loc, diag::err_member_call_without_object) + << Range; } /// Builds an expression which might be an implicit member expression. ExprResult Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs) { switch (ClassifyImplicitMemberAccess(*this, CurScope, R)) { case IMA_Instance: - return BuildImplicitMemberExpr(SS, R, TemplateArgs, true); + return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true); case IMA_Mixed: case IMA_Mixed_Unrelated: case IMA_Unresolved: - return BuildImplicitMemberExpr(SS, R, TemplateArgs, false); + return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false); + case IMA_Field_Uneval_Context: + Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use) + << R.getLookupNameInfo().getName(); + // Fall through. case IMA_Static: case IMA_Mixed_StaticContext: case IMA_Unresolved_StaticContext: - if (TemplateArgs) - return BuildTemplateIdExpr(SS, R, false, *TemplateArgs); + if (TemplateArgs || TemplateKWLoc.isValid()) + return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs); return BuildDeclarationNameExpr(SS, R, false); case IMA_Error_StaticContext: case IMA_Error_Unrelated: - DiagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(), + diagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(), R.getLookupNameInfo()); return ExprError(); } llvm_unreachable("unexpected instance member access kind"); - return ExprError(); } /// Check an ext-vector component access expression. @@ -403,6 +426,7 @@ ExprResult Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs) { @@ -417,7 +441,7 @@ Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType, // allows this, while still reporting an error if T is a struct pointer. if (!IsArrow) { const PointerType *PT = BaseType->getAs<PointerType>(); - if (PT && (!getLangOptions().ObjC1 || + if (PT && (!getLangOpts().ObjC1 || PT->getPointeeType()->isRecordType())) { assert(BaseExpr && "cannot happen with implicit member accesses"); Diag(NameInfo.getLoc(), diag::err_typecheck_member_reference_struct_union) @@ -435,6 +459,7 @@ Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType, return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr, BaseType, IsArrow, OpLoc, SS.getWithLocInContext(Context), + TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs)); } @@ -451,7 +476,7 @@ static void DiagnoseQualifiedMemberReference(Sema &SemaRef, // If this is an implicit member access, use a different set of // diagnostics. if (!BaseExpr) - return DiagnoseInstanceReference(SemaRef, SS, rep, nameInfo); + return diagnoseInstanceReference(SemaRef, SS, rep, nameInfo); SemaRef.Diag(nameInfo.getLoc(), diag::err_qualified_member_of_unrelated) << SS.getRange() << rep << BaseType; @@ -509,6 +534,20 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, return true; } +namespace { + +// Callback to only accept typo corrections that are either a ValueDecl or a +// FunctionTemplateDecl. +class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback { + public: + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + NamedDecl *ND = candidate.getCorrectionDecl(); + return ND && (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)); + } +}; + +} + static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, SourceRange BaseRange, const RecordType *RTy, @@ -559,17 +598,16 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, // We didn't find anything with the given name, so try to correct // for typos. DeclarationName Name = R.getLookupName(); + RecordMemberExprValidatorCCC Validator; TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), NULL, - &SS, DC, false, - Sema::CTC_MemberLookup); - NamedDecl *ND = Corrected.getCorrectionDecl(); + &SS, Validator, DC); R.clear(); - if (ND && (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND))) { + if (NamedDecl *ND = Corrected.getCorrectionDecl()) { std::string CorrectedStr( - Corrected.getAsString(SemaRef.getLangOptions())); + Corrected.getAsString(SemaRef.getLangOpts())); std::string CorrectedQuotedStr( - Corrected.getQuoted(SemaRef.getLangOptions())); + Corrected.getQuoted(SemaRef.getLangOpts())); R.setLookupName(Corrected.getCorrection()); R.addDecl(ND); SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest) @@ -586,6 +624,7 @@ ExprResult Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow, CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs) { @@ -593,7 +632,7 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, (SS.isSet() && isDependentScopeSpecifier(SS))) return ActOnDependentMemberExpr(Base, BaseType, IsArrow, OpLoc, - SS, FirstQualifierInScope, + SS, TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs); LookupResult R(*this, NameInfo, LookupMemberName); @@ -631,8 +670,8 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, } return BuildMemberReferenceExpr(Base, BaseType, - OpLoc, IsArrow, SS, FirstQualifierInScope, - R, TemplateArgs); + OpLoc, IsArrow, SS, TemplateKWLoc, + FirstQualifierInScope, R, TemplateArgs); } static ExprResult @@ -697,7 +736,7 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, // We've found a member of an anonymous struct/union that is // inside a non-anonymous struct/union, so in a well-formed // program our base object expression is "this". - QualType ThisTy = getAndCaptureCurrentThisType(); + QualType ThisTy = getCurrentThisType(); if (ThisTy.isNull()) { Diag(loc, diag::err_invalid_member_use_in_static_method) << indirectField->getDeclName(); @@ -705,6 +744,7 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, } // Our base object expression is "this". + CheckCXXThisCapture(loc); baseObjectExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/ true); baseObjectIsPointer = true; @@ -754,22 +794,30 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, } /// \brief Build a MemberExpr AST node. -static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, - const CXXScopeSpec &SS, ValueDecl *Member, +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) { - return MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C), - Member, FoundDecl, MemberNameInfo, - TemplateArgs, Ty, VK, OK); + assert((!isArrow || Base->isRValue()) && "-> base must be a pointer rvalue"); + MemberExpr *E = + MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C), + TemplateKWLoc, Member, FoundDecl, MemberNameInfo, + TemplateArgs, Ty, VK, OK); + SemaRef.MarkMemberReferenced(E); + return E; } ExprResult Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, SourceLocation OpLoc, bool IsArrow, const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierInScope, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs, @@ -777,7 +825,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, QualType BaseType = BaseExprType; if (IsArrow) { assert(BaseType->isPointerType()); - BaseType = BaseType->getAs<PointerType>()->getPointeeType(); + BaseType = BaseType->castAs<PointerType>()->getPointeeType(); } R.setBaseObjectType(BaseType); @@ -813,7 +861,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, !SuppressQualifierCheck && CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R)) return ExprError(); - + // Construct an unresolved result if we in fact got an unresolved // result. if (R.isOverloadedResult() || R.isUnresolvableResult()) { @@ -826,7 +874,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, BaseExpr, BaseExprType, IsArrow, OpLoc, SS.getWithLocInContext(Context), - MemberNameInfo, + TemplateKWLoc, MemberNameInfo, TemplateArgs, R.begin(), R.end()); return Owned(MemExpr); @@ -853,6 +901,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, SourceLocation Loc = R.getNameLoc(); if (SS.getRange().isValid()) Loc = SS.getRange().getBegin(); + CheckCXXThisCapture(Loc); BaseExpr = new (Context) CXXThisExpr(Loc, BaseExprType,/*isImplicit=*/true); } @@ -870,15 +919,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, return ExprError(); } - // Perform a property load on the base regardless of whether we - // actually need it for the declaration. - if (BaseExpr->getObjectKind() == OK_ObjCProperty) { - ExprResult Result = ConvertPropertyForRValue(BaseExpr); - if (Result.isInvalid()) - return ExprError(); - BaseExpr = Result.take(); - } - if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow, SS, FD, FoundDecl, MemberNameInfo); @@ -890,9 +930,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, BaseExpr, OpLoc); if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { - MarkDeclarationReferenced(MemberLoc, Var); - return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, - Var, FoundDecl, MemberNameInfo, + return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, + TemplateKWLoc, Var, FoundDecl, MemberNameInfo, Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary)); } @@ -908,17 +947,16 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, type = MemberFn->getType(); } - MarkDeclarationReferenced(MemberLoc, MemberDecl); - return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, - MemberFn, FoundDecl, MemberNameInfo, - type, valueKind, OK_Ordinary)); + return Owned(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)) { - MarkDeclarationReferenced(MemberLoc, MemberDecl); - return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, - Enum, FoundDecl, MemberNameInfo, + return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, + TemplateKWLoc, Enum, FoundDecl, MemberNameInfo, Enum->getType(), VK_RValue, OK_Ordinary)); } @@ -979,6 +1017,15 @@ static bool isPointerToRecordType(QualType T) { return false; } +/// Perform conversions on the LHS of a member access expression. +ExprResult +Sema::PerformMemberExprBaseConversion(Expr *Base, bool IsArrow) { + if (IsArrow && !Base->getType()->isFunctionType()) + return DefaultFunctionArrayLvalueConversion(Base); + + return CheckPlaceholderExpr(Base); +} + /// Look up the given member of the given non-type-dependent /// expression. This can return in one of two ways: /// * If it returns a sentinel null-but-valid result, the caller will @@ -997,16 +1044,10 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, assert(BaseExpr.get() && "no base expression"); // Perform default conversions. - BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); + BaseExpr = PerformMemberExprBaseConversion(BaseExpr.take(), IsArrow); if (BaseExpr.isInvalid()) return ExprError(); - if (IsArrow) { - BaseExpr = DefaultLvalueConversion(BaseExpr.take()); - if (BaseExpr.isInvalid()) - return ExprError(); - } - QualType BaseType = BaseExpr.get()->getType(); assert(!BaseType->isDependentType()); @@ -1034,7 +1075,7 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() << FixItHint::CreateReplacement(OpLoc, "."); IsArrow = false; - } else if (BaseType == Context.BoundMemberTy) { + } else if (BaseType->isFunctionType()) { goto fail; } else { Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) @@ -1071,15 +1112,17 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, // - an interface ObjCInterfaceDecl *IDecl = OTy->getInterface(); if (!IDecl) { - if (getLangOptions().ObjCAutoRefCount && + if (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")) + // apparently.ghjg + if (OTy->isObjCId() && Member->isStr("isa")) { + Diag(MemberLoc, diag::warn_objc_isa_use); return Owned(new (Context) ObjCIsaExpr(BaseExpr.take(), IsArrow, MemberLoc, Context.getObjCClassType())); + } if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, @@ -1087,17 +1130,22 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, goto fail; } - ObjCInterfaceDecl *ClassDeclared; + if (RequireCompleteType(OpLoc, BaseType, + PDiag(diag::err_typecheck_incomplete_tag) + << BaseExpr.get()->getSourceRange())) + return ExprError(); + + ObjCInterfaceDecl *ClassDeclared = 0; ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared); if (!IV) { // Attempt to correct for typos in ivar names. - LookupResult Res(*this, R.getLookupName(), R.getNameLoc(), - LookupMemberName); - TypoCorrection Corrected = CorrectTypo( - R.getLookupNameInfo(), LookupMemberName, NULL, NULL, IDecl, false, - IsArrow ? CTC_ObjCIvarLookup : CTC_ObjCPropertyLookup); - if ((IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>())) { + DeclFilterCCC<ObjCIvarDecl> Validator; + Validator.IsObjCIvarLookup = IsArrow; + if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(), + LookupMemberName, NULL, NULL, + Validator, IDecl)) { + IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>(); Diag(R.getNameLoc(), diag::err_typecheck_member_reference_ivar_suggest) << IDecl->getDeclName() << MemberName << IV->getDeclName() @@ -1105,6 +1153,13 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, IV->getNameAsString()); Diag(IV->getLocation(), diag::note_previous_decl) << IV->getDeclName(); + + // Figure out the class that declares the ivar. + assert(!ClassDeclared); + Decl *D = cast<Decl>(IV->getDeclContext()); + if (ObjCCategoryDecl *CAT = dyn_cast<ObjCCategoryDecl>(D)) + D = CAT->getClassInterface(); + ClassDeclared = cast<ObjCInterfaceDecl>(D); } else { if (IsArrow && IDecl->FindPropertyDeclaration(Member)) { Diag(MemberLoc, @@ -1113,8 +1168,6 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, << FixItHint::CreateReplacement(OpLoc, "."); return ExprError(); } - Res.clear(); - Res.setLookupName(Member); Diag(MemberLoc, diag::err_typecheck_member_reference_ivar) << IDecl->getDeclName() << MemberName @@ -1122,6 +1175,8 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, return ExprError(); } } + + assert(ClassDeclared); // If the decl being referenced had an error, return an error for this // sub-expr without emitting another error, in order to avoid cascading @@ -1151,18 +1206,19 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, dyn_cast<ObjCCategoryImplDecl>(ObjCImpDecl)) ClassOfMethodDecl = CatImplClass->getClassInterface(); } - - if (IV->getAccessControl() == ObjCIvarDecl::Private) { - if (ClassDeclared != IDecl || - ClassOfMethodDecl != ClassDeclared) - Diag(MemberLoc, diag::error_private_ivar_access) + if (!getLangOpts().DebuggerSupport) { + if (IV->getAccessControl() == ObjCIvarDecl::Private) { + if (!declaresSameEntity(ClassDeclared, IDecl) || + !declaresSameEntity(ClassOfMethodDecl, ClassDeclared)) + Diag(MemberLoc, diag::error_private_ivar_access) + << IV->getDeclName(); + } else if (!IDecl->isSuperClassOf(ClassOfMethodDecl)) + // @protected + Diag(MemberLoc, diag::error_protected_ivar_access) << IV->getDeclName(); - } else if (!IDecl->isSuperClassOf(ClassOfMethodDecl)) - // @protected - Diag(MemberLoc, diag::error_protected_ivar_access) - << IV->getDeclName(); + } } - if (getLangOptions().ObjCAutoRefCount) { + if (getLangOpts().ObjCAutoRefCount) { Expr *BaseExp = BaseExpr.get()->IgnoreParenImpCasts(); if (UnaryOperator *UO = dyn_cast<UnaryOperator>(BaseExp)) if (UO->getOpcode() == UO_Deref) @@ -1209,11 +1265,8 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); - QualType T = PD->getType(); - if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) - T = getMessageSendResultType(BaseType, Getter, false, false); - - return Owned(new (Context) ObjCPropertyRefExpr(PD, T, + return Owned(new (Context) ObjCPropertyRefExpr(PD, + Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, MemberLoc, @@ -1231,16 +1284,10 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, if (Decl *SDecl = FindGetterSetterNameDecl(OPT, /*Property id*/0, SetterSel, Context)) SMD = dyn_cast<ObjCMethodDecl>(SDecl); - QualType PType = getMessageSendResultType(BaseType, OMD, false, - false); - ExprValueKind VK = VK_LValue; - if (!getLangOptions().CPlusPlus && PType.isCForbiddenLValueType()) - VK = VK_RValue; - ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty); - - return Owned(new (Context) ObjCPropertyRefExpr(OMD, SMD, PType, - VK, OK, + return Owned(new (Context) ObjCPropertyRefExpr(OMD, SMD, + Context.PseudoObjectTy, + VK_LValue, OK_ObjCProperty, MemberLoc, BaseExpr.take())); } } @@ -1295,23 +1342,9 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, return ExprError(); if (Getter || Setter) { - QualType PType; - - ExprValueKind VK = VK_LValue; - if (Getter) { - PType = getMessageSendResultType(QualType(OT, 0), Getter, true, - false); - if (!getLangOptions().CPlusPlus && PType.isCForbiddenLValueType()) - VK = VK_RValue; - } else { - // Get the expression type from Setter's incoming parameter. - PType = (*(Setter->param_end() -1))->getType(); - } - ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty); - - // FIXME: we must check that the setter has property type. return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, - PType, VK, OK, + Context.PseudoObjectTy, + VK_LValue, OK_ObjCProperty, MemberLoc, BaseExpr.take())); } @@ -1384,7 +1417,7 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, if (tryToRecoverWithCall(BaseExpr, PDiag(diag::err_member_reference_needs_call), /*complain*/ false, - IsArrow ? &isRecordType : &isPointerToRecordType)) { + IsArrow ? &isPointerToRecordType : &isRecordType)) { if (BaseExpr.isInvalid()) return ExprError(); BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); @@ -1415,6 +1448,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, UnqualifiedId &Id, Decl *ObjCImpDecl, bool HasTrailingLParen) { @@ -1422,7 +1456,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, return ExprError(); // Warn about the explicit constructor calls Microsoft extension. - if (getLangOptions().MicrosoftExt && + if (getLangOpts().MicrosoftExt && Id.getKind() == UnqualifiedId::IK_ConstructorName) Diag(Id.getSourceRange().getBegin(), diag::ext_ms_explicit_constructor_call); @@ -1451,7 +1485,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, isDependentScopeSpecifier(SS)) { Result = ActOnDependentMemberExpr(Base, Base->getType(), IsArrow, OpLoc, - SS, FirstQualifierInScope, + SS, TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs); } else { LookupResult R(*this, NameInfo, LookupMemberName); @@ -1480,8 +1514,8 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, } Result = BuildMemberReferenceExpr(Base, Base->getType(), - OpLoc, IsArrow, SS, FirstQualifierInScope, - R, TemplateArgs); + OpLoc, IsArrow, SS, TemplateKWLoc, + FirstQualifierInScope, R, TemplateArgs); } return move(Result); @@ -1536,13 +1570,13 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, MemberType = S.Context.getQualifiedType(MemberType, Combined); } - S.MarkDeclarationReferenced(MemberNameInfo.getLoc(), Field); ExprResult Base = S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(), FoundDecl, Field); if (Base.isInvalid()) return ExprError(); - return S.Owned(BuildMemberExpr(S.Context, Base.take(), IsArrow, SS, + return S.Owned(BuildMemberExpr(S, S.Context, Base.take(), IsArrow, SS, + /*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl, MemberNameInfo, MemberType, VK, OK)); } @@ -1553,6 +1587,7 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, /// is from an appropriate type. ExprResult Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs, bool IsKnownInstance) { @@ -1569,7 +1604,7 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, // If this is known to be an instance access, go ahead and build an // implicit 'this' expression now. // 'this' expression now. - QualType ThisTy = getAndCaptureCurrentThisType(); + QualType ThisTy = getCurrentThisType(); assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'"); Expr *baseExpr = 0; // null signifies implicit access @@ -1577,13 +1612,14 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation Loc = R.getNameLoc(); if (SS.getRange().isValid()) Loc = SS.getRange().getBegin(); + CheckCXXThisCapture(Loc); baseExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/true); } return BuildMemberReferenceExpr(baseExpr, ThisTy, /*OpLoc*/ SourceLocation(), /*IsArrow*/ true, - SS, + SS, TemplateKWLoc, /*FirstQualifierInScope*/ 0, R, TemplateArgs); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp index 20098b2..b62d56e 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp @@ -17,6 +17,8 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Initialization.h" #include "clang/Analysis/DomainSpecific/CocoaConventions.h" +#include "clang/Edit/Rewriters.h" +#include "clang/Edit/Commit.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprObjC.h" @@ -43,7 +45,7 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, // If we have a multi-part string, merge it all together. if (NumStrings != 1) { // Concatenate objc strings. - llvm::SmallString<128> StrBuf; + SmallString<128> StrBuf; SmallVector<SourceLocation, 8> StrLocs; for (unsigned i = 0; i != NumStrings; ++i) { @@ -70,7 +72,11 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, Context.getPointerType(Context.CharTy), &StrLocs[0], StrLocs.size()); } + + return BuildObjCStringLiteral(AtLocs[0], S); +} +ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){ // Verify that this composite string is acceptable for ObjC strings. if (CheckObjCString(S)) return true; @@ -82,16 +88,16 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, QualType Ty = Context.getObjCConstantStringInterface(); if (!Ty.isNull()) { Ty = Context.getObjCObjectPointerType(Ty); - } else if (getLangOptions().NoConstantCFStrings) { + } else if (getLangOpts().NoConstantCFStrings) { IdentifierInfo *NSIdent=0; - std::string StringClass(getLangOptions().ObjCConstantStringClass); + std::string StringClass(getLangOpts().ObjCConstantStringClass); if (StringClass.empty()) NSIdent = &Context.Idents.get("NSConstantString"); else NSIdent = &Context.Idents.get(StringClass); - NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLocs[0], + NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc, LookupOrdinaryName); if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) { Context.setObjCConstantStringInterface(StrIF); @@ -106,20 +112,638 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, } } else { IdentifierInfo *NSIdent = &Context.Idents.get("NSString"); - NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLocs[0], + NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc, LookupOrdinaryName); if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) { Context.setObjCConstantStringInterface(StrIF); Ty = Context.getObjCConstantStringInterface(); Ty = Context.getObjCObjectPointerType(Ty); } else { - // If there is no NSString interface defined then treat constant - // strings as untyped objects and let the runtime figure it out later. - Ty = Context.getObjCIdType(); + // If there is no NSString interface defined, implicitly declare + // a @class NSString; and use that instead. This is to make sure + // type of an NSString literal is represented correctly, instead of + // being an 'id' type. + Ty = Context.getObjCNSStringType(); + if (Ty.isNull()) { + ObjCInterfaceDecl *NSStringIDecl = + ObjCInterfaceDecl::Create (Context, + Context.getTranslationUnitDecl(), + SourceLocation(), NSIdent, + 0, SourceLocation()); + Ty = Context.getObjCInterfaceType(NSStringIDecl); + Context.setObjCNSStringType(Ty); + } + Ty = Context.getObjCObjectPointerType(Ty); + } + } + + return new (Context) ObjCStringLiteral(S, Ty, AtLoc); +} + +/// \brief Retrieve the NSNumber factory method that should be used to create +/// an Objective-C literal for the given type. +static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, + QualType T, QualType ReturnType, + SourceRange Range) { + llvm::Optional<NSAPI::NSNumberLiteralMethodKind> Kind + = S.NSAPIObj->getNSNumberFactoryMethodKind(T); + + if (!Kind) { + S.Diag(Loc, diag::err_invalid_nsnumber_type) + << T << Range; + return 0; + } + + // If we already looked up this method, we're done. + if (S.NSNumberLiteralMethods[*Kind]) + return S.NSNumberLiteralMethods[*Kind]; + + Selector Sel = S.NSAPIObj->getNSNumberLiteralSelector(*Kind, + /*Instance=*/false); + + // Look for the appropriate method within NSNumber. + ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel);; + if (!Method && S.getLangOpts().DebuggerObjCLiteral) { + TypeSourceInfo *ResultTInfo = 0; + Method = ObjCMethodDecl::Create(S.Context, SourceLocation(), SourceLocation(), Sel, + ReturnType, + ResultTInfo, + S.Context.getTranslationUnitDecl(), + false /*Instance*/, false/*isVariadic*/, + /*isSynthesized=*/false, + /*isImplicitlyDeclared=*/true, /*isDefined=*/false, + ObjCMethodDecl::Required, + false); + ParmVarDecl *value = ParmVarDecl::Create(S.Context, Method, + SourceLocation(), SourceLocation(), + &S.Context.Idents.get("value"), + T, /*TInfo=*/0, SC_None, SC_None, 0); + Method->setMethodParams(S.Context, value, ArrayRef<SourceLocation>()); + } + + if (!Method) { + S.Diag(Loc, diag::err_undeclared_nsnumber_method) << Sel; + return 0; + } + + // Make sure the return type is reasonable. + if (!Method->getResultType()->isObjCObjectPointerType()) { + S.Diag(Loc, diag::err_objc_literal_method_sig) + << Sel; + S.Diag(Method->getLocation(), diag::note_objc_literal_method_return) + << Method->getResultType(); + return 0; + } + + // Note: if the parameter type is out-of-line, we'll catch it later in the + // implicit conversion. + + S.NSNumberLiteralMethods[*Kind] = Method; + return Method; +} + +/// BuildObjCNumericLiteral - builds an ObjCNumericLiteral AST node for the +/// numeric literal expression. Type of the expression will be "NSNumber *" +/// or "id" if NSNumber is unavailable. +ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) { + // Look up the NSNumber class, if we haven't done so already. + if (!NSNumberDecl) { + NamedDecl *IF = LookupSingleName(TUScope, + NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber), + AtLoc, LookupOrdinaryName); + NSNumberDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + + if (!NSNumberDecl && getLangOpts().DebuggerObjCLiteral) + NSNumberDecl = ObjCInterfaceDecl::Create (Context, + Context.getTranslationUnitDecl(), + SourceLocation(), + NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber), + 0, SourceLocation()); + if (!NSNumberDecl) { + Diag(AtLoc, diag::err_undeclared_nsnumber); + return ExprError(); + } + } + + // Determine the type of the literal. + QualType NumberType = Number->getType(); + if (CharacterLiteral *Char = dyn_cast<CharacterLiteral>(Number)) { + // In C, character literals have type 'int'. That's not the type we want + // to use to determine the Objective-c literal kind. + switch (Char->getKind()) { + case CharacterLiteral::Ascii: + NumberType = Context.CharTy; + break; + + case CharacterLiteral::Wide: + NumberType = Context.getWCharType(); + break; + + case CharacterLiteral::UTF16: + NumberType = Context.Char16Ty; + break; + + case CharacterLiteral::UTF32: + NumberType = Context.Char32Ty; + break; + } + } + + ObjCMethodDecl *Method = 0; + // Look for the appropriate method within NSNumber. + // Construct the literal. + QualType Ty + = Context.getObjCObjectPointerType( + Context.getObjCInterfaceType(NSNumberDecl)); + Method = getNSNumberFactoryMethod(*this, AtLoc, + NumberType, Ty, + Number->getSourceRange()); + + if (!Method) + return ExprError(); + + // Convert the number to the type that the parameter expects. + QualType ElementT = Method->param_begin()[0]->getType(); + ExprResult ConvertedNumber = PerformImplicitConversion(Number, ElementT, + AA_Sending); + if (ConvertedNumber.isInvalid()) + return ExprError(); + Number = ConvertedNumber.get(); + + return MaybeBindToTemporary( + new (Context) ObjCNumericLiteral(Number, Ty, Method, AtLoc)); +} + +ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc, + SourceLocation ValueLoc, + bool Value) { + ExprResult Inner; + if (getLangOpts().CPlusPlus) { + Inner = ActOnCXXBoolLiteral(ValueLoc, Value? tok::kw_true : tok::kw_false); + } else { + // C doesn't actually have a way to represent literal values of type + // _Bool. So, we'll use 0/1 and implicit cast to _Bool. + Inner = ActOnIntegerConstant(ValueLoc, Value? 1 : 0); + Inner = ImpCastExprToType(Inner.get(), Context.BoolTy, + CK_IntegralToBoolean); + } + + return BuildObjCNumericLiteral(AtLoc, Inner.get()); +} + +/// \brief Check that the given expression is a valid element of an Objective-C +/// collection literal. +static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, + QualType T) { + // If the expression is type-dependent, there's nothing for us to do. + if (Element->isTypeDependent()) + return Element; + + ExprResult Result = S.CheckPlaceholderExpr(Element); + if (Result.isInvalid()) + return ExprError(); + Element = Result.get(); + + // In C++, check for an implicit conversion to an Objective-C object pointer + // type. + if (S.getLangOpts().CPlusPlus && Element->getType()->isRecordType()) { + InitializedEntity Entity + = InitializedEntity::InitializeParameter(S.Context, T, /*Consumed=*/false); + InitializationKind Kind + = InitializationKind::CreateCopy(Element->getLocStart(), SourceLocation()); + InitializationSequence Seq(S, Entity, Kind, &Element, 1); + if (!Seq.Failed()) + return Seq.Perform(S, Entity, Kind, MultiExprArg(S, &Element, 1)); + } + + Expr *OrigElement = Element; + + // Perform lvalue-to-rvalue conversion. + Result = S.DefaultLvalueConversion(Element); + if (Result.isInvalid()) + return ExprError(); + Element = Result.get(); + + // Make sure that we have an Objective-C pointer type or block. + if (!Element->getType()->isObjCObjectPointerType() && + !Element->getType()->isBlockPointerType()) { + bool Recovered = false; + + // If this is potentially an Objective-C numeric literal, add the '@'. + if (isa<IntegerLiteral>(OrigElement) || + isa<CharacterLiteral>(OrigElement) || + isa<FloatingLiteral>(OrigElement) || + isa<ObjCBoolLiteralExpr>(OrigElement) || + isa<CXXBoolLiteralExpr>(OrigElement)) { + if (S.NSAPIObj->getNSNumberFactoryMethodKind(OrigElement->getType())) { + int Which = isa<CharacterLiteral>(OrigElement) ? 1 + : (isa<CXXBoolLiteralExpr>(OrigElement) || + isa<ObjCBoolLiteralExpr>(OrigElement)) ? 2 + : 3; + + S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection) + << Which << OrigElement->getSourceRange() + << FixItHint::CreateInsertion(OrigElement->getLocStart(), "@"); + + Result = S.BuildObjCNumericLiteral(OrigElement->getLocStart(), + OrigElement); + if (Result.isInvalid()) + return ExprError(); + + Element = Result.get(); + Recovered = true; + } + } + // If this is potentially an Objective-C string literal, add the '@'. + else if (StringLiteral *String = dyn_cast<StringLiteral>(OrigElement)) { + if (String->isAscii()) { + S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection) + << 0 << OrigElement->getSourceRange() + << FixItHint::CreateInsertion(OrigElement->getLocStart(), "@"); + + Result = S.BuildObjCStringLiteral(OrigElement->getLocStart(), String); + if (Result.isInvalid()) + return ExprError(); + + Element = Result.get(); + Recovered = true; + } + } + + if (!Recovered) { + S.Diag(Element->getLocStart(), diag::err_invalid_collection_element) + << Element->getType(); + return ExprError(); } } + + // Make sure that the element has the type that the container factory + // function expects. + return S.PerformCopyInitialization( + InitializedEntity::InitializeParameter(S.Context, T, + /*Consumed=*/false), + Element->getLocStart(), Element); +} - return new (Context) ObjCStringLiteral(S, Ty, AtLocs[0]); +ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, + Expr *IndexExpr, + ObjCMethodDecl *getterMethod, + ObjCMethodDecl *setterMethod) { + // Feature support is for modern abi. + if (!LangOpts.ObjCNonFragileABI) + return ExprError(); + // If the expression is type-dependent, there's nothing for us to do. + assert ((!BaseExpr->isTypeDependent() && !IndexExpr->isTypeDependent()) && + "base or index cannot have dependent type here"); + ExprResult Result = CheckPlaceholderExpr(IndexExpr); + if (Result.isInvalid()) + return ExprError(); + IndexExpr = Result.get(); + + // Perform lvalue-to-rvalue conversion. + Result = DefaultLvalueConversion(BaseExpr); + if (Result.isInvalid()) + return ExprError(); + BaseExpr = Result.get(); + return Owned(ObjCSubscriptRefExpr::Create(Context, + BaseExpr, + IndexExpr, + Context.PseudoObjectTy, + getterMethod, + setterMethod, RB)); + +} + +ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { + // Look up the NSArray class, if we haven't done so already. + if (!NSArrayDecl) { + NamedDecl *IF = LookupSingleName(TUScope, + NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray), + SR.getBegin(), + LookupOrdinaryName); + NSArrayDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + if (!NSArrayDecl && getLangOpts().DebuggerObjCLiteral) + NSArrayDecl = ObjCInterfaceDecl::Create (Context, + Context.getTranslationUnitDecl(), + SourceLocation(), + NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray), + 0, SourceLocation()); + + if (!NSArrayDecl) { + Diag(SR.getBegin(), diag::err_undeclared_nsarray); + return ExprError(); + } + } + + // Find the arrayWithObjects:count: method, if we haven't done so already. + QualType IdT = Context.getObjCIdType(); + if (!ArrayWithObjectsMethod) { + Selector + Sel = NSAPIObj->getNSArraySelector(NSAPI::NSArr_arrayWithObjectsCount); + ArrayWithObjectsMethod = NSArrayDecl->lookupClassMethod(Sel); + if (!ArrayWithObjectsMethod && getLangOpts().DebuggerObjCLiteral) { + TypeSourceInfo *ResultTInfo = 0; + ArrayWithObjectsMethod = + ObjCMethodDecl::Create(Context, + SourceLocation(), SourceLocation(), Sel, + IdT, + ResultTInfo, + Context.getTranslationUnitDecl(), + false /*Instance*/, false/*isVariadic*/, + /*isSynthesized=*/false, + /*isImplicitlyDeclared=*/true, /*isDefined=*/false, + ObjCMethodDecl::Required, + false); + SmallVector<ParmVarDecl *, 2> Params; + ParmVarDecl *objects = ParmVarDecl::Create(Context, ArrayWithObjectsMethod, + SourceLocation(), SourceLocation(), + &Context.Idents.get("objects"), + Context.getPointerType(IdT), + /*TInfo=*/0, + SC_None, + SC_None, + 0); + Params.push_back(objects); + ParmVarDecl *cnt = ParmVarDecl::Create(Context, ArrayWithObjectsMethod, + SourceLocation(), SourceLocation(), + &Context.Idents.get("cnt"), + Context.UnsignedLongTy, + /*TInfo=*/0, + SC_None, + SC_None, + 0); + Params.push_back(cnt); + ArrayWithObjectsMethod->setMethodParams(Context, Params, + ArrayRef<SourceLocation>()); + + + } + + if (!ArrayWithObjectsMethod) { + Diag(SR.getBegin(), diag::err_undeclared_arraywithobjects) << Sel; + return ExprError(); + } + } + + // Make sure the return type is reasonable. + if (!ArrayWithObjectsMethod->getResultType()->isObjCObjectPointerType()) { + Diag(SR.getBegin(), diag::err_objc_literal_method_sig) + << ArrayWithObjectsMethod->getSelector(); + Diag(ArrayWithObjectsMethod->getLocation(), + diag::note_objc_literal_method_return) + << ArrayWithObjectsMethod->getResultType(); + return ExprError(); + } + + // Dig out the type that all elements should be converted to. + QualType T = ArrayWithObjectsMethod->param_begin()[0]->getType(); + const PointerType *PtrT = T->getAs<PointerType>(); + if (!PtrT || + !Context.hasSameUnqualifiedType(PtrT->getPointeeType(), IdT)) { + Diag(SR.getBegin(), diag::err_objc_literal_method_sig) + << ArrayWithObjectsMethod->getSelector(); + Diag(ArrayWithObjectsMethod->param_begin()[0]->getLocation(), + diag::note_objc_literal_method_param) + << 0 << T + << Context.getPointerType(IdT.withConst()); + return ExprError(); + } + T = PtrT->getPointeeType(); + + // Check that the 'count' parameter is integral. + if (!ArrayWithObjectsMethod->param_begin()[1]->getType()->isIntegerType()) { + Diag(SR.getBegin(), diag::err_objc_literal_method_sig) + << ArrayWithObjectsMethod->getSelector(); + Diag(ArrayWithObjectsMethod->param_begin()[1]->getLocation(), + diag::note_objc_literal_method_param) + << 1 + << ArrayWithObjectsMethod->param_begin()[1]->getType() + << "integral"; + return ExprError(); + } + + // Check that each of the elements provided is valid in a collection literal, + // performing conversions as necessary. + Expr **ElementsBuffer = Elements.get(); + for (unsigned I = 0, N = Elements.size(); I != N; ++I) { + ExprResult Converted = CheckObjCCollectionLiteralElement(*this, + ElementsBuffer[I], + T); + if (Converted.isInvalid()) + return ExprError(); + + ElementsBuffer[I] = Converted.get(); + } + + QualType Ty + = Context.getObjCObjectPointerType( + Context.getObjCInterfaceType(NSArrayDecl)); + + return MaybeBindToTemporary( + ObjCArrayLiteral::Create(Context, + llvm::makeArrayRef(Elements.get(), + Elements.size()), + Ty, ArrayWithObjectsMethod, SR)); +} + +ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, + ObjCDictionaryElement *Elements, + unsigned NumElements) { + // Look up the NSDictionary class, if we haven't done so already. + if (!NSDictionaryDecl) { + NamedDecl *IF = LookupSingleName(TUScope, + NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary), + SR.getBegin(), LookupOrdinaryName); + NSDictionaryDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + if (!NSDictionaryDecl && getLangOpts().DebuggerObjCLiteral) + NSDictionaryDecl = ObjCInterfaceDecl::Create (Context, + Context.getTranslationUnitDecl(), + SourceLocation(), + NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary), + 0, SourceLocation()); + + if (!NSDictionaryDecl) { + Diag(SR.getBegin(), diag::err_undeclared_nsdictionary); + return ExprError(); + } + } + + // Find the dictionaryWithObjects:forKeys:count: method, if we haven't done + // so already. + QualType IdT = Context.getObjCIdType(); + if (!DictionaryWithObjectsMethod) { + Selector Sel = NSAPIObj->getNSDictionarySelector( + NSAPI::NSDict_dictionaryWithObjectsForKeysCount); + DictionaryWithObjectsMethod = NSDictionaryDecl->lookupClassMethod(Sel); + if (!DictionaryWithObjectsMethod && getLangOpts().DebuggerObjCLiteral) { + DictionaryWithObjectsMethod = + ObjCMethodDecl::Create(Context, + SourceLocation(), SourceLocation(), Sel, + IdT, + 0 /*TypeSourceInfo */, + Context.getTranslationUnitDecl(), + false /*Instance*/, false/*isVariadic*/, + /*isSynthesized=*/false, + /*isImplicitlyDeclared=*/true, /*isDefined=*/false, + ObjCMethodDecl::Required, + false); + SmallVector<ParmVarDecl *, 3> Params; + ParmVarDecl *objects = ParmVarDecl::Create(Context, DictionaryWithObjectsMethod, + SourceLocation(), SourceLocation(), + &Context.Idents.get("objects"), + Context.getPointerType(IdT), + /*TInfo=*/0, + SC_None, + SC_None, + 0); + Params.push_back(objects); + ParmVarDecl *keys = ParmVarDecl::Create(Context, DictionaryWithObjectsMethod, + SourceLocation(), SourceLocation(), + &Context.Idents.get("keys"), + Context.getPointerType(IdT), + /*TInfo=*/0, + SC_None, + SC_None, + 0); + Params.push_back(keys); + ParmVarDecl *cnt = ParmVarDecl::Create(Context, DictionaryWithObjectsMethod, + SourceLocation(), SourceLocation(), + &Context.Idents.get("cnt"), + Context.UnsignedLongTy, + /*TInfo=*/0, + SC_None, + SC_None, + 0); + Params.push_back(cnt); + DictionaryWithObjectsMethod->setMethodParams(Context, Params, + ArrayRef<SourceLocation>()); + } + + if (!DictionaryWithObjectsMethod) { + Diag(SR.getBegin(), diag::err_undeclared_dictwithobjects) << Sel; + return ExprError(); + } + } + + // Make sure the return type is reasonable. + if (!DictionaryWithObjectsMethod->getResultType()->isObjCObjectPointerType()){ + Diag(SR.getBegin(), diag::err_objc_literal_method_sig) + << DictionaryWithObjectsMethod->getSelector(); + Diag(DictionaryWithObjectsMethod->getLocation(), + diag::note_objc_literal_method_return) + << DictionaryWithObjectsMethod->getResultType(); + return ExprError(); + } + + // Dig out the type that all values should be converted to. + QualType ValueT = DictionaryWithObjectsMethod->param_begin()[0]->getType(); + const PointerType *PtrValue = ValueT->getAs<PointerType>(); + if (!PtrValue || + !Context.hasSameUnqualifiedType(PtrValue->getPointeeType(), IdT)) { + Diag(SR.getBegin(), diag::err_objc_literal_method_sig) + << DictionaryWithObjectsMethod->getSelector(); + Diag(DictionaryWithObjectsMethod->param_begin()[0]->getLocation(), + diag::note_objc_literal_method_param) + << 0 << ValueT + << Context.getPointerType(IdT.withConst()); + return ExprError(); + } + ValueT = PtrValue->getPointeeType(); + + // Dig out the type that all keys should be converted to. + QualType KeyT = DictionaryWithObjectsMethod->param_begin()[1]->getType(); + const PointerType *PtrKey = KeyT->getAs<PointerType>(); + if (!PtrKey || + !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(), + IdT)) { + bool err = true; + if (PtrKey) { + if (QIDNSCopying.isNull()) { + // key argument of selector is id<NSCopying>? + if (ObjCProtocolDecl *NSCopyingPDecl = + LookupProtocol(&Context.Idents.get("NSCopying"), SR.getBegin())) { + ObjCProtocolDecl *PQ[] = {NSCopyingPDecl}; + QIDNSCopying = + Context.getObjCObjectType(Context.ObjCBuiltinIdTy, + (ObjCProtocolDecl**) PQ,1); + QIDNSCopying = Context.getObjCObjectPointerType(QIDNSCopying); + } + } + if (!QIDNSCopying.isNull()) + err = !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(), + QIDNSCopying); + } + + if (err) { + Diag(SR.getBegin(), diag::err_objc_literal_method_sig) + << DictionaryWithObjectsMethod->getSelector(); + Diag(DictionaryWithObjectsMethod->param_begin()[1]->getLocation(), + diag::note_objc_literal_method_param) + << 1 << KeyT + << Context.getPointerType(IdT.withConst()); + return ExprError(); + } + } + KeyT = PtrKey->getPointeeType(); + + // Check that the 'count' parameter is integral. + if (!DictionaryWithObjectsMethod->param_begin()[2]->getType() + ->isIntegerType()) { + Diag(SR.getBegin(), diag::err_objc_literal_method_sig) + << DictionaryWithObjectsMethod->getSelector(); + Diag(DictionaryWithObjectsMethod->param_begin()[2]->getLocation(), + diag::note_objc_literal_method_param) + << 2 + << DictionaryWithObjectsMethod->param_begin()[2]->getType() + << "integral"; + return ExprError(); + } + + // Check that each of the keys and values provided is valid in a collection + // literal, performing conversions as necessary. + bool HasPackExpansions = false; + for (unsigned I = 0, N = NumElements; I != N; ++I) { + // Check the key. + ExprResult Key = CheckObjCCollectionLiteralElement(*this, Elements[I].Key, + KeyT); + if (Key.isInvalid()) + return ExprError(); + + // Check the value. + ExprResult Value + = CheckObjCCollectionLiteralElement(*this, Elements[I].Value, ValueT); + if (Value.isInvalid()) + return ExprError(); + + Elements[I].Key = Key.get(); + Elements[I].Value = Value.get(); + + if (Elements[I].EllipsisLoc.isInvalid()) + continue; + + if (!Elements[I].Key->containsUnexpandedParameterPack() && + !Elements[I].Value->containsUnexpandedParameterPack()) { + Diag(Elements[I].EllipsisLoc, + diag::err_pack_expansion_without_parameter_packs) + << SourceRange(Elements[I].Key->getLocStart(), + Elements[I].Value->getLocEnd()); + return ExprError(); + } + + HasPackExpansions = true; + } + + + QualType Ty + = Context.getObjCObjectPointerType( + Context.getObjCInterfaceType(NSDictionaryDecl)); + return MaybeBindToTemporary( + ObjCDictionaryLiteral::Create(Context, + llvm::makeArrayRef(Elements, + NumElements), + HasPackExpansions, + Ty, + DictionaryWithObjectsMethod, SR)); } ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc, @@ -144,7 +768,7 @@ ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc, // which is an array type. StrTy = Context.CharTy; // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). - if (getLangOptions().CPlusPlus || getLangOptions().ConstStrings) + if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings) StrTy.addConst(); StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1), ArrayType::Normal, 0); @@ -191,7 +815,7 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, // In ARC, forbid the user from using @selector for // retain/release/autorelease/dealloc/retainCount. - if (getLangOptions().ObjCAutoRefCount) { + if (getLangOpts().ObjCAutoRefCount) { switch (Sel.getMethodFamily()) { case OMF_retain: case OMF_release: @@ -237,14 +861,8 @@ ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, } /// Try to capture an implicit reference to 'self'. -ObjCMethodDecl *Sema::tryCaptureObjCSelf() { - // Ignore block scopes: we can capture through them. - DeclContext *DC = CurContext; - while (true) { - if (isa<BlockDecl>(DC)) DC = cast<BlockDecl>(DC)->getDeclContext(); - else if (isa<EnumDecl>(DC)) DC = cast<EnumDecl>(DC)->getDeclContext(); - else break; - } +ObjCMethodDecl *Sema::tryCaptureObjCSelf(SourceLocation Loc) { + DeclContext *DC = getFunctionLevelDeclContext(); // If we're not in an ObjC method, error out. Note that, unlike the // C++ case, we don't require an instance method --- class methods @@ -253,22 +871,7 @@ ObjCMethodDecl *Sema::tryCaptureObjCSelf() { if (!method) return 0; - ImplicitParamDecl *self = method->getSelfDecl(); - assert(self && "capturing 'self' in non-definition?"); - - // Mark that we're closing on 'this' in all the block scopes, if applicable. - for (unsigned idx = FunctionScopes.size() - 1; - isa<BlockScopeInfo>(FunctionScopes[idx]); - --idx) { - BlockScopeInfo *blockScope = cast<BlockScopeInfo>(FunctionScopes[idx]); - unsigned &captureIndex = blockScope->CaptureMap[self]; - if (captureIndex) break; - - bool nested = isa<BlockScopeInfo>(FunctionScopes[idx-1]); - blockScope->Captures.push_back( - BlockDecl::Capture(self, /*byref*/ false, nested, /*copy*/ 0)); - captureIndex = blockScope->Captures.size(); // +1 - } + tryCaptureVariable(method->getSelfDecl(), Loc); return method; } @@ -365,18 +968,18 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, } unsigned DiagID; - if (getLangOptions().ObjCAutoRefCount) + if (getLangOpts().ObjCAutoRefCount) DiagID = diag::err_arc_method_not_found; else DiagID = isClassMessage ? diag::warn_class_method_not_found : diag::warn_inst_method_not_found; - if (!getLangOptions().DebuggerSupport) + if (!getLangOpts().DebuggerSupport) Diag(lbrac, DiagID) << Sel << isClassMessage << SourceRange(lbrac, rbrac); // In debuggers, we want to use __unknown_anytype for these // results so that clients can cast them. - if (getLangOptions().DebuggerSupport) { + if (getLangOpts().DebuggerSupport) { ReturnType = Context.UnknownAnyTy; } else { ReturnType = Context.getObjCIdType(); @@ -409,17 +1012,23 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, Expr *argExpr = Args[i]; - ParmVarDecl *Param = Method->param_begin()[i]; + ParmVarDecl *param = Method->param_begin()[i]; assert(argExpr && "CheckMessageArgumentTypes(): missing expression"); + // Strip the unbridged-cast placeholder expression off unless it's + // a consumed argument. + if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) && + !param->hasAttr<CFConsumedAttr>()) + argExpr = stripARCUnbridgedCast(argExpr); + if (RequireCompleteType(argExpr->getSourceRange().getBegin(), - Param->getType(), + param->getType(), PDiag(diag::err_call_incomplete_argument) << argExpr->getSourceRange())) return true; InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, - Param); + param); ExprResult ArgE = PerformCopyInitialization(Entity, lbrac, Owned(argExpr)); if (ArgE.isInvalid()) IsError = true; @@ -448,27 +1057,24 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, Args[NumArgs-1]->getLocEnd()); } } - // diagnose nonnull arguments. - for (specific_attr_iterator<NonNullAttr> - i = Method->specific_attr_begin<NonNullAttr>(), - e = Method->specific_attr_end<NonNullAttr>(); i != e; ++i) { - CheckNonNullArguments(*i, Args, lbrac); - } DiagnoseSentinelCalls(Method, lbrac, Args, NumArgs); + + // Do additional checkings on method. + IsError |= CheckObjCMethodCall(Method, lbrac, Args, NumArgs); + return IsError; } bool Sema::isSelfExpr(Expr *receiver) { // 'self' is objc 'self' in an objc method only. - DeclContext *DC = CurContext; - while (isa<BlockDecl>(DC)) - DC = DC->getParent(); - if (DC && !isa<ObjCMethodDecl>(DC)) - return false; + ObjCMethodDecl *method = + dyn_cast<ObjCMethodDecl>(CurContext->getNonClosureAncestor()); + if (!method) return false; + receiver = receiver->IgnoreParenLValueCasts(); if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(receiver)) - if (DRE->getDecl()->getIdentifier() == &Context.Idents.get("self")) + if (DRE->getDecl() == method->getSelfDecl()) return true; return false; } @@ -507,6 +1113,9 @@ ObjCMethodDecl *Sema::LookupPrivateClassMethod(Selector Sel, ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel, ObjCInterfaceDecl *ClassDecl) { + if (!ClassDecl->hasDefinition()) + return 0; + ObjCMethodDecl *Method = 0; while (ClassDecl && !Method) { // If we have implementations in scope, check "private" methods. @@ -521,6 +1130,35 @@ ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel, return Method; } +/// LookupMethodInType - Look up a method in an ObjCObjectType. +ObjCMethodDecl *Sema::LookupMethodInObjectType(Selector sel, QualType type, + bool isInstance) { + const ObjCObjectType *objType = type->castAs<ObjCObjectType>(); + if (ObjCInterfaceDecl *iface = objType->getInterface()) { + // Look it up in the main interface (and categories, etc.) + if (ObjCMethodDecl *method = iface->lookupMethod(sel, isInstance)) + return method; + + // Okay, look for "private" methods declared in any + // @implementations we've seen. + if (isInstance) { + if (ObjCMethodDecl *method = LookupPrivateInstanceMethod(sel, iface)) + return method; + } else { + if (ObjCMethodDecl *method = LookupPrivateClassMethod(sel, iface)) + return method; + } + } + + // Check qualifiers. + for (ObjCObjectType::qual_iterator + i = objType->qual_begin(), e = objType->qual_end(); i != e; ++i) + if (ObjCMethodDecl *method = (*i)->lookupMethod(sel, isInstance)) + return method; + + return 0; +} + /// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier /// list of a qualified objective pointer type. ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel, @@ -557,35 +1195,26 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, } IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); - - if (IFace->isForwardDecl()) { - Diag(MemberLoc, diag::err_property_not_found_forward_class) - << MemberName << QualType(OPT, 0); - Diag(IFace->getLocation(), diag::note_forward_class); + SourceRange BaseRange = Super? SourceRange(SuperLoc) + : BaseExpr->getSourceRange(); + if (RequireCompleteType(MemberLoc, OPT->getPointeeType(), + PDiag(diag::err_property_not_found_forward_class) + << MemberName << BaseRange)) return ExprError(); - } + // Search for a declared property first. if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) { // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); - QualType ResTy = PD->getType(); - ResTy = ResTy.getNonLValueExprType(Context); - Selector Sel = PP.getSelectorTable().getNullarySelector(Member); - ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); - if (Getter && - (Getter->hasRelatedResultType() - || DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc))) - ResTy = getMessageSendResultType(QualType(OPT, 0), Getter, false, - Super); if (Super) - return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, + return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, MemberLoc, SuperLoc, SuperType)); else - return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, + return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, MemberLoc, BaseExpr)); } @@ -597,17 +1226,16 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); - QualType T = PD->getType(); - if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) - T = getMessageSendResultType(QualType(OPT, 0), Getter, false, Super); if (Super) - return Owned(new (Context) ObjCPropertyRefExpr(PD, T, + return Owned(new (Context) ObjCPropertyRefExpr(PD, + Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, MemberLoc, SuperLoc, SuperType)); else - return Owned(new (Context) ObjCPropertyRefExpr(PD, T, + return Owned(new (Context) ObjCPropertyRefExpr(PD, + Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, MemberLoc, @@ -662,38 +1290,27 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, return ExprError(); if (Getter || Setter) { - QualType PType; - if (Getter) - PType = getMessageSendResultType(QualType(OPT, 0), Getter, false, Super); - else { - ParmVarDecl *ArgDecl = *Setter->param_begin(); - PType = ArgDecl->getType(); - } - - ExprValueKind VK = VK_LValue; - ExprObjectKind OK = OK_ObjCProperty; - if (!getLangOptions().CPlusPlus && !PType.hasQualifiers() && - PType->isVoidType()) - VK = VK_RValue, OK = OK_Ordinary; - if (Super) return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, - PType, VK, OK, + Context.PseudoObjectTy, + VK_LValue, OK_ObjCProperty, MemberLoc, SuperLoc, SuperType)); else return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, - PType, VK, OK, + Context.PseudoObjectTy, + VK_LValue, OK_ObjCProperty, MemberLoc, BaseExpr)); } // Attempt to correct for typos in property names. - TypoCorrection Corrected = CorrectTypo( + DeclFilterCCC<ObjCPropertyDecl> Validator; + if (TypoCorrection Corrected = CorrectTypo( DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL, - NULL, IFace, false, CTC_NoKeywords, OPT); - if (ObjCPropertyDecl *Property = - Corrected.getCorrectionDeclAs<ObjCPropertyDecl>()) { + NULL, Validator, IFace, false, OPT)) { + ObjCPropertyDecl *Property = + Corrected.getCorrectionDeclAs<ObjCPropertyDecl>(); DeclarationName TypoResult = Corrected.getCorrection(); Diag(MemberLoc, diag::err_property_not_found_suggest) << MemberName << QualType(OPT, 0) << TypoResult @@ -710,14 +1327,10 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, QualType T = Ivar->getType(); if (const ObjCObjectPointerType * OBJPT = T->getAsObjCInterfacePointerType()) { - const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType(); - if (ObjCInterfaceDecl *IFace = IFaceT->getDecl()) - if (IFace->isForwardDecl()) { - Diag(MemberLoc, diag::err_property_not_as_forward_class) - << MemberName << IFace; - Diag(IFace->getLocation(), diag::note_forward_class); - return ExprError(); - } + if (RequireCompleteType(MemberLoc, OBJPT->getPointeeType(), + PDiag(diag::err_property_not_as_forward_class) + << MemberName << BaseExpr->getSourceRange())) + return ExprError(); } Diag(MemberLoc, diag::err_ivar_access_using_property_syntax_suggest) @@ -753,7 +1366,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, if (receiverNamePtr->isStr("super")) { IsSuper = true; - if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf()) { + if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(receiverNameLoc)) { if (CurMethod->isInstanceMethod()) { QualType T = Context.getObjCInterfaceType(CurMethod->getClassInterface()); @@ -819,34 +1432,17 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, return ExprError(); if (Getter || Setter) { - QualType PType; - - ExprValueKind VK = VK_LValue; - if (Getter) { - PType = getMessageSendResultType(Context.getObjCInterfaceType(IFace), - Getter, true, - receiverNamePtr->isStr("super")); - if (!getLangOptions().CPlusPlus && - !PType.hasQualifiers() && PType->isVoidType()) - VK = VK_RValue; - } else { - for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(), - E = Setter->param_end(); PI != E; ++PI) - PType = (*PI)->getType(); - VK = VK_LValue; - } - - ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty); - if (IsSuper) return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, - PType, VK, OK, + Context.PseudoObjectTy, + VK_LValue, OK_ObjCProperty, propertyNameLoc, receiverNameLoc, Context.getObjCInterfaceType(IFace))); return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, - PType, VK, OK, + Context.PseudoObjectTy, + VK_LValue, OK_ObjCProperty, propertyNameLoc, receiverNameLoc, IFace)); } @@ -854,6 +1450,24 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, << &propertyName << Context.getObjCInterfaceType(IFace)); } +namespace { + +class ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback { + public: + ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) { + // Determine whether "super" is acceptable in the current context. + if (Method && Method->getClassInterface()) + WantObjCSuper = Method->getClassInterface()->getSuperClass(); + } + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() || + candidate.isKeyword("super"); + } +}; + +} + Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, IdentifierInfo *Name, SourceLocation NameLoc, @@ -878,6 +1492,11 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, // FIXME: This is a hack. Ivar lookup should be part of normal // lookup. if (ObjCMethodDecl *Method = getCurMethodDecl()) { + if (!Method->getClassInterface()) { + // Fall back: let the parser try to parse it as an instance message. + return ObjCInstanceMessage; + } + ObjCInterfaceDecl *ClassDeclared; if (Method->getClassInterface()->lookupInstanceVariable(Name, ClassDeclared)) @@ -918,39 +1537,32 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, } } - // Determine our typo-correction context. - CorrectTypoContext CTC = CTC_Expression; - if (ObjCMethodDecl *Method = getCurMethodDecl()) - if (Method->getClassInterface() && - Method->getClassInterface()->getSuperClass()) - CTC = CTC_ObjCMessageReceiver; - + ObjCInterfaceOrSuperCCC Validator(getCurMethodDecl()); if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(), Result.getLookupKind(), S, NULL, - NULL, false, CTC)) { - if (NamedDecl *ND = Corrected.getCorrectionDecl()) { - // If we found a declaration, correct when it refers to an Objective-C - // class. - if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND)) { - Diag(NameLoc, diag::err_unknown_receiver_suggest) - << Name << Corrected.getCorrection() - << FixItHint::CreateReplacement(SourceRange(NameLoc), - ND->getNameAsString()); - Diag(ND->getLocation(), diag::note_previous_decl) - << Corrected.getCorrection(); - - QualType T = Context.getObjCInterfaceType(Class); - TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc); - ReceiverType = CreateParsedType(T, TSInfo); - return ObjCClassMessage; - } - } else if (Corrected.isKeyword() && - Corrected.getCorrectionAsIdentifierInfo()->isStr("super")) { - // If we've found the keyword "super", this is a send to super. + Validator)) { + 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. Diag(NameLoc, diag::err_unknown_receiver_suggest) << Name << Corrected.getCorrection() << FixItHint::CreateReplacement(SourceRange(NameLoc), "super"); return ObjCSuperMessage; + } else if (ObjCInterfaceDecl *Class = + Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) { + // If we found a declaration, correct when it refers to an Objective-C + // class. + Diag(NameLoc, diag::err_unknown_receiver_suggest) + << Name << Corrected.getCorrection() + << FixItHint::CreateReplacement(SourceRange(NameLoc), + Class->getNameAsString()); + Diag(Class->getLocation(), diag::note_previous_decl) + << Corrected.getCorrection(); + + QualType T = Context.getObjCInterfaceType(Class); + TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc); + ReceiverType = CreateParsedType(T, TSInfo); + return ObjCClassMessage; } } @@ -966,7 +1578,7 @@ ExprResult Sema::ActOnSuperMessage(Scope *S, SourceLocation RBracLoc, MultiExprArg Args) { // Determine whether we are inside a method or not. - ObjCMethodDecl *Method = tryCaptureObjCSelf(); + ObjCMethodDecl *Method = tryCaptureObjCSelf(SuperLoc); if (!Method) { Diag(SuperLoc, diag::err_invalid_receiver_to_message_super); return ExprError(); @@ -1012,6 +1624,68 @@ ExprResult Sema::ActOnSuperMessage(Scope *S, LBracLoc, SelectorLocs, RBracLoc, move(Args)); } + +ExprResult Sema::BuildClassMessageImplicit(QualType ReceiverType, + bool isSuperReceiver, + SourceLocation Loc, + Selector Sel, + ObjCMethodDecl *Method, + MultiExprArg Args) { + TypeSourceInfo *receiverTypeInfo = 0; + if (!ReceiverType.isNull()) + receiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType); + + return BuildClassMessage(receiverTypeInfo, ReceiverType, + /*SuperLoc=*/isSuperReceiver ? Loc : SourceLocation(), + Sel, Method, Loc, Loc, Loc, Args, + /*isImplicit=*/true); + +} + +static void applyCocoaAPICheck(Sema &S, const ObjCMessageExpr *Msg, + unsigned DiagID, + bool (*refactor)(const ObjCMessageExpr *, + const NSAPI &, edit::Commit &)) { + SourceLocation MsgLoc = Msg->getExprLoc(); + if (S.Diags.getDiagnosticLevel(DiagID, MsgLoc) == DiagnosticsEngine::Ignored) + return; + + SourceManager &SM = S.SourceMgr; + edit::Commit ECommit(SM, S.LangOpts); + if (refactor(Msg,*S.NSAPIObj, ECommit)) { + DiagnosticBuilder Builder = S.Diag(MsgLoc, DiagID) + << Msg->getSelector() << Msg->getSourceRange(); + // FIXME: Don't emit diagnostic at all if fixits are non-commitable. + if (!ECommit.isCommitable()) + return; + for (edit::Commit::edit_iterator + I = ECommit.edit_begin(), E = ECommit.edit_end(); I != E; ++I) { + const edit::Commit::Edit &Edit = *I; + switch (Edit.Kind) { + case edit::Commit::Act_Insert: + Builder.AddFixItHint(FixItHint::CreateInsertion(Edit.OrigLoc, + Edit.Text, + Edit.BeforePrev)); + break; + case edit::Commit::Act_InsertFromRange: + Builder.AddFixItHint( + FixItHint::CreateInsertionFromRange(Edit.OrigLoc, + Edit.getInsertFromRange(SM), + Edit.BeforePrev)); + break; + case edit::Commit::Act_Remove: + Builder.AddFixItHint(FixItHint::CreateRemoval(Edit.getFileRange(SM))); + break; + } + } + } +} + +static void checkCocoaAPI(Sema &S, const ObjCMessageExpr *Msg) { + applyCocoaAPICheck(S, Msg, diag::warn_objc_redundant_literal_use, + edit::rewriteObjCRedundantCallWithLiteral); +} + /// \brief Build an Objective-C class message expression. /// /// This routine takes care of both normal class messages and @@ -1048,7 +1722,8 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, SourceLocation LBracLoc, ArrayRef<SourceLocation> SelectorLocs, SourceLocation RBracLoc, - MultiExprArg ArgsIn) { + MultiExprArg ArgsIn, + bool isImplicit) { SourceLocation Loc = SuperLoc.isValid()? SuperLoc : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin(); if (LBracLoc.isInvalid()) { @@ -1066,7 +1741,8 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, return Owned(ObjCMessageExpr::Create(Context, ReceiverType, VK_RValue, LBracLoc, ReceiverTypeInfo, Sel, SelectorLocs, /*Method=*/0, - makeArrayRef(Args, NumArgs),RBracLoc)); + makeArrayRef(Args, NumArgs),RBracLoc, + isImplicit)); } // Find the class to which we are sending this message. @@ -1078,20 +1754,23 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, return ExprError(); } assert(Class && "We don't know which class we're messaging?"); - (void)DiagnoseUseOfDecl(Class, Loc); + // objc++ diagnoses during typename annotation. + if (!getLangOpts().CPlusPlus) + (void)DiagnoseUseOfDecl(Class, Loc); // Find the method we are messaging. if (!Method) { - if (Class->isForwardDecl()) { - if (getLangOptions().ObjCAutoRefCount) { - Diag(Loc, diag::err_arc_receiver_forward_class) << ReceiverType; - } else { - Diag(Loc, diag::warn_receiver_forward_class) << Class->getDeclName(); - } - + SourceRange TypeRange + = SuperLoc.isValid()? SourceRange(SuperLoc) + : ReceiverTypeInfo->getTypeLoc().getSourceRange(); + if (RequireCompleteType(Loc, Context.getObjCInterfaceType(Class), + (getLangOpts().ObjCAutoRefCount + ? PDiag(diag::err_arc_receiver_forward_class) + : PDiag(diag::warn_receiver_forward_class)) + << TypeRange)) { // A forward class used in messaging is treated as a 'Class' Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(LBracLoc, RBracLoc)); - if (Method && !getLangOptions().ObjCAutoRefCount) + if (Method && !getLangOpts().ObjCAutoRefCount) Diag(Method->getLocation(), diag::note_method_sent_forward_class) << Method->getDeclName(); } @@ -1123,18 +1802,21 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, return ExprError(); // Construct the appropriate ObjCMessageExpr. - Expr *Result; + ObjCMessageExpr *Result; if (SuperLoc.isValid()) Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, SuperLoc, /*IsInstanceSuper=*/false, ReceiverType, Sel, SelectorLocs, Method, makeArrayRef(Args, NumArgs), - RBracLoc); - else + RBracLoc, isImplicit); + else { Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, ReceiverTypeInfo, Sel, SelectorLocs, Method, makeArrayRef(Args, NumArgs), - RBracLoc); + RBracLoc, isImplicit); + if (!isImplicit) + checkCocoaAPI(*this, Result); + } return MaybeBindToTemporary(Result); } @@ -1162,6 +1844,18 @@ ExprResult Sema::ActOnClassMessage(Scope *S, LBracLoc, SelectorLocs, RBracLoc, move(Args)); } +ExprResult Sema::BuildInstanceMessageImplicit(Expr *Receiver, + QualType ReceiverType, + SourceLocation Loc, + Selector Sel, + ObjCMethodDecl *Method, + MultiExprArg Args) { + return BuildInstanceMessage(Receiver, ReceiverType, + /*SuperLoc=*/!Receiver ? Loc : SourceLocation(), + Sel, Method, Loc, Loc, Loc, Args, + /*isImplicit=*/true); +} + /// \brief Build an Objective-C instance message expression. /// /// This routine takes care of both normal instance messages and @@ -1198,7 +1892,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, SourceLocation LBracLoc, ArrayRef<SourceLocation> SelectorLocs, SourceLocation RBracLoc, - MultiExprArg ArgsIn) { + MultiExprArg ArgsIn, + bool isImplicit) { // The location of the receiver. SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart(); @@ -1211,6 +1906,16 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // If we have a receiver expression, perform appropriate promotions // and determine receiver type. if (Receiver) { + if (Receiver->hasPlaceholderType()) { + ExprResult Result; + if (Receiver->getType() == Context.UnknownAnyTy) + Result = forceUnknownAnyToType(Receiver, Context.getObjCIdType()); + else + Result = CheckPlaceholderExpr(Receiver); + if (Result.isInvalid()) return ExprError(); + Receiver = Result.take(); + } + if (Receiver->isTypeDependent()) { // If the receiver is type-dependent, we can't type-check anything // at this point. Build a dependent expression. @@ -1221,7 +1926,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, VK_RValue, LBracLoc, Receiver, Sel, SelectorLocs, /*Method=*/0, makeArrayRef(Args, NumArgs), - RBracLoc)); + RBracLoc, isImplicit)); } // If necessary, apply function/array conversion to the receiver. @@ -1260,7 +1965,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (Method) { Diag(Loc, diag::warn_instance_method_on_class_found) << Method->getSelector() << Sel; - Diag(Method->getLocation(), diag::note_method_declared_at); + Diag(Method->getLocation(), diag::note_method_declared_at) + << Method->getDeclName(); } } } else { @@ -1314,28 +2020,37 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // We allow sending a message to a pointer to an interface (an object). ClassDecl = OCIType->getInterfaceDecl(); - if (ClassDecl->isForwardDecl() && getLangOptions().ObjCAutoRefCount) { - Diag(Loc, diag::err_arc_receiver_forward_instance) - << OCIType->getPointeeType() - << (Receiver ? Receiver->getSourceRange() : SourceRange(SuperLoc)); - return ExprError(); + // Try to complete the type. Under ARC, this is a hard error from which + // we don't try to recover. + const ObjCInterfaceDecl *forwardClass = 0; + if (RequireCompleteType(Loc, OCIType->getPointeeType(), + getLangOpts().ObjCAutoRefCount + ? PDiag(diag::err_arc_receiver_forward_instance) + << (Receiver ? Receiver->getSourceRange() + : SourceRange(SuperLoc)) + : PDiag(diag::warn_receiver_forward_instance) + << (Receiver ? Receiver->getSourceRange() + : SourceRange(SuperLoc)))) { + if (getLangOpts().ObjCAutoRefCount) + return ExprError(); + + forwardClass = OCIType->getInterfaceDecl(); + Diag(Receiver ? Receiver->getLocStart() + : SuperLoc, diag::note_receiver_is_id); + Method = 0; + } else { + Method = ClassDecl->lookupInstanceMethod(Sel); } - // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be - // faster than the following method (which can do *many* linear searches). - // The idea is to add class info to MethodPool. - Method = ClassDecl->lookupInstanceMethod(Sel); - if (!Method) // Search protocol qualifiers. Method = LookupMethodInQualifiedType(Sel, OCIType, true); - const ObjCInterfaceDecl *forwardClass = 0; if (!Method) { // If we have implementations in scope, check "private" methods. Method = LookupPrivateInstanceMethod(Sel, ClassDecl); - if (!Method && getLangOptions().ObjCAutoRefCount) { + if (!Method && getLangOpts().ObjCAutoRefCount) { Diag(Loc, diag::err_arc_may_not_respond) << OCIType->getPointeeType() << Sel; return ExprError(); @@ -1348,8 +2063,6 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (OCIType->qual_empty()) { Method = LookupInstanceMethodInGlobalPool(Sel, SourceRange(LBracLoc, RBracLoc)); - if (OCIType->getInterfaceDecl()->isForwardDecl()) - forwardClass = OCIType->getInterfaceDecl(); if (Method && !forwardClass) Diag(Loc, diag::warn_maynot_respond) << OCIType->getInterfaceDecl()->getIdentifier() << Sel; @@ -1358,7 +2071,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } if (Method && DiagnoseUseOfDecl(Method, Loc, forwardClass)) return ExprError(); - } else if (!getLangOptions().ObjCAutoRefCount && + } else if (!getLangOpts().ObjCAutoRefCount && !Context.getObjCIdType().isNull() && (ReceiverType->isPointerType() || ReceiverType->isIntegerType())) { @@ -1380,7 +2093,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, ReceiverType = Receiver->getType(); } else { ExprResult ReceiverRes; - if (getLangOptions().CPlusPlus) + if (getLangOpts().CPlusPlus) ReceiverRes = PerformContextuallyConvertToObjCPointer(Receiver); if (ReceiverRes.isUsable()) { Receiver = ReceiverRes.take(); @@ -1424,7 +2137,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // In ARC, forbid the user from sending messages to // retain/release/autorelease/dealloc/retainCount explicitly. - if (getLangOptions().ObjCAutoRefCount) { + if (getLangOpts().ObjCAutoRefCount) { ObjCMethodFamily family = (Method ? Method->getMethodFamily() : Sel.getMethodFamily()); switch (family) { @@ -1475,7 +2188,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // selector names a +1 method Diag(SelLoc, diag::err_arc_perform_selector_retains); - Diag(SelMethod->getLocation(), diag::note_method_declared_at); + Diag(SelMethod->getLocation(), diag::note_method_declared_at) + << SelMethod->getDeclName(); } break; default: @@ -1484,7 +2198,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // selector names a +1 method Diag(SelLoc, diag::err_arc_perform_selector_retains); - Diag(SelMethod->getLocation(), diag::note_method_declared_at); + Diag(SelMethod->getLocation(), diag::note_method_declared_at) + << SelMethod->getDeclName(); } break; } @@ -1505,13 +2220,23 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, SuperLoc, /*IsInstanceSuper=*/true, ReceiverType, Sel, SelectorLocs, Method, - makeArrayRef(Args, NumArgs), RBracLoc); - else + makeArrayRef(Args, NumArgs), RBracLoc, + isImplicit); + else { Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, Receiver, Sel, SelectorLocs, Method, - makeArrayRef(Args, NumArgs), RBracLoc); + makeArrayRef(Args, NumArgs), RBracLoc, + isImplicit); + if (!isImplicit) + checkCocoaAPI(*this, Result); + } - if (getLangOptions().ObjCAutoRefCount) { + if (getLangOpts().ObjCAutoRefCount) { + if (Receiver && + (Receiver->IgnoreParenImpCasts()->getType().getObjCLifetime() + == Qualifiers::OCL_Weak)) + Diag(Receiver->getLocStart(), diag::warn_receiver_is_weak); + // In ARC, annotate delegate init calls. if (Result->getMethodFamily() == OMF_init && (SuperLoc.isValid() || isSelfExpr(Receiver))) { @@ -1693,7 +2418,6 @@ namespace { case CK_NoOp: case CK_LValueToRValue: case CK_BitCast: - case CK_GetObjCProperty: case CK_CPointerToObjCPointerCast: case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: @@ -1721,6 +2445,12 @@ namespace { return merge(left, Visit(e->getFalseExpr())); } + /// Look through pseudo-objects. + ACCResult VisitPseudoObjectExpr(PseudoObjectExpr *e) { + // If we're getting here, we should always have a result. + return Visit(e->getResultExpr()); + } + /// Statement expressions are okay if their result expression is okay. ACCResult VisitStmtExpr(StmtExpr *e) { return Visit(e->getSubStmt()->body_back()); @@ -1834,7 +2564,171 @@ namespace { }; } -void +static bool +KnownName(Sema &S, const char *name) { + LookupResult R(S, &S.Context.Idents.get(name), SourceLocation(), + Sema::LookupOrdinaryName); + return S.LookupName(R, S.TUScope, false); +} + +static void addFixitForObjCARCConversion(Sema &S, + DiagnosticBuilder &DiagB, + Sema::CheckedConversionKind CCK, + SourceLocation afterLParen, + QualType castType, + Expr *castExpr, + const char *bridgeKeyword, + const char *CFBridgeName) { + // We handle C-style and implicit casts here. + switch (CCK) { + case Sema::CCK_ImplicitConversion: + case Sema::CCK_CStyleCast: + break; + case Sema::CCK_FunctionalCast: + case Sema::CCK_OtherCast: + return; + } + + if (CFBridgeName) { + Expr *castedE = castExpr; + if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(castedE)) + castedE = CCE->getSubExpr(); + castedE = castedE->IgnoreImpCasts(); + SourceRange range = castedE->getSourceRange(); + if (isa<ParenExpr>(castedE)) { + DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), + CFBridgeName)); + } else { + std::string namePlusParen = CFBridgeName; + namePlusParen += "("; + DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), + namePlusParen)); + DiagB.AddFixItHint(FixItHint::CreateInsertion( + S.PP.getLocForEndOfToken(range.getEnd()), + ")")); + } + return; + } + + if (CCK == Sema::CCK_CStyleCast) { + DiagB.AddFixItHint(FixItHint::CreateInsertion(afterLParen, bridgeKeyword)); + } else { + std::string castCode = "("; + castCode += bridgeKeyword; + castCode += castType.getAsString(); + castCode += ")"; + Expr *castedE = castExpr->IgnoreImpCasts(); + SourceRange range = castedE->getSourceRange(); + if (isa<ParenExpr>(castedE)) { + DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), + castCode)); + } else { + castCode += "("; + DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), + castCode)); + DiagB.AddFixItHint(FixItHint::CreateInsertion( + S.PP.getLocForEndOfToken(range.getEnd()), + ")")); + } + } +} + +static void +diagnoseObjCARCConversion(Sema &S, SourceRange castRange, + QualType castType, ARCConversionTypeClass castACTC, + Expr *castExpr, ARCConversionTypeClass exprACTC, + Sema::CheckedConversionKind CCK) { + SourceLocation loc = + (castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc()); + + if (S.makeUnavailableInSystemHeader(loc, + "converts between Objective-C and C pointers in -fobjc-arc")) + return; + + QualType castExprType = castExpr->getType(); + + unsigned srcKind = 0; + switch (exprACTC) { + case ACTC_none: + case ACTC_coreFoundation: + case ACTC_voidPtr: + srcKind = (castExprType->isPointerType() ? 1 : 0); + break; + case ACTC_retainable: + srcKind = (castExprType->isBlockPointerType() ? 2 : 3); + break; + case ACTC_indirectRetainable: + srcKind = 4; + break; + } + + // Check whether this could be fixed with a bridge cast. + SourceLocation afterLParen = S.PP.getLocForEndOfToken(castRange.getBegin()); + SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc; + + // Bridge from an ARC type to a CF type. + if (castACTC == ACTC_retainable && isAnyRetainable(exprACTC)) { + + S.Diag(loc, diag::err_arc_cast_requires_bridge) + << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit + << 2 // of C pointer type + << castExprType + << unsigned(castType->isBlockPointerType()) // to ObjC|block type + << castType + << castRange + << castExpr->getSourceRange(); + bool br = KnownName(S, "CFBridgingRelease"); + { + DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge); + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, + castType, castExpr, "__bridge ", 0); + } + { + DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge_transfer) + << castExprType << br; + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, + castType, castExpr, "__bridge_transfer ", + br ? "CFBridgingRelease" : 0); + } + + return; + } + + // Bridge from a CF type to an ARC type. + if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) { + bool br = KnownName(S, "CFBridgingRetain"); + S.Diag(loc, diag::err_arc_cast_requires_bridge) + << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit + << unsigned(castExprType->isBlockPointerType()) // of ObjC|block type + << castExprType + << 2 // to C pointer type + << castType + << castRange + << castExpr->getSourceRange(); + + { + DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge); + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, + castType, castExpr, "__bridge ", 0); + } + { + DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge_retained) + << castType << br; + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, + castType, castExpr, "__bridge_retained ", + br ? "CFBridgingRetain" : 0); + } + + return; + } + + S.Diag(loc, diag::err_arc_mismatched_cast) + << (CCK != Sema::CCK_ImplicitConversion) + << srcKind << castExprType << castType + << castRange << castExpr->getSourceRange(); +} + +Sema::ARCConversionResult Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, Expr *&castExpr, CheckedConversionKind CCK) { QualType castExprType = castExpr->getType(); @@ -1847,22 +2741,49 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExprType); ARCConversionTypeClass castACTC = classifyTypeForARCConversion(effCastType); - if (exprACTC == castACTC) return; - if (isAnyCLike(exprACTC) && isAnyCLike(castACTC)) return; + if (exprACTC == castACTC) { + // check for viablity and report error if casting an rvalue to a + // life-time qualifier. + if ((castACTC == ACTC_retainable) && + (CCK == CCK_CStyleCast || CCK == CCK_OtherCast) && + (castType != castExprType)) { + const Type *DT = castType.getTypePtr(); + QualType QDT = castType; + // We desugar some types but not others. We ignore those + // that cannot happen in a cast; i.e. auto, and those which + // should not be de-sugared; i.e typedef. + if (const ParenType *PT = dyn_cast<ParenType>(DT)) + QDT = PT->desugar(); + else if (const TypeOfType *TP = dyn_cast<TypeOfType>(DT)) + QDT = TP->desugar(); + else if (const AttributedType *AT = dyn_cast<AttributedType>(DT)) + QDT = AT->desugar(); + if (QDT != castType && + QDT.getObjCLifetime() != Qualifiers::OCL_None) { + SourceLocation loc = + (castRange.isValid() ? castRange.getBegin() + : castExpr->getExprLoc()); + Diag(loc, diag::err_arc_nolifetime_behavior); + } + } + return ACR_okay; + } + + if (isAnyCLike(exprACTC) && isAnyCLike(castACTC)) return ACR_okay; // Allow all of these types to be cast to integer types (but not // vice-versa). if (castACTC == ACTC_none && castType->isIntegralType(Context)) - return; + return ACR_okay; // Allow casts between pointers to lifetime types (e.g., __strong id*) // and pointers to void (e.g., cv void *). Casting from void* to lifetime* // must be explicit. if (exprACTC == ACTC_indirectRetainable && castACTC == ACTC_voidPtr) - return; + return ACR_okay; if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr && CCK != CCK_ImplicitConversion) - return; + return ACR_okay; switch (ARCCastChecker(Context, exprACTC, castACTC).Visit(castExpr)) { // For invalid casts, fall through. @@ -1872,7 +2793,7 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, // Do nothing for both bottom and +0. case ACC_bottom: case ACC_plusZero: - return; + return ACR_okay; // If the result is +1, consume it here. case ACC_plusOne: @@ -1880,74 +2801,94 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, CK_ARCConsumeObject, castExpr, 0, VK_RValue); ExprNeedsCleanups = true; - return; + return ACR_okay; } - - SourceLocation loc = - (castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc()); - - if (makeUnavailableInSystemHeader(loc, - "converts between Objective-C and C pointers in -fobjc-arc")) - return; - - unsigned srcKind = 0; - switch (exprACTC) { - case ACTC_none: - case ACTC_coreFoundation: - case ACTC_voidPtr: - srcKind = (castExprType->isPointerType() ? 1 : 0); - break; - case ACTC_retainable: - srcKind = (castExprType->isBlockPointerType() ? 2 : 3); - break; - case ACTC_indirectRetainable: - srcKind = 4; - break; + + // If this is a non-implicit cast from id or block type to a + // CoreFoundation type, delay complaining in case the cast is used + // in an acceptable context. + if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) && + CCK != CCK_ImplicitConversion) + return ACR_unbridged; + + diagnoseObjCARCConversion(*this, castRange, castType, castACTC, + castExpr, exprACTC, CCK); + return ACR_okay; +} + +/// Given that we saw an expression with the ARCUnbridgedCastTy +/// placeholder type, complain bitterly. +void Sema::diagnoseARCUnbridgedCast(Expr *e) { + // We expect the spurious ImplicitCastExpr to already have been stripped. + assert(!e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast)); + CastExpr *realCast = cast<CastExpr>(e->IgnoreParens()); + + SourceRange castRange; + QualType castType; + CheckedConversionKind CCK; + + if (CStyleCastExpr *cast = dyn_cast<CStyleCastExpr>(realCast)) { + castRange = SourceRange(cast->getLParenLoc(), cast->getRParenLoc()); + castType = cast->getTypeAsWritten(); + CCK = CCK_CStyleCast; + } else if (ExplicitCastExpr *cast = dyn_cast<ExplicitCastExpr>(realCast)) { + castRange = cast->getTypeInfoAsWritten()->getTypeLoc().getSourceRange(); + castType = cast->getTypeAsWritten(); + CCK = CCK_OtherCast; + } else { + castType = cast->getType(); + CCK = CCK_ImplicitConversion; } - - if (CCK == CCK_CStyleCast) { - // Check whether this could be fixed with a bridge cast. - SourceLocation AfterLParen = PP.getLocForEndOfToken(castRange.getBegin()); - SourceLocation NoteLoc = AfterLParen.isValid()? AfterLParen : loc; - - if (castACTC == ACTC_retainable && isAnyRetainable(exprACTC)) { - Diag(loc, diag::err_arc_cast_requires_bridge) - << 2 - << castExprType - << (castType->isBlockPointerType()? 1 : 0) - << castType - << castRange - << castExpr->getSourceRange(); - Diag(NoteLoc, diag::note_arc_bridge) - << FixItHint::CreateInsertion(AfterLParen, "__bridge "); - Diag(NoteLoc, diag::note_arc_bridge_transfer) - << castExprType - << FixItHint::CreateInsertion(AfterLParen, "__bridge_transfer "); - - return; - } - - if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) { - Diag(loc, diag::err_arc_cast_requires_bridge) - << (castExprType->isBlockPointerType()? 1 : 0) - << castExprType - << 2 - << castType - << castRange - << castExpr->getSourceRange(); - - Diag(NoteLoc, diag::note_arc_bridge) - << FixItHint::CreateInsertion(AfterLParen, "__bridge "); - Diag(NoteLoc, diag::note_arc_bridge_retained) - << castType - << FixItHint::CreateInsertion(AfterLParen, "__bridge_retained "); - return; + + ARCConversionTypeClass castACTC = + classifyTypeForARCConversion(castType.getNonReferenceType()); + + Expr *castExpr = realCast->getSubExpr(); + assert(classifyTypeForARCConversion(castExpr->getType()) == ACTC_retainable); + + diagnoseObjCARCConversion(*this, castRange, castType, castACTC, + castExpr, ACTC_retainable, CCK); +} + +/// stripARCUnbridgedCast - Given an expression of ARCUnbridgedCast +/// type, remove the placeholder cast. +Expr *Sema::stripARCUnbridgedCast(Expr *e) { + assert(e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast)); + + if (ParenExpr *pe = dyn_cast<ParenExpr>(e)) { + Expr *sub = stripARCUnbridgedCast(pe->getSubExpr()); + return new (Context) ParenExpr(pe->getLParen(), pe->getRParen(), sub); + } else if (UnaryOperator *uo = dyn_cast<UnaryOperator>(e)) { + assert(uo->getOpcode() == UO_Extension); + Expr *sub = stripARCUnbridgedCast(uo->getSubExpr()); + return new (Context) UnaryOperator(sub, UO_Extension, sub->getType(), + sub->getValueKind(), sub->getObjectKind(), + uo->getOperatorLoc()); + } else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) { + assert(!gse->isResultDependent()); + + unsigned n = gse->getNumAssocs(); + SmallVector<Expr*, 4> subExprs(n); + SmallVector<TypeSourceInfo*, 4> subTypes(n); + for (unsigned i = 0; i != n; ++i) { + subTypes[i] = gse->getAssocTypeSourceInfo(i); + Expr *sub = gse->getAssocExpr(i); + if (i == gse->getResultIndex()) + sub = stripARCUnbridgedCast(sub); + subExprs[i] = sub; } + + return new (Context) GenericSelectionExpr(Context, gse->getGenericLoc(), + gse->getControllingExpr(), + subTypes.data(), subExprs.data(), + n, gse->getDefaultLoc(), + gse->getRParenLoc(), + gse->containsUnexpandedParameterPack(), + gse->getResultIndex()); + } else { + assert(isa<ImplicitCastExpr>(e) && "bad form of unbridged cast!"); + return cast<ImplicitCastExpr>(e)->getSubExpr(); } - - Diag(loc, diag::err_arc_mismatched_cast) - << (CCK != CCK_ImplicitConversion) << srcKind << castExprType << castType - << castRange << castExpr->getSourceRange(); } bool Sema::CheckObjCARCUnavailableWeakConversion(QualType castType, @@ -2007,7 +2948,8 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, case OBC_Bridge: break; - case OBC_BridgeRetained: + case OBC_BridgeRetained: { + bool br = KnownName(*this, "CFBridgingRelease"); Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind) << 2 << FromType @@ -2018,12 +2960,14 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, Diag(BridgeKeywordLoc, diag::note_arc_bridge) << FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge"); Diag(BridgeKeywordLoc, diag::note_arc_bridge_transfer) - << FromType + << FromType << br << FixItHint::CreateReplacement(BridgeKeywordLoc, - "__bridge_transfer "); + br ? "CFBridgingRelease " + : "__bridge_transfer "); Kind = OBC_Bridge; break; + } case OBC_BridgeTransfer: // We must consume the Objective-C object produced by the cast. @@ -2047,7 +2991,8 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, SubExpr, 0, VK_RValue); break; - case OBC_BridgeTransfer: + case OBC_BridgeTransfer: { + bool br = KnownName(*this, "CFBridgingRetain"); Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind) << (FromType->isBlockPointerType()? 1 : 0) << FromType @@ -2059,12 +3004,14 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, Diag(BridgeKeywordLoc, diag::note_arc_bridge) << FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge "); Diag(BridgeKeywordLoc, diag::note_arc_bridge_retained) - << T - << FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge_retained "); + << T << br + << FixItHint::CreateReplacement(BridgeKeywordLoc, + br ? "CFBridgingRetain " : "__bridge_retained"); Kind = OBC_Bridge; break; } + } } else { Diag(LParenLoc, diag::err_arc_bridge_cast_incompatible) << FromType << T << Kind diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp index 8e8a46d..b78ea7d 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp @@ -158,3 +158,47 @@ bool ConversionFixItGenerator::tryToFixConversion(const Expr *FullExpr, return false; } + +static bool isMacroDefined(const Sema &S, StringRef Name) { + return S.PP.getMacroInfo(&S.getASTContext().Idents.get(Name)); +} + +const char *Sema::getFixItZeroInitializerForType(QualType T) const { + if (T->isScalarType()) { + // Suggest " = 0" for non-enumeration scalar types, unless we can find a + // better initializer. + if (T->isEnumeralType()) + return 0; + if ((T->isObjCObjectPointerType() || T->isBlockPointerType()) && + isMacroDefined(*this, "nil")) + return " = nil"; + if (T->isRealFloatingType()) + return " = 0.0"; + if (T->isBooleanType() && LangOpts.CPlusPlus) + return " = false"; + if (T->isPointerType() || T->isMemberPointerType()) { + if (LangOpts.CPlusPlus0x) + return " = nullptr"; + else if (isMacroDefined(*this, "NULL")) + return " = NULL"; + } + if (T->isCharType()) + return " = '\\0'"; + if (T->isWideCharType()) + return " = L'\\0'"; + if (T->isChar16Type()) + return " = u'\\0'"; + if (T->isChar32Type()) + return " = U'\\0'"; + return " = 0"; + } + + const CXXRecordDecl *RD = T->getAsCXXRecordDecl(); + if (!RD || !RD->hasDefinition()) + return 0; + if (LangOpts.CPlusPlus0x && !RD->hasUserProvidedDefaultConstructor()) + return "{}"; + if (RD->isAggregate()) + return " = {}"; + return 0; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp index 7ed3fa8..a65b41f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp @@ -21,6 +21,8 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/TypeLoc.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include <map> @@ -104,7 +106,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, // We have an array of character type with known size. However, // the size may be smaller or larger than the string we are initializing. // FIXME: Avoid truncation for 64-bit length strings. - if (S.getLangOptions().CPlusPlus) { + if (S.getLangOpts().CPlusPlus) { if (StringLiteral *SL = dyn_cast<StringLiteral>(Str)) { // For Pascal strings it's OK to strip off the terminating null character, // so the example below is valid: @@ -116,13 +118,13 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, // [dcl.init.string]p2 if (StrLength > CAT->getSize().getZExtValue()) - S.Diag(Str->getSourceRange().getBegin(), + S.Diag(Str->getLocStart(), diag::err_initializer_string_for_char_array_too_long) << Str->getSourceRange(); } else { // C99 6.7.8p14. if (StrLength-1 > CAT->getSize().getZExtValue()) - S.Diag(Str->getSourceRange().getBegin(), + S.Diag(Str->getLocStart(), diag::warn_initializer_string_for_char_array_too_long) << Str->getSourceRange(); } @@ -170,7 +172,8 @@ class InitListChecker { Sema &SemaRef; bool hadError; bool VerifyOnly; // no diagnostics, no structure building - std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic; + bool AllowBraceElision; + llvm::DenseMap<InitListExpr *, InitListExpr *> SyntacticToSemantic; InitListExpr *FullyStructuredList; void CheckImplicitInitList(const InitializedEntity &Entity, @@ -256,9 +259,12 @@ class InitListChecker { bool CheckFlexibleArrayInit(const InitializedEntity &Entity, Expr *InitExpr, FieldDecl *Field, bool TopLevelObject); + void CheckValueInitializable(const InitializedEntity &Entity); + public: InitListChecker(Sema &S, const InitializedEntity &Entity, - InitListExpr *IL, QualType &T, bool VerifyOnly); + InitListExpr *IL, QualType &T, bool VerifyOnly, + bool AllowBraceElision); bool HadError() { return hadError; } // @brief Retrieves the fully-structured initializer list used for @@ -267,11 +273,23 @@ public: }; } // end anonymous namespace +void InitListChecker::CheckValueInitializable(const InitializedEntity &Entity) { + assert(VerifyOnly && + "CheckValueInitializable is only inteded for verification mode."); + + SourceLocation Loc; + InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc, + true); + InitializationSequence InitSeq(SemaRef, Entity, Kind, 0, 0); + if (InitSeq.Failed()) + hadError = true; +} + void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field, const InitializedEntity &ParentEntity, InitListExpr *ILE, bool &RequiresSecondPass) { - SourceLocation Loc = ILE->getSourceRange().getBegin(); + SourceLocation Loc = ILE->getLocStart(); unsigned NumInits = ILE->getNumInits(); InitializedEntity MemberEntity = InitializedEntity::InitializeMember(Field, &ParentEntity); @@ -336,9 +354,9 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity, bool &RequiresSecondPass) { assert((ILE->getType() != SemaRef.Context.VoidTy) && "Should not have void type"); - SourceLocation Loc = ILE->getSourceRange().getBegin(); + SourceLocation Loc = ILE->getLocStart(); if (ILE->getSyntacticForm()) - Loc = ILE->getSyntacticForm()->getSourceRange().getBegin(); + Loc = ILE->getSyntacticForm()->getLocStart(); if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) { if (RType->getDecl()->isUnion() && @@ -400,7 +418,8 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity, ElementEntity.getKind() == InitializedEntity::EK_VectorElement) ElementEntity.setElementIndex(Init); - if (Init >= NumInits || !ILE->getInit(Init)) { + Expr *InitExpr = (Init < NumInits ? ILE->getInit(Init) : 0); + if (!InitExpr && !ILE->hasArrayFiller()) { InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc, true); InitializationSequence InitSeq(SemaRef, ElementEntity, Kind, 0, 0); @@ -444,7 +463,7 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity, } } } else if (InitListExpr *InnerILE - = dyn_cast<InitListExpr>(ILE->getInit(Init))) + = dyn_cast_or_null<InitListExpr>(InitExpr)) FillInValueInitializations(ElementEntity, InnerILE, RequiresSecondPass); } } @@ -452,8 +471,8 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity, InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, InitListExpr *IL, QualType &T, - bool VerifyOnly) - : SemaRef(S), VerifyOnly(VerifyOnly) { + bool VerifyOnly, bool AllowBraceElision) + : SemaRef(S), VerifyOnly(VerifyOnly), AllowBraceElision(AllowBraceElision) { hadError = false; unsigned newIndex = 0; @@ -527,7 +546,7 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, InitListExpr *StructuredSubobjectInitList = getStructuredSubobjectInit(ParentIList, Index, T, StructuredList, StructuredIndex, - SourceRange(ParentIList->getInit(Index)->getSourceRange().getBegin(), + SourceRange(ParentIList->getInit(Index)->getLocStart(), ParentIList->getSourceRange().getEnd())); unsigned StructuredSubobjectInitIndex = 0; @@ -537,10 +556,14 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, /*SubobjectIsDesignatorContext=*/false, Index, StructuredSubobjectInitList, StructuredSubobjectInitIndex); - unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1); - if (!VerifyOnly) { + + if (VerifyOnly) { + if (!AllowBraceElision && (T->isArrayType() || T->isRecordType())) + hadError = true; + } else { StructuredSubobjectInitList->setType(T); + unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1); // Update the structured sub-object initializer so that it's ending // range corresponds with the end of the last initializer it used. if (EndIndex < ParentIList->getNumInits()) { @@ -549,10 +572,11 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, StructuredSubobjectInitList->setRBraceLoc(EndLoc); } - // Warn about missing braces. + // Complain about missing braces. if (T->isArrayType() || T->isRecordType()) { SemaRef.Diag(StructuredSubobjectInitList->getLocStart(), - diag::warn_missing_braces) + AllowBraceElision ? diag::warn_missing_braces : + diag::err_missing_braces) << StructuredSubobjectInitList->getSourceRange() << FixItHint::CreateInsertion( StructuredSubobjectInitList->getLocStart(), "{") @@ -560,6 +584,8 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, SemaRef.PP.getLocForEndOfToken( StructuredSubobjectInitList->getLocEnd()), "}"); + if (!AllowBraceElision) + hadError = true; } } } @@ -578,7 +604,9 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true, Index, StructuredList, StructuredIndex, TopLevelObject); if (!VerifyOnly) { - QualType ExprTy = T.getNonLValueExprType(SemaRef.Context); + QualType ExprTy = T; + if (!ExprTy->isArrayType()) + ExprTy = ExprTy.getNonLValueExprType(SemaRef.Context); IList->setType(ExprTy); StructuredList->setType(ExprTy); } @@ -588,8 +616,8 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, if (Index < IList->getNumInits()) { // We have leftover initializers if (VerifyOnly) { - if (SemaRef.getLangOptions().CPlusPlus || - (SemaRef.getLangOptions().OpenCL && + if (SemaRef.getLangOpts().CPlusPlus || + (SemaRef.getLangOpts().OpenCL && IList->getType()->isVectorType())) { hadError = true; } @@ -599,7 +627,7 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, if (StructuredIndex == 1 && IsStringInit(StructuredList->getInit(0), T, SemaRef.Context)) { unsigned DK = diag::warn_excess_initializers_in_char_array_initializer; - if (SemaRef.getLangOptions().CPlusPlus) { + if (SemaRef.getLangOpts().CPlusPlus) { DK = diag::err_excess_initializers_in_char_array_initializer; hadError = true; } @@ -618,11 +646,11 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, 4; unsigned DK = diag::warn_excess_initializers; - if (SemaRef.getLangOptions().CPlusPlus) { + if (SemaRef.getLangOpts().CPlusPlus) { DK = diag::err_excess_initializers; hadError = true; } - if (SemaRef.getLangOptions().OpenCL && initKind == 1) { + if (SemaRef.getLangOpts().OpenCL && initKind == 1) { DK = diag::err_excess_initializers; hadError = true; } @@ -754,7 +782,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, // Fall through for subaggregate initialization. - } else if (SemaRef.getLangOptions().CPlusPlus) { + } else if (SemaRef.getLangOpts().CPlusPlus) { // C++ [dcl.init.aggr]p12: // All implicit type conversions (clause 4) are considered when // initializing the aggregate member with an initializer from @@ -817,7 +845,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, // subaggregate, brace elision is assumed and the initializer is // considered for the initialization of the first member of // the subaggregate. - if (!SemaRef.getLangOptions().OpenCL && + if (!SemaRef.getLangOpts().OpenCL && (ElemType->isAggregateType() || ElemType->isVectorType())) { CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList, StructuredIndex); @@ -856,7 +884,7 @@ void InitListChecker::CheckComplexType(const InitializedEntity &Entity, // This is an extension in C. (The builtin _Complex type does not exist // in the C++ standard.) - if (!SemaRef.getLangOptions().CPlusPlus && !VerifyOnly) + if (!SemaRef.getLangOpts().CPlusPlus && !VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::ext_complex_component_init) << IList->getSourceRange(); @@ -879,12 +907,13 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity, InitListExpr *StructuredList, unsigned &StructuredIndex) { if (Index >= IList->getNumInits()) { - if (!SemaRef.getLangOptions().CPlusPlus0x) { - if (!VerifyOnly) - SemaRef.Diag(IList->getLocStart(), diag::err_empty_scalar_initializer) - << IList->getSourceRange(); - hadError = true; - } + if (!VerifyOnly) + SemaRef.Diag(IList->getLocStart(), + SemaRef.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_empty_scalar_initializer : + diag::err_empty_scalar_initializer) + << IList->getSourceRange(); + hadError = !SemaRef.getLangOpts().CPlusPlus0x; ++Index; ++StructuredIndex; return; @@ -902,7 +931,7 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity, return; } else if (isa<DesignatedInitExpr>(expr)) { if (!VerifyOnly) - SemaRef.Diag(expr->getSourceRange().getBegin(), + SemaRef.Diag(expr->getLocStart(), diag::err_designator_for_scalar_init) << DeclType << expr->getSourceRange(); hadError = true; @@ -964,8 +993,7 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity, } Expr *expr = IList->getInit(Index); - if (isa<InitListExpr>(expr)) { - // FIXME: Allowed in C++11. + if (isa<InitListExpr>(expr) && !SemaRef.getLangOpts().CPlusPlus0x) { if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list) << DeclType << IList->getSourceRange(); @@ -1005,15 +1033,20 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { - if (Index >= IList->getNumInits()) - return; - const VectorType *VT = DeclType->getAs<VectorType>(); unsigned maxElements = VT->getNumElements(); unsigned numEltsInit = 0; QualType elementType = VT->getElementType(); - if (!SemaRef.getLangOptions().OpenCL) { + if (Index >= IList->getNumInits()) { + // Make sure the element type can be value-initialized. + if (VerifyOnly) + CheckValueInitializable( + InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity)); + return; + } + + if (!SemaRef.getLangOpts().OpenCL) { // If the initializing element is a vector, try to copy-initialize // instead of breaking it apart (which is doomed to failure anyway). Expr *Init = IList->getInit(Index); @@ -1055,8 +1088,11 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, for (unsigned i = 0; i < maxElements; ++i, ++numEltsInit) { // Don't attempt to go past the end of the init list - if (Index >= IList->getNumInits()) + if (Index >= IList->getNumInits()) { + if (VerifyOnly) + CheckValueInitializable(ElementEntity); break; + } ElementEntity.setElementIndex(Index); CheckSubElementType(ElementEntity, IList, elementType, Index, @@ -1098,11 +1134,13 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, } // OpenCL requires all elements to be initialized. - // FIXME: Shouldn't this set hadError to true then? - if (numEltsInit != maxElements && !VerifyOnly) - SemaRef.Diag(IList->getSourceRange().getBegin(), - diag::err_vector_incorrect_num_initializers) - << (numEltsInit < maxElements) << maxElements << numEltsInit; + if (numEltsInit != maxElements) { + if (!VerifyOnly) + SemaRef.Diag(IList->getLocStart(), + diag::err_vector_incorrect_num_initializers) + << (numEltsInit < maxElements) << maxElements << numEltsInit; + hadError = true; + } } void InitListChecker::CheckArrayType(const InitializedEntity &Entity, @@ -1223,6 +1261,14 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity, DeclType = SemaRef.Context.getConstantArrayType(elementType, maxElements, ArrayType::Normal, 0); } + if (!hadError && VerifyOnly) { + // Check if there are any members of the array that get value-initialized. + // 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)); + } } bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity, @@ -1235,7 +1281,7 @@ bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity, cast<InitListExpr>(InitExpr)->getNumInits() == 0) { // Empty flexible array init always allowed as an extension FlexArrayDiag = diag::ext_flexible_array_init; - } else if (SemaRef.getLangOptions().CPlusPlus) { + } else if (SemaRef.getLangOpts().CPlusPlus) { // Disallow flexible array init in C++; it is not required for gcc // compatibility, and it needs work to IRGen correctly in general. FlexArrayDiag = diag::err_flexible_array_init; @@ -1254,9 +1300,9 @@ bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity, } if (!VerifyOnly) { - SemaRef.Diag(InitExpr->getSourceRange().getBegin(), + SemaRef.Diag(InitExpr->getLocStart(), FlexArrayDiag) - << InitExpr->getSourceRange().getBegin(); + << InitExpr->getLocStart(); SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) << Field; } @@ -1283,15 +1329,17 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity, } if (DeclType->isUnionType() && IList->getNumInits() == 0) { - if (!VerifyOnly) { - // Value-initialize the first named member of the union. - RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl(); - for (RecordDecl::field_iterator FieldEnd = RD->field_end(); - Field != FieldEnd; ++Field) { - if (Field->getDeclName()) { + // Value-initialize the first named member of the union. + RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl(); + for (RecordDecl::field_iterator FieldEnd = RD->field_end(); + Field != FieldEnd; ++Field) { + if (Field->getDeclName()) { + if (VerifyOnly) + CheckValueInitializable( + InitializedEntity::InitializeMember(*Field, &Entity)); + else StructuredList->setInitializedFieldInUnion(*Field); - break; - } + break; } } return; @@ -1394,6 +1442,17 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity, } } + // Check that any remaining fields can be value-initialized. + if (VerifyOnly && Field != FieldEnd && !DeclType->isUnionType() && + !Field->getType()->isIncompleteArrayType()) { + // FIXME: Should check for holes left by designated initializers too. + for (; Field != FieldEnd && !hadError; ++Field) { + if (!Field->isUnnamedBitfield()) + CheckValueInitializable( + InitializedEntity::InitializeMember(*Field, &Entity)); + } + } + if (Field == FieldEnd || !Field->getType()->isIncompleteArrayType() || Index >= IList->getNumInits()) return; @@ -1454,7 +1513,8 @@ static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField, IdentifierInfo *FieldName) { assert(AnonField->isAnonymousStructOrUnion()); Decl *NextDecl = AnonField->getNextDeclInContext(); - while (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(NextDecl)) { + while (IndirectFieldDecl *IF = + dyn_cast_or_null<IndirectFieldDecl>(NextDecl)) { if (FieldName && FieldName == IF->getAnonField()->getIdentifier()) return IF; NextDecl = NextDecl->getNextDeclInContext(); @@ -1474,6 +1534,26 @@ static DesignatedInitExpr *CloneDesignatedInitExpr(Sema &SemaRef, DIE->usesGNUSyntax(), DIE->getInit()); } +namespace { + +// Callback to only accept typo corrections that are for field members of +// the given struct or union. +class FieldInitializerValidatorCCC : public CorrectionCandidateCallback { + public: + explicit FieldInitializerValidatorCCC(RecordDecl *RD) + : Record(RD) {} + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>(); + return FD && FD->getDeclContext()->getRedeclContext()->Equals(Record); + } + + private: + RecordDecl *Record; +}; + +} + /// @brief Check the well-formedness of a C99 designated initializer. /// /// Determines whether the designated initializer @p DIE, which @@ -1552,7 +1632,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // Determine the structural initializer list that corresponds to the // current subobject. - StructuredList = IsFirstDesignator? SyntacticToSemantic[IList] + StructuredList = IsFirstDesignator? SyntacticToSemantic.lookup(IList) : getStructuredSubobjectInit(IList, Index, CurrentObjectType, StructuredList, StructuredIndex, SourceRange(D->getStartLocation(), @@ -1577,7 +1657,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, Loc = D->getFieldLoc(); if (!VerifyOnly) SemaRef.Diag(Loc, diag::err_field_designator_non_aggr) - << SemaRef.getLangOptions().CPlusPlus << CurrentObjectType; + << SemaRef.getLangOpts().CPlusPlus << CurrentObjectType; ++Index; return true; } @@ -1632,19 +1712,17 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, if (Lookup.first == Lookup.second) { // Name lookup didn't find anything. Determine whether this // was a typo for another field name. - LookupResult R(SemaRef, FieldName, D->getFieldLoc(), - Sema::LookupMemberName); + FieldInitializerValidatorCCC Validator(RT->getDecl()); TypoCorrection Corrected = SemaRef.CorrectTypo( DeclarationNameInfo(FieldName, D->getFieldLoc()), - Sema::LookupMemberName, /*Scope=*/NULL, /*SS=*/NULL, - RT->getDecl(), false, Sema::CTC_NoKeywords); - if ((ReplacementField = Corrected.getCorrectionDeclAs<FieldDecl>()) && - ReplacementField->getDeclContext()->getRedeclContext() - ->Equals(RT->getDecl())) { + Sema::LookupMemberName, /*Scope=*/0, /*SS=*/0, Validator, + RT->getDecl()); + if (Corrected) { std::string CorrectedStr( - Corrected.getAsString(SemaRef.getLangOptions())); + Corrected.getAsString(SemaRef.getLangOpts())); std::string CorrectedQuotedStr( - Corrected.getQuoted(SemaRef.getLangOptions())); + Corrected.getQuoted(SemaRef.getLangOpts())); + ReplacementField = Corrected.getCorrectionDeclAs<FieldDecl>(); SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown_suggest) << FieldName << CurrentObjectType << CorrectedQuotedStr @@ -1740,7 +1818,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, !isa<StringLiteral>(DIE->getInit())) { // The initializer is not an initializer list. if (!VerifyOnly) { - SemaRef.Diag(DIE->getInit()->getSourceRange().getBegin(), + SemaRef.Diag(DIE->getInit()->getLocStart(), diag::err_flexible_array_init_needs_braces) << DIE->getInit()->getSourceRange(); SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) @@ -1881,7 +1959,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned()); if (DesignatedEndIndex >= MaxElements) { if (!VerifyOnly) - SemaRef.Diag(IndexExpr->getSourceRange().getBegin(), + SemaRef.Diag(IndexExpr->getLocStart(), diag::err_array_designator_too_large) << DesignatedEndIndex.toString(10) << MaxElements.toString(10) << IndexExpr->getSourceRange(); @@ -1968,7 +2046,7 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, return 0; // No structured list in verification-only mode. Expr *ExistingInit = 0; if (!StructuredList) - ExistingInit = SyntacticToSemantic[IList]; + ExistingInit = SyntacticToSemantic.lookup(IList); else if (StructuredIndex < StructuredList->getNumInits()) ExistingInit = StructuredList->getInit(StructuredIndex); @@ -1990,7 +2068,7 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, SemaRef.Diag(InitRange.getBegin(), diag::warn_subobject_initializer_overrides) << InitRange; - SemaRef.Diag(ExistingInit->getSourceRange().getBegin(), + SemaRef.Diag(ExistingInit->getLocStart(), diag::note_previous_initializer) << /*FIXME:has side effects=*/0 << ExistingInit->getSourceRange(); @@ -2001,7 +2079,10 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, InitRange.getBegin(), 0, 0, InitRange.getEnd()); - Result->setType(CurrentObjectType.getNonLValueExprType(SemaRef.Context)); + QualType ResultType = CurrentObjectType; + if (!ResultType->isArrayType()) + ResultType = ResultType.getNonLValueExprType(SemaRef.Context); + Result->setType(ResultType); // Pre-allocate storage for the structured initializer list. unsigned NumElements = 0; @@ -2063,10 +2144,10 @@ void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList, if (Expr *PrevInit = StructuredList->updateInit(SemaRef.Context, StructuredIndex, expr)) { // This initializer overwrites a previous initializer. Warn. - SemaRef.Diag(expr->getSourceRange().getBegin(), + SemaRef.Diag(expr->getLocStart(), diag::warn_initializer_overrides) << expr->getSourceRange(); - SemaRef.Diag(PrevInit->getSourceRange().getBegin(), + SemaRef.Diag(PrevInit->getLocStart(), diag::note_previous_initializer) << /*FIXME:has side effects=*/0 << PrevInit->getSourceRange(); @@ -2076,26 +2157,27 @@ void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList, } /// Check that the given Index expression is a valid array designator -/// value. This is essentailly just a wrapper around +/// value. This is essentially just a wrapper around /// VerifyIntegerConstantExpression that also checks for negative values /// and produces a reasonable diagnostic if there is a -/// failure. Returns true if there was an error, false otherwise. If -/// everything went okay, Value will receive the value of the constant -/// expression. -static bool +/// failure. Returns the index expression, possibly with an implicit cast +/// added, on success. If everything went okay, Value will receive the +/// value of the constant expression. +static ExprResult CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) { - SourceLocation Loc = Index->getSourceRange().getBegin(); + SourceLocation Loc = Index->getLocStart(); // Make sure this is an integer constant expression. - if (S.VerifyIntegerConstantExpression(Index, &Value)) - return true; + ExprResult Result = S.VerifyIntegerConstantExpression(Index, &Value); + if (Result.isInvalid()) + return Result; if (Value.isSigned() && Value.isNegative()) return S.Diag(Loc, diag::err_array_designator_negative) << Value.toString(10) << Index->getSourceRange(); Value.setIsUnsigned(true); - return false; + return Result; } ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, @@ -2120,9 +2202,9 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, case Designator::ArrayDesignator: { Expr *Index = static_cast<Expr *>(D.getArrayIndex()); llvm::APSInt IndexValue; - if (!Index->isTypeDependent() && - !Index->isValueDependent() && - CheckArrayDesignatorExpr(*this, Index, IndexValue)) + if (!Index->isTypeDependent() && !Index->isValueDependent()) + Index = CheckArrayDesignatorExpr(*this, Index, IndexValue).take(); + if (!Index) Invalid = true; else { Designators.push_back(ASTDesignator(InitExpressions.size(), @@ -2142,10 +2224,13 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, StartIndex->isValueDependent(); bool EndDependent = EndIndex->isTypeDependent() || EndIndex->isValueDependent(); - if ((!StartDependent && - CheckArrayDesignatorExpr(*this, StartIndex, StartValue)) || - (!EndDependent && - CheckArrayDesignatorExpr(*this, EndIndex, EndValue))) + if (!StartDependent) + StartIndex = + CheckArrayDesignatorExpr(*this, StartIndex, StartValue).take(); + if (!EndDependent) + EndIndex = CheckArrayDesignatorExpr(*this, EndIndex, EndValue).take(); + + if (!StartIndex || !EndIndex) Invalid = true; else { // Make sure we're comparing values with the same bit width. @@ -2187,10 +2272,7 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, InitExpressions.data(), InitExpressions.size(), Loc, GNUSyntax, Init.takeAs<Expr>()); - if (getLangOptions().CPlusPlus) - Diag(DIE->getLocStart(), diag::ext_designated_init_cxx) - << DIE->getSourceRange(); - else if (!getLangOptions().C99) + if (!getLangOpts().C99) Diag(DIE->getLocStart(), diag::ext_designated_init) << DIE->getSourceRange(); @@ -2244,6 +2326,9 @@ DeclarationName InitializedEntity::getName() const { case EK_Member: return VariableOrMember->getDeclName(); + case EK_LambdaCapture: + return Capture.Var->getDeclName(); + case EK_Result: case EK_Exception: case EK_New: @@ -2257,8 +2342,7 @@ DeclarationName InitializedEntity::getName() const { return DeclarationName(); } - // Silence GCC warning - return DeclarationName(); + llvm_unreachable("Invalid EntityKind!"); } DeclaratorDecl *InitializedEntity::getDecl() const { @@ -2280,11 +2364,11 @@ DeclaratorDecl *InitializedEntity::getDecl() const { case EK_VectorElement: case EK_ComplexElement: case EK_BlockElement: + case EK_LambdaCapture: return 0; } - // Silence GCC warning - return 0; + llvm_unreachable("Invalid EntityKind!"); } bool InitializedEntity::allowsNRVO() const { @@ -2304,6 +2388,7 @@ bool InitializedEntity::allowsNRVO() const { case EK_VectorElement: case EK_ComplexElement: case EK_BlockElement: + case EK_LambdaCapture: break; } @@ -2329,15 +2414,19 @@ void InitializationSequence::Step::Destroy() { case SK_QualificationConversionLValue: case SK_ListInitialization: case SK_ListConstructorCall: + case SK_UnwrapInitList: + case SK_RewrapInitList: case SK_ConstructorInitialization: case SK_ZeroInitialization: case SK_CAssignment: case SK_StringInit: case SK_ObjCObjectConversion: case SK_ArrayInit: + case SK_ParenthesizedArrayInit: case SK_PassByIndirectCopyRestore: case SK_PassByIndirectRestore: case SK_ProduceObjCObject: + case SK_StdInitializerList: break; case SK_ConversionSequence: @@ -2373,186 +2462,35 @@ bool InitializationSequence::isAmbiguous() const { case FK_ArrayTypeMismatch: case FK_NonConstantArrayInit: case FK_ListInitializationFailed: + case FK_VariableLengthArrayHasInitializer: + case FK_PlaceholderType: + case FK_InitListElementCopyFailure: + case FK_ExplicitConstructor: return false; case FK_ReferenceInitOverloadFailed: case FK_UserConversionOverloadFailed: case FK_ConstructorOverloadFailed: + case FK_ListConstructorOverloadFailed: return FailedOverloadResult == OR_Ambiguous; } - return false; + llvm_unreachable("Invalid EntityKind!"); } bool InitializationSequence::isConstructorInitialization() const { return !Steps.empty() && Steps.back().Kind == SK_ConstructorInitialization; } -bool InitializationSequence::endsWithNarrowing(ASTContext &Ctx, - const Expr *Initializer, - bool *isInitializerConstant, - APValue *ConstantValue) const { - if (Steps.empty() || Initializer->isValueDependent()) - return false; - - const Step &LastStep = Steps.back(); - if (LastStep.Kind != SK_ConversionSequence) - return false; - - const ImplicitConversionSequence &ICS = *LastStep.ICS; - const StandardConversionSequence *SCS = NULL; - switch (ICS.getKind()) { - case ImplicitConversionSequence::StandardConversion: - SCS = &ICS.Standard; - break; - case ImplicitConversionSequence::UserDefinedConversion: - SCS = &ICS.UserDefined.After; - break; - case ImplicitConversionSequence::AmbiguousConversion: - case ImplicitConversionSequence::EllipsisConversion: - case ImplicitConversionSequence::BadConversion: - return false; - } - - // Check if SCS represents a narrowing conversion, according to C++0x - // [dcl.init.list]p7: - // - // A narrowing conversion is an implicit conversion ... - ImplicitConversionKind PossibleNarrowing = SCS->Second; - QualType FromType = SCS->getToType(0); - QualType ToType = SCS->getToType(1); - switch (PossibleNarrowing) { - // * from a floating-point type to an integer type, or - // - // * from an integer type or unscoped enumeration type to a floating-point - // type, except where the source is a constant expression and the actual - // value after conversion will fit into the target type and will produce - // the original value when converted back to the original type, or - case ICK_Floating_Integral: - if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) { - *isInitializerConstant = false; - return true; - } else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) { - llvm::APSInt IntConstantValue; - if (Initializer && - Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) { - // Convert the integer to the floating type. - llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType)); - Result.convertFromAPInt(IntConstantValue, IntConstantValue.isSigned(), - llvm::APFloat::rmNearestTiesToEven); - // And back. - llvm::APSInt ConvertedValue = IntConstantValue; - bool ignored; - Result.convertToInteger(ConvertedValue, - llvm::APFloat::rmTowardZero, &ignored); - // If the resulting value is different, this was a narrowing conversion. - if (IntConstantValue != ConvertedValue) { - *isInitializerConstant = true; - *ConstantValue = APValue(IntConstantValue); - return true; - } - } else { - // Variables are always narrowings. - *isInitializerConstant = false; - return true; - } - } - return false; - - // * from long double to double or float, or from double to float, except - // where the source is a constant expression and the actual value after - // conversion is within the range of values that can be represented (even - // if it cannot be represented exactly), or - case ICK_Floating_Conversion: - if (1 == Ctx.getFloatingTypeOrder(FromType, ToType)) { - // FromType is larger than ToType. - Expr::EvalResult InitializerValue; - // FIXME: Check whether Initializer is a constant expression according - // to C++0x [expr.const], rather than just whether it can be folded. - if (Initializer->Evaluate(InitializerValue, Ctx) && - !InitializerValue.HasSideEffects && InitializerValue.Val.isFloat()) { - // Constant! (Except for FIXME above.) - llvm::APFloat FloatVal = InitializerValue.Val.getFloat(); - // Convert the source value into the target type. - bool ignored; - llvm::APFloat::opStatus ConvertStatus = FloatVal.convert( - Ctx.getFloatTypeSemantics(ToType), - llvm::APFloat::rmNearestTiesToEven, &ignored); - // If there was no overflow, the source value is within the range of - // values that can be represented. - if (ConvertStatus & llvm::APFloat::opOverflow) { - *isInitializerConstant = true; - *ConstantValue = InitializerValue.Val; - return true; - } - } else { - *isInitializerConstant = false; - return true; - } - } - return false; - - // * from an integer type or unscoped enumeration type to an integer type - // that cannot represent all the values of the original type, except where - // the source is a constant expression and the actual value after - // conversion will fit into the target type and will produce the original - // value when converted back to the original type. - case ICK_Boolean_Conversion: // Bools are integers too. - if (!FromType->isIntegralOrUnscopedEnumerationType()) { - // Boolean conversions can be from pointers and pointers to members - // [conv.bool], and those aren't considered narrowing conversions. - return false; - } // Otherwise, fall through to the integral case. - case ICK_Integral_Conversion: { - assert(FromType->isIntegralOrUnscopedEnumerationType()); - assert(ToType->isIntegralOrUnscopedEnumerationType()); - const bool FromSigned = FromType->isSignedIntegerOrEnumerationType(); - const unsigned FromWidth = Ctx.getIntWidth(FromType); - const bool ToSigned = ToType->isSignedIntegerOrEnumerationType(); - const unsigned ToWidth = Ctx.getIntWidth(ToType); - - if (FromWidth > ToWidth || - (FromWidth == ToWidth && FromSigned != ToSigned)) { - // Not all values of FromType can be represented in ToType. - llvm::APSInt InitializerValue; - if (Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) { - *isInitializerConstant = true; - *ConstantValue = APValue(InitializerValue); - - // Add a bit to the InitializerValue so we don't have to worry about - // signed vs. unsigned comparisons. - InitializerValue = InitializerValue.extend( - InitializerValue.getBitWidth() + 1); - // Convert the initializer to and from the target width and signed-ness. - llvm::APSInt ConvertedValue = InitializerValue; - ConvertedValue = ConvertedValue.trunc(ToWidth); - ConvertedValue.setIsSigned(ToSigned); - ConvertedValue = ConvertedValue.extend(InitializerValue.getBitWidth()); - ConvertedValue.setIsSigned(InitializerValue.isSigned()); - // If the result is different, this was a narrowing conversion. - return ConvertedValue != InitializerValue; - } else { - // Variables are always narrowings. - *isInitializerConstant = false; - return true; - } - } - return false; - } - - default: - // Other kinds of conversions are not narrowings. - return false; - } -} - -void InitializationSequence::AddAddressOverloadResolutionStep( - FunctionDecl *Function, - DeclAccessPair Found) { +void +InitializationSequence +::AddAddressOverloadResolutionStep(FunctionDecl *Function, + DeclAccessPair Found, + bool HadMultipleCandidates) { Step S; S.Kind = SK_ResolveAddressOfOverloadedFunction; S.Type = Function->getType(); - S.Function.HadMultipleCandidates = false; + S.Function.HadMultipleCandidates = HadMultipleCandidates; S.Function.Function = Function; S.Function.FoundDecl = Found; Steps.push_back(S); @@ -2565,7 +2503,6 @@ void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType, case VK_RValue: S.Kind = SK_CastDerivedToBaseRValue; break; case VK_XValue: S.Kind = SK_CastDerivedToBaseXValue; break; case VK_LValue: S.Kind = SK_CastDerivedToBaseLValue; break; - default: llvm_unreachable("No such category"); } S.Type = BaseType; Steps.push_back(S); @@ -2586,13 +2523,15 @@ void InitializationSequence::AddExtraneousCopyToTemporary(QualType T) { Steps.push_back(S); } -void InitializationSequence::AddUserConversionStep(FunctionDecl *Function, - DeclAccessPair FoundDecl, - QualType T) { +void +InitializationSequence::AddUserConversionStep(FunctionDecl *Function, + DeclAccessPair FoundDecl, + QualType T, + bool HadMultipleCandidates) { Step S; S.Kind = SK_UserConversion; S.Type = T; - S.Function.HadMultipleCandidates = false; + S.Function.HadMultipleCandidates = HadMultipleCandidates; S.Function.Function = Function; S.Function.FoundDecl = FoundDecl; Steps.push_back(S); @@ -2635,14 +2574,17 @@ void InitializationSequence::AddListInitializationStep(QualType T) { } void -InitializationSequence::AddConstructorInitializationStep( - CXXConstructorDecl *Constructor, - AccessSpecifier Access, - QualType T) { +InitializationSequence +::AddConstructorInitializationStep(CXXConstructorDecl *Constructor, + AccessSpecifier Access, + QualType T, + bool HadMultipleCandidates, + bool FromInitList, bool AsInitList) { Step S; - S.Kind = SK_ConstructorInitialization; + S.Kind = FromInitList && !AsInitList ? SK_ListConstructorCall + : SK_ConstructorInitialization; S.Type = T; - S.Function.HadMultipleCandidates = false; + S.Function.HadMultipleCandidates = HadMultipleCandidates; S.Function.Function = Constructor; S.Function.FoundDecl = DeclAccessPair::make(Constructor, Access); Steps.push_back(S); @@ -2683,6 +2625,13 @@ void InitializationSequence::AddArrayInitStep(QualType T) { Steps.push_back(S); } +void InitializationSequence::AddParenthesizedArrayInitStep(QualType T) { + Step S; + S.Kind = SK_ParenthesizedArrayInit; + S.Type = T; + Steps.push_back(S); +} + void InitializationSequence::AddPassByIndirectCopyRestoreStep(QualType type, bool shouldCopy) { Step s; @@ -2699,6 +2648,28 @@ void InitializationSequence::AddProduceObjCObjectStep(QualType T) { Steps.push_back(S); } +void InitializationSequence::AddStdInitializerListConstructionStep(QualType T) { + Step S; + S.Kind = SK_StdInitializerList; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::RewrapReferenceInitList(QualType T, + InitListExpr *Syntactic) { + assert(Syntactic->getNumInits() == 1 && + "Can only rewrap trivial init lists."); + Step S; + S.Kind = SK_UnwrapInitList; + S.Type = Syntactic->getInit(0)->getType(); + Steps.insert(Steps.begin(), S); + + S.Kind = SK_RewrapInitList; + S.Type = T; + S.WrappingSyntacticList = Syntactic; + Steps.push_back(S); +} + void InitializationSequence::SetOverloadFailure(FailureKind Failure, OverloadingResult Result) { setSequenceKind(FailedSequence); @@ -2713,7 +2684,7 @@ void InitializationSequence::SetOverloadFailure(FailureKind Failure, static void MaybeProduceObjCObject(Sema &S, InitializationSequence &Sequence, const InitializedEntity &Entity) { - if (!S.getLangOptions().ObjCAutoRefCount) return; + if (!S.getLangOpts().ObjCAutoRefCount) return; /// When initializing a parameter, produce the value if it's marked /// __attribute__((ns_consumed)). @@ -2737,6 +2708,386 @@ static void MaybeProduceObjCObject(Sema &S, } } +/// \brief When initializing from init list via constructor, deal with the +/// empty init list and std::initializer_list special cases. +/// +/// \return True if this was a special case, false otherwise. +static bool TryListConstructionSpecialCases(Sema &S, + InitListExpr *List, + CXXRecordDecl *DestRecordDecl, + QualType DestType, + InitializationSequence &Sequence) { + // C++11 [dcl.init.list]p3: + // List-initialization of an object or reference of type T is defined as + // follows: + // - If T is an aggregate, aggregate initialization is performed. + if (DestType->isAggregateType()) + return false; + + // - Otherwise, if the initializer list has no elements and T is a class + // type with a default constructor, the object is value-initialized. + if (List->getNumInits() == 0) { + if (CXXConstructorDecl *DefaultConstructor = + S.LookupDefaultConstructor(DestRecordDecl)) { + if (DefaultConstructor->isDeleted() || + S.isFunctionConsideredUnavailable(DefaultConstructor)) { + // Fake an overload resolution failure. + OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); + DeclAccessPair FoundDecl = DeclAccessPair::make(DefaultConstructor, + DefaultConstructor->getAccess()); + if (FunctionTemplateDecl *ConstructorTmpl = + dyn_cast<FunctionTemplateDecl>(DefaultConstructor)) + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + /*ExplicitArgs*/ 0, + ArrayRef<Expr*>(), CandidateSet, + /*SuppressUserConversions*/ false); + else + S.AddOverloadCandidate(DefaultConstructor, FoundDecl, + ArrayRef<Expr*>(), CandidateSet, + /*SuppressUserConversions*/ false); + Sequence.SetOverloadFailure( + InitializationSequence::FK_ListConstructorOverloadFailed, + OR_Deleted); + } else + Sequence.AddConstructorInitializationStep(DefaultConstructor, + DefaultConstructor->getAccess(), + DestType, + /*MultipleCandidates=*/false, + /*FromInitList=*/true, + /*AsInitList=*/false); + return true; + } + } + + // - Otherwise, if T is a specialization of std::initializer_list, [...] + QualType E; + if (S.isStdInitializerList(DestType, &E)) { + // Check that each individual element can be copy-constructed. But since we + // have no place to store further information, we'll recalculate everything + // later. + InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary( + S.Context.getConstantArrayType(E, + llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()), + List->getNumInits()), + ArrayType::Normal, 0)); + InitializedEntity Element = InitializedEntity::InitializeElement(S.Context, + 0, HiddenArray); + for (unsigned i = 0, n = List->getNumInits(); i < n; ++i) { + Element.setElementIndex(i); + if (!S.CanPerformCopyInitialization(Element, List->getInit(i))) { + Sequence.SetFailed( + InitializationSequence::FK_InitListElementCopyFailure); + return true; + } + } + Sequence.AddStdInitializerListConstructionStep(DestType); + return true; + } + + // Not a special case. + return false; +} + +static OverloadingResult +ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet &CandidateSet, + DeclContext::lookup_iterator Con, + DeclContext::lookup_iterator ConEnd, + OverloadCandidateSet::iterator &Best, + bool CopyInitializing, bool AllowExplicit, + bool OnlyListConstructors, bool InitListSyntax) { + CandidateSet.clear(); + + for (; Con != ConEnd; ++Con) { + NamedDecl *D = *Con; + DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); + bool SuppressUserConversions = false; + + // Find the constructor (which may be a template). + CXXConstructorDecl *Constructor = 0; + FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D); + if (ConstructorTmpl) + Constructor = cast<CXXConstructorDecl>( + ConstructorTmpl->getTemplatedDecl()); + else { + Constructor = cast<CXXConstructorDecl>(D); + + // If we're performing copy initialization using a copy constructor, we + // suppress user-defined conversions on the arguments. We do the same for + // move constructors. + if ((CopyInitializing || (InitListSyntax && NumArgs == 1)) && + Constructor->isCopyOrMoveConstructor()) + SuppressUserConversions = true; + } + + if (!Constructor->isInvalidDecl() && + (AllowExplicit || !Constructor->isExplicit()) && + (!OnlyListConstructors || S.isInitListConstructor(Constructor))) { + if (ConstructorTmpl) + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + /*ExplicitArgs*/ 0, + llvm::makeArrayRef(Args, NumArgs), + CandidateSet, SuppressUserConversions); + else { + // C++ [over.match.copy]p1: + // - When initializing a temporary to be bound to the first parameter + // of a constructor that takes a reference to possibly cv-qualified + // T as its first argument, called with a single argument in the + // context of direct-initialization, explicit conversion functions + // are also considered. + bool AllowExplicitConv = AllowExplicit && !CopyInitializing && + NumArgs == 1 && + Constructor->isCopyOrMoveConstructor(); + S.AddOverloadCandidate(Constructor, FoundDecl, + llvm::makeArrayRef(Args, NumArgs), CandidateSet, + SuppressUserConversions, + /*PartialOverloading=*/false, + /*AllowExplicit=*/AllowExplicitConv); + } + } + } + + // Perform overload resolution and return the result. + return CandidateSet.BestViableFunction(S, DeclLoc, Best); +} + +/// \brief Attempt initialization by constructor (C++ [dcl.init]), which +/// enumerates the constructors of the initialized entity and performs overload +/// resolution to select the best. +/// If InitListSyntax is true, this is list-initialization of a non-aggregate +/// class type. +static void TryConstructorInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr **Args, unsigned NumArgs, + QualType DestType, + InitializationSequence &Sequence, + bool InitListSyntax = false) { + assert((!InitListSyntax || (NumArgs == 1 && isa<InitListExpr>(Args[0]))) && + "InitListSyntax must come with a single initializer list argument."); + + // Check constructor arguments for self reference. + if (DeclaratorDecl *DD = Entity.getDecl()) + // Parameters arguments are occassionially constructed with itself, + // for instance, in recursive functions. Skip them. + if (!isa<ParmVarDecl>(DD)) + for (unsigned i = 0; i < NumArgs; ++i) + S.CheckSelfReference(DD, Args[i]); + + // The type we're constructing needs to be complete. + if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) { + Sequence.setIncompleteTypeFailure(DestType); + return; + } + + const RecordType *DestRecordType = DestType->getAs<RecordType>(); + assert(DestRecordType && "Constructor initialization requires record type"); + CXXRecordDecl *DestRecordDecl + = cast<CXXRecordDecl>(DestRecordType->getDecl()); + + if (InitListSyntax && + TryListConstructionSpecialCases(S, cast<InitListExpr>(Args[0]), + DestRecordDecl, DestType, Sequence)) + return; + + // Build the candidate set directly in the initialization sequence + // structure, so that it will persist if we fail. + OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); + + // Determine whether we are allowed to call explicit constructors or + // explicit conversion operators. + bool AllowExplicit = Kind.AllowExplicit() || InitListSyntax; + bool CopyInitialization = Kind.getKind() == InitializationKind::IK_Copy; + + // - Otherwise, if T is a class type, constructors are considered. The + // applicable constructors are enumerated, and the best one is chosen + // through overload resolution. + DeclContext::lookup_iterator ConStart, ConEnd; + llvm::tie(ConStart, ConEnd) = S.LookupConstructors(DestRecordDecl); + + OverloadingResult Result = OR_No_Viable_Function; + OverloadCandidateSet::iterator Best; + bool AsInitializerList = false; + + // C++11 [over.match.list]p1: + // When objects of non-aggregate type T are list-initialized, overload + // resolution selects the constructor in two phases: + // - Initially, the candidate functions are the initializer-list + // constructors of the class T and the argument list consists of the + // initializer list as a single argument. + if (InitListSyntax) { + AsInitializerList = true; + Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs, + CandidateSet, ConStart, ConEnd, Best, + CopyInitialization, AllowExplicit, + /*OnlyListConstructor=*/true, + InitListSyntax); + + // Time to unwrap the init list. + InitListExpr *ILE = cast<InitListExpr>(Args[0]); + Args = ILE->getInits(); + NumArgs = ILE->getNumInits(); + } + + // C++11 [over.match.list]p1: + // - If no viable initializer-list constructor is found, overload resolution + // is performed again, where the candidate functions are all the + // constructors of the class T nad the argument list consists of the + // elements of the initializer list. + if (Result == OR_No_Viable_Function) { + AsInitializerList = false; + Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs, + CandidateSet, ConStart, ConEnd, Best, + CopyInitialization, AllowExplicit, + /*OnlyListConstructors=*/false, + InitListSyntax); + } + if (Result) { + Sequence.SetOverloadFailure(InitListSyntax ? + InitializationSequence::FK_ListConstructorOverloadFailed : + InitializationSequence::FK_ConstructorOverloadFailed, + Result); + return; + } + + // C++0x [dcl.init]p6: + // If a program calls for the default initialization of an object + // of a const-qualified type T, T shall be a class type with a + // user-provided default constructor. + if (Kind.getKind() == InitializationKind::IK_Default && + Entity.getType().isConstQualified() && + cast<CXXConstructorDecl>(Best->Function)->isImplicit()) { + Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); + return; + } + + // C++11 [over.match.list]p1: + // In copy-list-initialization, if an explicit constructor is chosen, the + // initializer is ill-formed. + CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function); + if (InitListSyntax && !Kind.AllowExplicit() && CtorDecl->isExplicit()) { + Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor); + return; + } + + // Add the constructor initialization step. Any cv-qualification conversion is + // subsumed by the initialization. + bool HadMultipleCandidates = (CandidateSet.size() > 1); + Sequence.AddConstructorInitializationStep(CtorDecl, + Best->FoundDecl.getAccess(), + DestType, HadMultipleCandidates, + InitListSyntax, AsInitializerList); +} + +static bool +ResolveOverloadedFunctionForReferenceBinding(Sema &S, + Expr *Initializer, + QualType &SourceType, + QualType &UnqualifiedSourceType, + QualType UnqualifiedTargetType, + InitializationSequence &Sequence) { + if (S.Context.getCanonicalType(UnqualifiedSourceType) == + S.Context.OverloadTy) { + DeclAccessPair Found; + bool HadMultipleCandidates = false; + if (FunctionDecl *Fn + = S.ResolveAddressOfOverloadedFunction(Initializer, + UnqualifiedTargetType, + false, Found, + &HadMultipleCandidates)) { + Sequence.AddAddressOverloadResolutionStep(Fn, Found, + HadMultipleCandidates); + SourceType = Fn->getType(); + UnqualifiedSourceType = SourceType.getUnqualifiedType(); + } else if (!UnqualifiedTargetType->isRecordType()) { + Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); + return true; + } + } + return false; +} + +static void TryReferenceInitializationCore(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr *Initializer, + QualType cv1T1, QualType T1, + Qualifiers T1Quals, + QualType cv2T2, QualType T2, + Qualifiers T2Quals, + InitializationSequence &Sequence); + +static void TryListInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + InitListExpr *InitList, + InitializationSequence &Sequence); + +/// \brief Attempt list initialization of a reference. +static void TryReferenceListInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + InitListExpr *InitList, + InitializationSequence &Sequence) +{ + // First, catch C++03 where this isn't possible. + if (!S.getLangOpts().CPlusPlus0x) { + Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList); + return; + } + + QualType DestType = Entity.getType(); + QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType(); + Qualifiers T1Quals; + QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals); + + // Reference initialization via an initializer list works thus: + // If the initializer list consists of a single element that is + // reference-related to the referenced type, bind directly to that element + // (possibly creating temporaries). + // Otherwise, initialize a temporary with the initializer list and + // bind to that. + if (InitList->getNumInits() == 1) { + Expr *Initializer = InitList->getInit(0); + QualType cv2T2 = Initializer->getType(); + Qualifiers T2Quals; + QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals); + + // If this fails, creating a temporary wouldn't work either. + if (ResolveOverloadedFunctionForReferenceBinding(S, Initializer, cv2T2, T2, + T1, Sequence)) + return; + + SourceLocation DeclLoc = Initializer->getLocStart(); + bool dummy1, dummy2, dummy3; + Sema::ReferenceCompareResult RefRelationship + = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, dummy1, + dummy2, dummy3); + if (RefRelationship >= Sema::Ref_Related) { + // Try to bind the reference here. + TryReferenceInitializationCore(S, Entity, Kind, Initializer, cv1T1, T1, + T1Quals, cv2T2, T2, T2Quals, Sequence); + if (Sequence) + Sequence.RewrapReferenceInitList(cv1T1, InitList); + return; + } + } + + // Not reference-related. Create a temporary and bind to that. + InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1); + + TryListInitialization(S, TempEntity, Kind, InitList, Sequence); + if (Sequence) { + if (DestType->isRValueReferenceType() || + (T1Quals.hasConst() && !T1Quals.hasVolatile())) + Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true); + else + Sequence.SetFailed( + InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary); + } +} + /// \brief Attempt list initialization (C++0x [dcl.init.list]) static void TryListInitialization(Sema &S, const InitializedEntity &Entity, @@ -2747,23 +3098,40 @@ static void TryListInitialization(Sema &S, // C++ doesn't allow scalar initialization with more than one argument. // But C99 complex numbers are scalars and it makes sense there. - if (S.getLangOptions().CPlusPlus && DestType->isScalarType() && + if (S.getLangOpts().CPlusPlus && DestType->isScalarType() && !DestType->isAnyComplexType() && InitList->getNumInits() > 1) { Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar); return; } - // FIXME: C++0x defines behavior for these two cases. if (DestType->isReferenceType()) { - Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList); + TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence); return; } - if (DestType->isRecordType() && !DestType->isAggregateType()) { - Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType); - return; + if (DestType->isRecordType()) { + if (S.RequireCompleteType(InitList->getLocStart(), DestType, S.PDiag())) { + Sequence.setIncompleteTypeFailure(DestType); + return; + } + + if (!DestType->isAggregateType()) { + if (S.getLangOpts().CPlusPlus0x) { + Expr *Arg = InitList; + // A direct-initializer is not list-syntax, i.e. there's no special + // treatment of "A a({1, 2});". + TryConstructorInitialization(S, Entity, Kind, &Arg, 1, DestType, + Sequence, + Kind.getKind() != InitializationKind::IK_Direct); + } else + Sequence.SetFailed( + InitializationSequence::FK_InitListBadDestinationType); + return; + } } InitListChecker CheckInitList(S, Entity, InitList, - DestType, /*VerifyOnly=*/true); + DestType, /*VerifyOnly=*/true, + Kind.getKind() != InitializationKind::IK_DirectList || + !S.getLangOpts().CPlusPlus0x); if (CheckInitList.HadError()) { Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed); return; @@ -2778,8 +3146,8 @@ static void TryListInitialization(Sema &S, static OverloadingResult TryRefInitWithConversionFunction(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, - Expr *Initializer, - bool AllowRValues, + Expr *Initializer, + bool AllowRValues, InitializationSequence &Sequence) { QualType DestType = Entity.getType(); QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType(); @@ -2806,8 +3174,9 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // Determine whether we are allowed to call explicit constructors or // explicit conversion operators. - bool AllowExplicit = Kind.getKind() == InitializationKind::IK_Direct; - + bool AllowExplicit = Kind.AllowExplicit(); + bool AllowExplicitConvs = Kind.allowExplicitConversionFunctions(); + const RecordType *T1RecordType = 0; if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) && !S.RequireCompleteType(Kind.getLocation(), T1, 0)) { @@ -2835,11 +3204,11 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, if (ConstructorTmpl) S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, /*ExplicitArgs*/ 0, - &Initializer, 1, CandidateSet, + Initializer, CandidateSet, /*SuppressUserConversions=*/true); else S.AddOverloadCandidate(Constructor, FoundDecl, - &Initializer, 1, CandidateSet, + Initializer, CandidateSet, /*SuppressUserConversions=*/true); } } @@ -2876,7 +3245,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // FIXME: Do we need to make sure that we only consider conversion // candidates with reference-compatible results? That might be needed to // break recursion. - if ((AllowExplicit || !Conv->isExplicit()) && + if ((AllowExplicitConvs || !Conv->isExplicit()) && (AllowRValues || Conv->getConversionType()->isLValueReferenceType())){ if (ConvTemplate) S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), @@ -2903,7 +3272,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // This is the overload that will actually be used for the initialization, so // mark it as used. - S.MarkDeclarationReferenced(DeclLoc, Function); + S.MarkFunctionReferenced(DeclLoc, Function); // Compute the returned type of the conversion. if (isa<CXXConversionDecl>(Function)) @@ -2912,8 +3281,10 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, T2 = cv1T1; // Add the user-defined conversion step. + bool HadMultipleCandidates = (CandidateSet.size() > 1); Sequence.AddUserConversionStep(Function, Best->FoundDecl, - T2.getNonLValueExprType(S.Context)); + T2.getNonLValueExprType(S.Context), + HadMultipleCandidates); // Determine whether we need to perform derived-to-base or // cv-qualification adjustments. @@ -2958,6 +3329,10 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, return OR_Success; } +static void CheckCXX98CompatAccessibleCopy(Sema &S, + const InitializedEntity &Entity, + Expr *CurInitExpr); + /// \brief Attempt reference initialization (C++0x [dcl.init.ref]) static void TryReferenceInitialization(Sema &S, const InitializedEntity &Entity, @@ -2971,26 +3346,31 @@ static void TryReferenceInitialization(Sema &S, QualType cv2T2 = Initializer->getType(); Qualifiers T2Quals; QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals); - SourceLocation DeclLoc = Initializer->getLocStart(); // If the initializer is the address of an overloaded function, try // to resolve the overloaded function. If all goes well, T2 is the // type of the resulting function. - if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) { - DeclAccessPair Found; - if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Initializer, - T1, - false, - Found)) { - Sequence.AddAddressOverloadResolutionStep(Fn, Found); - cv2T2 = Fn->getType(); - T2 = cv2T2.getUnqualifiedType(); - } else if (!T1->isRecordType()) { - Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); - return; - } - } + if (ResolveOverloadedFunctionForReferenceBinding(S, Initializer, cv2T2, T2, + T1, Sequence)) + return; + + // Delegate everything else to a subfunction. + TryReferenceInitializationCore(S, Entity, Kind, Initializer, cv1T1, T1, + T1Quals, cv2T2, T2, T2Quals, Sequence); +} +/// \brief Reference initialization without resolving overloaded functions. +static void TryReferenceInitializationCore(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr *Initializer, + QualType cv1T1, QualType T1, + Qualifiers T1Quals, + QualType cv2T2, QualType T2, + Qualifiers T2Quals, + InitializationSequence &Sequence) { + QualType DestType = Entity.getType(); + SourceLocation DeclLoc = Initializer->getLocStart(); // Compute some basic properties of the types and the initializer. bool isLValueRef = DestType->isLValueReferenceType(); bool isRValueRef = !isLValueRef; @@ -3108,8 +3488,10 @@ static void TryReferenceInitialization(Sema &S, // // The constructor that would be used to make the copy shall // be callable whether or not the copy is actually done. - if (!S.getLangOptions().CPlusPlus0x && !S.getLangOptions().MicrosoftExt) + if (!S.getLangOpts().CPlusPlus0x && !S.getLangOpts().MicrosoftExt) Sequence.AddExtraneousCopyToTemporary(cv2T2); + else if (S.getLangOpts().CPlusPlus0x) + CheckCXX98CompatAccessibleCopy(S, Entity, Initializer); } if (DerivedToBase) @@ -3122,7 +3504,7 @@ static void TryReferenceInitialization(Sema &S, if (T1Quals != T2Quals) Sequence.AddQualificationConversionStep(cv1T1, ValueKind); Sequence.AddReferenceBindingStep(cv1T1, - /*bindingTemporary=*/(InitCategory.isPRValue() && !T2->isArrayType())); + /*bindingTemporary=*/InitCategory.isPRValue()); return; } @@ -3155,7 +3537,7 @@ static void TryReferenceInitialization(Sema &S, // Determine whether we are allowed to call explicit constructors or // explicit conversion operators. - bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct); + bool AllowExplicit = Kind.AllowExplicit(); InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1); @@ -3219,146 +3601,47 @@ static void TryStringLiteralInitialization(Sema &S, Sequence.AddStringInitStep(Entity.getType()); } -/// \brief Attempt initialization by constructor (C++ [dcl.init]), which -/// enumerates the constructors of the initialized entity and performs overload -/// resolution to select the best. -static void TryConstructorInitialization(Sema &S, - const InitializedEntity &Entity, - const InitializationKind &Kind, - Expr **Args, unsigned NumArgs, - QualType DestType, - InitializationSequence &Sequence) { - // Check constructor arguments for self reference. - if (DeclaratorDecl *DD = Entity.getDecl()) - // Parameters arguments are occassionially constructed with itself, - // for instance, in recursive functions. Skip them. - if (!isa<ParmVarDecl>(DD)) - for (unsigned i = 0; i < NumArgs; ++i) - S.CheckSelfReference(DD, Args[i]); - - // Build the candidate set directly in the initialization sequence - // structure, so that it will persist if we fail. - OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); - CandidateSet.clear(); - - // Determine whether we are allowed to call explicit constructors or - // explicit conversion operators. - bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct || - Kind.getKind() == InitializationKind::IK_Value || - Kind.getKind() == InitializationKind::IK_Default); - - // The type we're constructing needs to be complete. - if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) { - Sequence.SetFailed(InitializationSequence::FK_Incomplete); - return; - } - - // The type we're converting to is a class type. Enumerate its constructors - // to see if one is suitable. - const RecordType *DestRecordType = DestType->getAs<RecordType>(); - assert(DestRecordType && "Constructor initialization requires record type"); - CXXRecordDecl *DestRecordDecl - = cast<CXXRecordDecl>(DestRecordType->getDecl()); - - DeclContext::lookup_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl); - Con != ConEnd; ++Con) { - NamedDecl *D = *Con; - DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); - bool SuppressUserConversions = false; - - // Find the constructor (which may be a template). - CXXConstructorDecl *Constructor = 0; - FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D); - if (ConstructorTmpl) - Constructor = cast<CXXConstructorDecl>( - ConstructorTmpl->getTemplatedDecl()); - else { - Constructor = cast<CXXConstructorDecl>(D); - - // If we're performing copy initialization using a copy constructor, we - // suppress user-defined conversions on the arguments. - // FIXME: Move constructors? - if (Kind.getKind() == InitializationKind::IK_Copy && - Constructor->isCopyConstructor()) - SuppressUserConversions = true; - } - - if (!Constructor->isInvalidDecl() && - (AllowExplicit || !Constructor->isExplicit())) { - if (ConstructorTmpl) - S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, - /*ExplicitArgs*/ 0, - Args, NumArgs, CandidateSet, - SuppressUserConversions); - else - S.AddOverloadCandidate(Constructor, FoundDecl, - Args, NumArgs, CandidateSet, - SuppressUserConversions); - } - } - - SourceLocation DeclLoc = Kind.getLocation(); - - // Perform overload resolution. If it fails, return the failed result. - OverloadCandidateSet::iterator Best; - if (OverloadingResult Result - = CandidateSet.BestViableFunction(S, DeclLoc, Best)) { - Sequence.SetOverloadFailure( - InitializationSequence::FK_ConstructorOverloadFailed, - Result); - return; - } - - // C++0x [dcl.init]p6: - // If a program calls for the default initialization of an object - // of a const-qualified type T, T shall be a class type with a - // user-provided default constructor. - if (Kind.getKind() == InitializationKind::IK_Default && - Entity.getType().isConstQualified() && - cast<CXXConstructorDecl>(Best->Function)->isImplicit()) { - Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); - return; - } - - // Add the constructor initialization step. Any cv-qualification conversion is - // subsumed by the initialization. - Sequence.AddConstructorInitializationStep( - cast<CXXConstructorDecl>(Best->Function), - Best->FoundDecl.getAccess(), - DestType); -} - /// \brief Attempt value initialization (C++ [dcl.init]p7). static void TryValueInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, InitializationSequence &Sequence) { - // C++ [dcl.init]p5: + // C++98 [dcl.init]p5, C++11 [dcl.init]p7: // // To value-initialize an object of type T means: QualType T = Entity.getType(); // -- if T is an array type, then each element is value-initialized; - while (const ArrayType *AT = S.Context.getAsArrayType(T)) - T = AT->getElementType(); + T = S.Context.getBaseElementType(T); if (const RecordType *RT = T->getAs<RecordType>()) { if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) { + // C++98: // -- if T is a class type (clause 9) with a user-declared // constructor (12.1), then the default constructor for T is // called (and the initialization is ill-formed if T has no // accessible default constructor); - // - // FIXME: we really want to refer to a single subobject of the array, - // but Entity doesn't have a way to capture that (yet). - if (ClassDecl->hasUserDeclaredConstructor()) - return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence); + if (!S.getLangOpts().CPlusPlus0x) { + if (ClassDecl->hasUserDeclaredConstructor()) + // FIXME: we really want to refer to a single subobject of the array, + // but Entity doesn't have a way to capture that (yet). + return TryConstructorInitialization(S, Entity, Kind, 0, 0, + T, Sequence); + } else { + // C++11: + // -- if T is a class type (clause 9) with either no default constructor + // (12.1 [class.ctor]) or a default constructor that is user-provided + // or deleted, then the object is default-initialized; + CXXConstructorDecl *CD = S.LookupDefaultConstructor(ClassDecl); + if (!CD || !CD->getCanonicalDecl()->isDefaulted() || CD->isDeleted()) + return TryConstructorInitialization(S, Entity, Kind, 0, 0, + T, Sequence); + } - // -- if T is a (possibly cv-qualified) non-union class type - // without a user-provided constructor, then the object is - // zero-initialized and, if T's implicitly-declared default - // constructor is non-trivial, that constructor is called. + // -- if T is a (possibly cv-qualified) non-union class type without a + // user-provided or deleted default constructor, then the object is + // zero-initialized and, if T has a non-trivial default constructor, + // default-initialized; if ((ClassDecl->getTagKind() == TTK_Class || ClassDecl->getTagKind() == TTK_Struct)) { Sequence.AddZeroInitializationStep(Entity.getType()); @@ -3385,7 +3668,7 @@ static void TryDefaultInitialization(Sema &S, // - if T is a (possibly cv-qualified) class type (Clause 9), the default // constructor for T is called (and the initialization is ill-formed if // T has no accessible default constructor); - if (DestType->isRecordType() && S.getLangOptions().CPlusPlus) { + if (DestType->isRecordType() && S.getLangOpts().CPlusPlus) { TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType, Sequence); return; } @@ -3395,7 +3678,7 @@ static void TryDefaultInitialization(Sema &S, // If a program calls for the default initialization of an object of // a const-qualified type T, T shall be a class type with a user-provided // default constructor. - if (DestType.isConstQualified() && S.getLangOptions().CPlusPlus) { + if (DestType.isConstQualified() && S.getLangOpts().CPlusPlus) { Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); return; } @@ -3428,7 +3711,7 @@ static void TryUserDefinedConversion(Sema &S, // Determine whether we are allowed to call explicit constructors or // explicit conversion operators. - bool AllowExplicit = Kind.getKind() == InitializationKind::IK_Direct; + bool AllowExplicit = Kind.AllowExplicit(); if (const RecordType *DestRecordType = DestType->getAs<RecordType>()) { // The type we're converting to is a class type. Enumerate its constructors @@ -3459,11 +3742,11 @@ static void TryUserDefinedConversion(Sema &S, if (ConstructorTmpl) S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, /*ExplicitArgs*/ 0, - &Initializer, 1, CandidateSet, + Initializer, CandidateSet, /*SuppressUserConversions=*/true); else S.AddOverloadCandidate(Constructor, FoundDecl, - &Initializer, 1, CandidateSet, + Initializer, CandidateSet, /*SuppressUserConversions=*/true); } } @@ -3523,29 +3806,35 @@ static void TryUserDefinedConversion(Sema &S, } FunctionDecl *Function = Best->Function; - S.MarkDeclarationReferenced(DeclLoc, Function); + S.MarkFunctionReferenced(DeclLoc, Function); + bool HadMultipleCandidates = (CandidateSet.size() > 1); if (isa<CXXConstructorDecl>(Function)) { // Add the user-defined conversion step. Any cv-qualification conversion is - // subsumed by the initialization. - Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType); + // subsumed by the initialization. Per DR5, the created temporary is of the + // cv-unqualified type of the destination. + Sequence.AddUserConversionStep(Function, Best->FoundDecl, + DestType.getUnqualifiedType(), + HadMultipleCandidates); return; } // Add the user-defined conversion step that calls the conversion function. QualType ConvType = Function->getCallResultType(); if (ConvType->getAs<RecordType>()) { - // If we're converting to a class type, there may be an copy if + // If we're converting to a class type, there may be an copy of // the resulting temporary object (possible to create an object of // a base class type). That copy is not a separate conversion, so // we just make a note of the actual destination type (possibly a // base class of the type returned by the conversion function) and // let the user-defined conversion step handle the conversion. - Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType); + Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType, + HadMultipleCandidates); return; } - Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType); + Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType, + HadMultipleCandidates); // If the conversion following the call to the conversion function // is interesting, add it as a separate step. @@ -3592,16 +3881,11 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e, } // If we have a declaration reference, it had better be a local variable. - } else if (isa<DeclRefExpr>(e) || isa<BlockDeclRefExpr>(e)) { + } else if (isa<DeclRefExpr>(e)) { if (!isAddressOf) return IIK_nonlocal; - VarDecl *var; - if (isa<DeclRefExpr>(e)) { - var = dyn_cast<VarDecl>(cast<DeclRefExpr>(e)->getDecl()); - if (!var) return IIK_nonlocal; - } else { - var = cast<BlockDeclRefExpr>(e)->getDecl(); - } + VarDecl *var = dyn_cast<VarDecl>(cast<DeclRefExpr>(e)->getDecl()); + if (!var) return IIK_nonlocal; return (var->hasLocalStorage() ? IIK_okay : IIK_nonlocal); @@ -3721,7 +4005,7 @@ InitializationSequence::InitializationSequence(Sema &S, QualType DestType = Entity.getType(); if (DestType->isDependentType() || - Expr::hasAnyTypeDependentArguments(Args, NumArgs)) { + Expr::hasAnyTypeDependentArguments(llvm::makeArrayRef(Args, NumArgs))) { SequenceKind = DependentSequence; return; } @@ -3730,15 +4014,17 @@ InitializationSequence::InitializationSequence(Sema &S, setSequenceKind(NormalSequence); for (unsigned I = 0; I != NumArgs; ++I) - if (Args[I]->getObjectKind() == OK_ObjCProperty) { - ExprResult Result = S.ConvertPropertyForRValue(Args[I]); - if (Result.isInvalid()) { - SetFailed(FK_ConversionFromPropertyFailed); + if (Args[I]->getType()->isNonOverloadPlaceholderType()) { + // FIXME: should we be doing this here? + ExprResult result = S.CheckPlaceholderExpr(Args[I]); + if (result.isInvalid()) { + SetFailed(FK_PlaceholderType); return; } - Args[I] = Result.take(); + Args[I] = result.take(); } + QualType SourceType; Expr *Initializer = 0; if (NumArgs == 1) { @@ -3747,11 +4033,13 @@ InitializationSequence::InitializationSequence(Sema &S, SourceType = Initializer->getType(); } - // - If the initializer is a braced-init-list, the object is - // list-initialized (8.5.4). - if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) { - TryListInitialization(S, Entity, Kind, InitList, *this); - return; + // - If the initializer is a (non-parenthesized) braced-init-list, the + // object is list-initialized (8.5.4). + if (Kind.getKind() != InitializationKind::IK_Direct) { + if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) { + TryListInitialization(S, Entity, Kind, InitList, *this); + return; + } } // - If the destination type is a reference type, see 8.5.3. @@ -3787,6 +4075,11 @@ InitializationSequence::InitializationSequence(Sema &S, // - Otherwise, if the destination type is an array, the program is // ill-formed. if (const ArrayType *DestAT = Context.getAsArrayType(DestType)) { + if (Initializer && isa<VariableArrayType>(DestAT)) { + SetFailed(FK_VariableLengthArrayHasInitializer); + return; + } + if (Initializer && IsStringInit(Initializer, DestAT, Context)) { TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this); return; @@ -3795,7 +4088,7 @@ InitializationSequence::InitializationSequence(Sema &S, // Note: as an GNU C extension, we allow initialization of an // array from a compound literal that creates an array of the same // type, so long as the initializer has no side effects. - if (!S.getLangOptions().CPlusPlus && Initializer && + if (!S.getLangOpts().CPlusPlus && Initializer && isa<CompoundLiteralExpr>(Initializer->IgnoreParens()) && Initializer->getType()->isArrayType()) { const ArrayType *SourceAT @@ -3807,6 +4100,15 @@ InitializationSequence::InitializationSequence(Sema &S, else { AddArrayInitStep(DestType); } + } + // Note: as a GNU C++ extension, we allow initialization of a + // class member from a parenthesized initializer list. + else if (S.getLangOpts().CPlusPlus && + Entity.getKind() == InitializedEntity::EK_Member && + Initializer && isa<InitListExpr>(Initializer)) { + TryListInitialization(S, Entity, Kind, cast<InitListExpr>(Initializer), + *this); + AddParenthesizedArrayInitStep(DestType); } else if (DestAT->getElementType()->isAnyCharacterType()) SetFailed(FK_ArrayNeedsInitListOrStringLiteral); else @@ -3817,12 +4119,12 @@ InitializationSequence::InitializationSequence(Sema &S, // Determine whether we should consider writeback conversions for // Objective-C ARC. - bool allowObjCWritebackConversion = S.getLangOptions().ObjCAutoRefCount && + bool allowObjCWritebackConversion = S.getLangOpts().ObjCAutoRefCount && Entity.getKind() == InitializedEntity::EK_Parameter; // We're at the end of the line for C: it's either a write-back conversion // or it's a C assignment. There's no need to check anything else. - if (!S.getLangOptions().CPlusPlus) { + if (!S.getLangOpts().CPlusPlus) { // If allowed, check whether this is an Objective-C writeback conversion. if (allowObjCWritebackConversion && tryObjCWritebackConversion(S, *this, Entity, Initializer)) { @@ -3835,7 +4137,7 @@ InitializationSequence::InitializationSequence(Sema &S, return; } - assert(S.getLangOptions().CPlusPlus); + assert(S.getLangOpts().CPlusPlus); // - If the destination type is a (possibly cv-qualified) class type: if (DestType->isRecordType()) { @@ -3964,10 +4266,11 @@ getAssignmentAction(const InitializedEntity &Entity) { case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_BlockElement: + case InitializedEntity::EK_LambdaCapture: return Sema::AA_Initializing; } - return Sema::AA_Converting; + llvm_unreachable("Invalid EntityKind!"); } /// \brief Whether we should binding a created object as a temporary when @@ -3985,6 +4288,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_Exception: case InitializedEntity::EK_BlockElement: + case InitializedEntity::EK_LambdaCapture: return false; case InitializedEntity::EK_Parameter: @@ -4007,6 +4311,7 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_BlockElement: + case InitializedEntity::EK_LambdaCapture: return false; case InitializedEntity::EK_Variable: @@ -4020,6 +4325,81 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) { llvm_unreachable("missed an InitializedEntity kind?"); } +/// \brief Look for copy and move constructors and constructor templates, for +/// copying an object via direct-initialization (per C++11 [dcl.init]p16). +static void LookupCopyAndMoveConstructors(Sema &S, + OverloadCandidateSet &CandidateSet, + CXXRecordDecl *Class, + Expr *CurInitExpr) { + DeclContext::lookup_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = S.LookupConstructors(Class); + Con != ConEnd; ++Con) { + CXXConstructorDecl *Constructor = 0; + + if ((Constructor = dyn_cast<CXXConstructorDecl>(*Con))) { + // Handle copy/moveconstructors, only. + if (!Constructor || Constructor->isInvalidDecl() || + !Constructor->isCopyOrMoveConstructor() || + !Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) + continue; + + DeclAccessPair FoundDecl + = DeclAccessPair::make(Constructor, Constructor->getAccess()); + S.AddOverloadCandidate(Constructor, FoundDecl, + CurInitExpr, CandidateSet); + continue; + } + + // Handle constructor templates. + FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(*Con); + if (ConstructorTmpl->isInvalidDecl()) + continue; + + Constructor = cast<CXXConstructorDecl>( + ConstructorTmpl->getTemplatedDecl()); + if (!Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) + continue; + + // FIXME: Do we need to limit this to copy-constructor-like + // candidates? + DeclAccessPair FoundDecl + = DeclAccessPair::make(ConstructorTmpl, ConstructorTmpl->getAccess()); + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, 0, + CurInitExpr, CandidateSet, true); + } +} + +/// \brief Get the location at which initialization diagnostics should appear. +static SourceLocation getInitializationLoc(const InitializedEntity &Entity, + Expr *Initializer) { + switch (Entity.getKind()) { + case InitializedEntity::EK_Result: + return Entity.getReturnLoc(); + + case InitializedEntity::EK_Exception: + return Entity.getThrowLoc(); + + case InitializedEntity::EK_Variable: + return Entity.getDecl()->getLocation(); + + case InitializedEntity::EK_LambdaCapture: + return Entity.getCaptureLoc(); + + case InitializedEntity::EK_ArrayElement: + case InitializedEntity::EK_Member: + case InitializedEntity::EK_Parameter: + case InitializedEntity::EK_Temporary: + case InitializedEntity::EK_New: + case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: + case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_ComplexElement: + case InitializedEntity::EK_BlockElement: + return Initializer->getLocStart(); + } + llvm_unreachable("missed an InitializedEntity kind?"); +} + /// \brief Make a (potentially elidable) temporary copy of the object /// provided by the given initializer by calling the appropriate copy /// constructor. @@ -4069,79 +4449,18 @@ static ExprResult CopyObject(Sema &S, // of constructor initialization, while copy elision for exception handlers // is handled by the run-time. bool Elidable = CurInitExpr->isTemporaryObject(S.Context, Class); - SourceLocation Loc; - switch (Entity.getKind()) { - case InitializedEntity::EK_Result: - Loc = Entity.getReturnLoc(); - break; - - case InitializedEntity::EK_Exception: - Loc = Entity.getThrowLoc(); - break; - - case InitializedEntity::EK_Variable: - Loc = Entity.getDecl()->getLocation(); - break; - - case InitializedEntity::EK_ArrayElement: - case InitializedEntity::EK_Member: - case InitializedEntity::EK_Parameter: - case InitializedEntity::EK_Temporary: - case InitializedEntity::EK_New: - case InitializedEntity::EK_Base: - case InitializedEntity::EK_Delegating: - case InitializedEntity::EK_VectorElement: - case InitializedEntity::EK_ComplexElement: - case InitializedEntity::EK_BlockElement: - Loc = CurInitExpr->getLocStart(); - break; - } + SourceLocation Loc = getInitializationLoc(Entity, CurInit.get()); // Make sure that the type we are copying is complete. if (S.RequireCompleteType(Loc, T, S.PDiag(diag::err_temp_copy_incomplete))) return move(CurInit); // Perform overload resolution using the class's copy/move constructors. - DeclContext::lookup_iterator Con, ConEnd; + // 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); - for (llvm::tie(Con, ConEnd) = S.LookupConstructors(Class); - Con != ConEnd; ++Con) { - // Only consider copy/move constructors and constructor templates. Per - // C++0x [dcl.init]p16, second bullet to class types, this - // initialization is direct-initialization. - CXXConstructorDecl *Constructor = 0; - - if ((Constructor = dyn_cast<CXXConstructorDecl>(*Con))) { - // Handle copy/moveconstructors, only. - if (!Constructor || Constructor->isInvalidDecl() || - !Constructor->isCopyOrMoveConstructor() || - !Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) - continue; - - DeclAccessPair FoundDecl - = DeclAccessPair::make(Constructor, Constructor->getAccess()); - S.AddOverloadCandidate(Constructor, FoundDecl, - &CurInitExpr, 1, CandidateSet); - continue; - } - - // Handle constructor templates. - FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(*Con); - if (ConstructorTmpl->isInvalidDecl()) - continue; - - Constructor = cast<CXXConstructorDecl>( - ConstructorTmpl->getTemplatedDecl()); - if (!Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) - continue; - - // FIXME: Do we need to limit this to copy-constructor-like - // candidates? - DeclAccessPair FoundDecl - = DeclAccessPair::make(ConstructorTmpl, ConstructorTmpl->getAccess()); - S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, 0, - &CurInitExpr, 1, CandidateSet, true); - } + LookupCopyAndMoveConstructors(S, CandidateSet, Class, CurInitExpr); bool HadMultipleCandidates = (CandidateSet.size() > 1); @@ -4156,7 +4475,7 @@ static ExprResult CopyObject(Sema &S, : diag::err_temp_copy_no_viable) << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); - CandidateSet.NoteCandidates(S, OCD_AllCandidates, &CurInitExpr, 1); + CandidateSet.NoteCandidates(S, OCD_AllCandidates, CurInitExpr); if (!IsExtraneousCopy || S.isSFINAEContext()) return ExprError(); return move(CurInit); @@ -4165,15 +4484,14 @@ static ExprResult CopyObject(Sema &S, S.Diag(Loc, diag::err_temp_copy_ambiguous) << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); - CandidateSet.NoteCandidates(S, OCD_ViableCandidates, &CurInitExpr, 1); + CandidateSet.NoteCandidates(S, OCD_ViableCandidates, CurInitExpr); return ExprError(); case OR_Deleted: S.Diag(Loc, diag::err_temp_copy_deleted) << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); - S.Diag(Best->Function->getLocation(), diag::note_unavailable_here) - << 1 << Best->Function->isDeleted(); + S.NoteDeletedFunction(Best->Function); return ExprError(); } @@ -4210,7 +4528,7 @@ static ExprResult CopyObject(Sema &S, return S.Owned(CurInitExpr); } - S.MarkDeclarationReferenced(Loc, Constructor); + S.MarkFunctionReferenced(Loc, Constructor); // Determine the arguments required to actually perform the // constructor call (we might have derived-to-base conversions, or @@ -4233,6 +4551,60 @@ static ExprResult CopyObject(Sema &S, return move(CurInit); } +/// \brief Check whether elidable copy construction for binding a reference to +/// a temporary would have succeeded if we were building in C++98 mode, for +/// -Wc++98-compat. +static void CheckCXX98CompatAccessibleCopy(Sema &S, + const InitializedEntity &Entity, + Expr *CurInitExpr) { + assert(S.getLangOpts().CPlusPlus0x); + + const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>(); + if (!Record) + return; + + SourceLocation Loc = getInitializationLoc(Entity, CurInitExpr); + if (S.Diags.getDiagnosticLevel(diag::warn_cxx98_compat_temp_copy, Loc) + == DiagnosticsEngine::Ignored) + return; + + // Find constructors which would have been considered. + OverloadCandidateSet CandidateSet(Loc); + LookupCopyAndMoveConstructors( + S, CandidateSet, cast<CXXRecordDecl>(Record->getDecl()), CurInitExpr); + + // Perform overload resolution. + OverloadCandidateSet::iterator Best; + OverloadingResult OR = CandidateSet.BestViableFunction(S, Loc, Best); + + PartialDiagnostic Diag = S.PDiag(diag::warn_cxx98_compat_temp_copy) + << OR << (int)Entity.getKind() << CurInitExpr->getType() + << CurInitExpr->getSourceRange(); + + switch (OR) { + case OR_Success: + S.CheckConstructorAccess(Loc, cast<CXXConstructorDecl>(Best->Function), + Entity, Best->FoundDecl.getAccess(), Diag); + // FIXME: Check default arguments as far as that's possible. + break; + + case OR_No_Viable_Function: + S.Diag(Loc, Diag); + CandidateSet.NoteCandidates(S, OCD_AllCandidates, CurInitExpr); + break; + + case OR_Ambiguous: + S.Diag(Loc, Diag); + CandidateSet.NoteCandidates(S, OCD_ViableCandidates, CurInitExpr); + break; + + case OR_Deleted: + S.Diag(Loc, Diag); + S.NoteDeletedFunction(Best->Function); + break; + } +} + void InitializationSequence::PrintInitLocationNote(Sema &S, const InitializedEntity &Entity) { if (Entity.getKind() == InitializedEntity::EK_Parameter && Entity.getDecl()) { @@ -4252,6 +4624,130 @@ static bool isReferenceBinding(const InitializationSequence::Step &s) { s.Kind == InitializationSequence::SK_BindReferenceToTemporary; } +static ExprResult +PerformConstructorInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + MultiExprArg Args, + const InitializationSequence::Step& Step, + bool &ConstructorInitRequiresZeroInit) { + unsigned NumArgs = Args.size(); + CXXConstructorDecl *Constructor + = cast<CXXConstructorDecl>(Step.Function.Function); + bool HadMultipleCandidates = Step.Function.HadMultipleCandidates; + + // Build a call to the selected constructor. + ASTOwningVector<Expr*> ConstructorArgs(S); + SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid()) + ? Kind.getEqualLoc() + : Kind.getLocation(); + + if (Kind.getKind() == InitializationKind::IK_Default) { + // Force even a trivial, implicit default constructor to be + // semantically checked. We do this explicitly because we don't build + // the definition for completely trivial constructors. + assert(Constructor->getParent() && "No parent class for constructor."); + if (Constructor->isDefaulted() && Constructor->isDefaultConstructor() && + Constructor->isTrivial() && !Constructor->isUsed(false)) + S.DefineImplicitDefaultConstructor(Loc, Constructor); + } + + ExprResult CurInit = S.Owned((Expr *)0); + + // C++ [over.match.copy]p1: + // - When initializing a temporary to be bound to the first parameter + // of a constructor that takes a reference to possibly cv-qualified + // T as its first argument, called with a single argument in the + // context of direct-initialization, explicit conversion functions + // are also considered. + bool AllowExplicitConv = Kind.AllowExplicit() && !Kind.isCopyInit() && + Args.size() == 1 && + Constructor->isCopyOrMoveConstructor(); + + // Determine the arguments required to actually perform the constructor + // call. + if (S.CompleteConstructorCall(Constructor, move(Args), + Loc, ConstructorArgs, + AllowExplicitConv)) + return ExprError(); + + + if (Entity.getKind() == InitializedEntity::EK_Temporary && + (Kind.getKind() == InitializationKind::IK_DirectList || + (NumArgs != 1 && // FIXME: Hack to work around cast weirdness + (Kind.getKind() == InitializationKind::IK_Direct || + Kind.getKind() == InitializationKind::IK_Value)))) { + // An explicitly-constructed temporary, e.g., X(1, 2). + unsigned NumExprs = ConstructorArgs.size(); + Expr **Exprs = (Expr **)ConstructorArgs.take(); + S.MarkFunctionReferenced(Loc, Constructor); + S.DiagnoseUseOfDecl(Constructor, Loc); + + TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); + if (!TSInfo) + TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc); + SourceRange ParenRange; + if (Kind.getKind() != InitializationKind::IK_DirectList) + ParenRange = Kind.getParenRange(); + + CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context, + Constructor, + TSInfo, + Exprs, + NumExprs, + ParenRange, + HadMultipleCandidates, + ConstructorInitRequiresZeroInit)); + } else { + CXXConstructExpr::ConstructionKind ConstructKind = + CXXConstructExpr::CK_Complete; + + if (Entity.getKind() == InitializedEntity::EK_Base) { + ConstructKind = Entity.getBaseSpecifier()->isVirtual() ? + CXXConstructExpr::CK_VirtualBase : + CXXConstructExpr::CK_NonVirtualBase; + } else if (Entity.getKind() == InitializedEntity::EK_Delegating) { + 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(); + + // If the entity allows NRVO, mark the construction as elidable + // unconditionally. + if (Entity.allowsNRVO()) + CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), + Constructor, /*Elidable=*/true, + move_arg(ConstructorArgs), + HadMultipleCandidates, + ConstructorInitRequiresZeroInit, + ConstructKind, + parenRange); + else + CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), + Constructor, + move_arg(ConstructorArgs), + HadMultipleCandidates, + ConstructorInitRequiresZeroInit, + ConstructKind, + parenRange); + } + if (CurInit.isInvalid()) + return ExprError(); + + // Only check access if all of that succeeded. + S.CheckConstructorAccess(Loc, Constructor, Entity, + Step.Function.FoundDecl.getAccess()); + S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc); + + if (shouldBindAsTemporary(Entity)) + CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); + + return move(CurInit); +} + ExprResult InitializationSequence::Perform(Sema &S, const InitializedEntity &Entity, @@ -4303,8 +4799,16 @@ InitializationSequence::Perform(Sema &S, } } + if (Kind.getKind() == InitializationKind::IK_Direct && + !Kind.isExplicitCast()) { + // Rebuild the ParenListExpr. + SourceRange ParenRange = Kind.getParenRange(); + return S.ActOnParenListExpr(ParenRange.getBegin(), ParenRange.getEnd(), + move(Args)); + } assert(Kind.getKind() == InitializationKind::IK_Copy || - Kind.isExplicitCast()); + Kind.isExplicitCast() || + Kind.getKind() == InitializationKind::IK_DirectList); return ExprResult(Args.release()[0]); } @@ -4340,23 +4844,20 @@ InitializationSequence::Perform(Sema &S, case SK_ConversionSequence: case SK_ListConstructorCall: case SK_ListInitialization: + case SK_UnwrapInitList: + case SK_RewrapInitList: case SK_CAssignment: case SK_StringInit: case SK_ObjCObjectConversion: case SK_ArrayInit: + case SK_ParenthesizedArrayInit: case SK_PassByIndirectCopyRestore: case SK_PassByIndirectRestore: - case SK_ProduceObjCObject: { + case SK_ProduceObjCObject: + case SK_StdInitializerList: { assert(Args.size() == 1); CurInit = Args.get()[0]; if (!CurInit.get()) return ExprError(); - - // Read from a property when initializing something with it. - if (CurInit.get()->getObjectKind() == OK_ObjCProperty) { - CurInit = S.ConvertPropertyForRValue(CurInit.take()); - if (CurInit.isInvalid()) - return ExprError(); - } break; } @@ -4466,7 +4967,7 @@ InitializationSequence::Perform(Sema &S, // If we're binding to an Objective-C object that has lifetime, we // need cleanups. - if (S.getLangOptions().ObjCAutoRefCount && + if (S.getLangOpts().ObjCAutoRefCount && CurInit.get()->getType()->isObjCLifetimeType()) S.ExprNeedsCleanups = true; @@ -4500,7 +5001,7 @@ InitializationSequence::Perform(Sema &S, Loc, ConstructorArgs)) return ExprError(); - // Build the an expression that constructs a temporary. + // Build an expression that constructs a temporary. CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor, move_arg(ConstructorArgs), HadMultipleCandidates, @@ -4550,16 +5051,16 @@ InitializationSequence::Perform(Sema &S, } bool RequiresCopy = !IsCopy && !isReferenceBinding(Steps.back()); - if (RequiresCopy || shouldBindAsTemporary(Entity)) - CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); - else if (CreatedObject && shouldDestroyTemporary(Entity)) { + bool MaybeBindToTemp = RequiresCopy || shouldBindAsTemporary(Entity); + + if (!MaybeBindToTemp && CreatedObject && shouldDestroyTemporary(Entity)) { QualType T = CurInit.get()->getType(); if (const RecordType *Record = T->getAs<RecordType>()) { CXXDestructorDecl *Destructor = S.LookupDestructor(cast<CXXRecordDecl>(Record->getDecl())); S.CheckDestructorAccess(CurInit.get()->getLocStart(), Destructor, S.PDiag(diag::err_access_dtor_temp) << T); - S.MarkDeclarationReferenced(CurInit.get()->getLocStart(), Destructor); + S.MarkFunctionReferenced(CurInit.get()->getLocStart(), Destructor); S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getLocStart()); } } @@ -4568,11 +5069,11 @@ InitializationSequence::Perform(Sema &S, CurInit.get()->getType(), CastKind, CurInit.get(), 0, CurInit.get()->getValueKind())); - + if (MaybeBindToTemp) + CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); if (RequiresCopy) CurInit = CopyObject(S, Entity.getType().getNonReferenceType(), Entity, move(CurInit), /*IsExtraneousCopy=*/false); - break; } @@ -4607,120 +5108,89 @@ InitializationSequence::Perform(Sema &S, case SK_ListInitialization: { InitListExpr *InitList = cast<InitListExpr>(CurInit.get()); - QualType Ty = Step->Type; - InitListChecker PerformInitList(S, Entity, InitList, - ResultType ? *ResultType : Ty, /*VerifyOnly=*/false); + // Hack: We must pass *ResultType if available in order to set the type + // of arrays, e.g. in 'int ar[] = {1, 2, 3};'. + // But in 'const X &x = {1, 2, 3};' we're supposed to initialize a + // temporary, not a reference, so we should pass Ty. + // Worst case: 'const int (&arref)[] = {1, 2, 3};'. + // Since this step is never used for a reference directly, we explicitly + // unwrap references here and rewrap them afterwards. + // We also need to create a InitializeTemporary entity for this. + QualType Ty = ResultType ? ResultType->getNonReferenceType() : Step->Type; + bool IsTemporary = Entity.getType()->isReferenceType(); + InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(Ty); + InitListChecker PerformInitList(S, IsTemporary ? TempEntity : Entity, + InitList, Ty, /*VerifyOnly=*/false, + Kind.getKind() != InitializationKind::IK_DirectList || + !S.getLangOpts().CPlusPlus0x); if (PerformInitList.HadError()) return ExprError(); + if (ResultType) { + if ((*ResultType)->isRValueReferenceType()) + Ty = S.Context.getRValueReferenceType(Ty); + else if ((*ResultType)->isLValueReferenceType()) + Ty = S.Context.getLValueReferenceType(Ty, + (*ResultType)->getAs<LValueReferenceType>()->isSpelledAsLValue()); + *ResultType = Ty; + } + + InitListExpr *StructuredInitList = + PerformInitList.getFullyStructuredList(); CurInit.release(); - CurInit = S.Owned(PerformInitList.getFullyStructuredList()); + CurInit = S.Owned(StructuredInitList); break; } - case SK_ListConstructorCall: - assert(false && "List constructor calls not yet supported."); - - case SK_ConstructorInitialization: { - unsigned NumArgs = Args.size(); - CXXConstructorDecl *Constructor - = cast<CXXConstructorDecl>(Step->Function.Function); - bool HadMultipleCandidates = Step->Function.HadMultipleCandidates; - - // Build a call to the selected constructor. - ASTOwningVector<Expr*> ConstructorArgs(S); - SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid()) - ? Kind.getEqualLoc() - : Kind.getLocation(); - - if (Kind.getKind() == InitializationKind::IK_Default) { - // Force even a trivial, implicit default constructor to be - // semantically checked. We do this explicitly because we don't build - // the definition for completely trivial constructors. - CXXRecordDecl *ClassDecl = Constructor->getParent(); - assert(ClassDecl && "No parent class for constructor."); - if (Constructor->isDefaulted() && Constructor->isDefaultConstructor() && - ClassDecl->hasTrivialDefaultConstructor() && - !Constructor->isUsed(false)) - S.DefineImplicitDefaultConstructor(Loc, Constructor); - } - - // Determine the arguments required to actually perform the constructor - // call. - if (S.CompleteConstructorCall(Constructor, move(Args), - Loc, ConstructorArgs)) - return ExprError(); - - - if (Entity.getKind() == InitializedEntity::EK_Temporary && - NumArgs != 1 && // FIXME: Hack to work around cast weirdness - (Kind.getKind() == InitializationKind::IK_Direct || - Kind.getKind() == InitializationKind::IK_Value)) { - // An explicitly-constructed temporary, e.g., X(1, 2). - unsigned NumExprs = ConstructorArgs.size(); - Expr **Exprs = (Expr **)ConstructorArgs.take(); - S.MarkDeclarationReferenced(Loc, Constructor); - S.DiagnoseUseOfDecl(Constructor, Loc); - - TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); - if (!TSInfo) - TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc); - - CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context, - Constructor, - TSInfo, - Exprs, - NumExprs, - Kind.getParenRange(), - HadMultipleCandidates, - ConstructorInitRequiresZeroInit)); - } else { - CXXConstructExpr::ConstructionKind ConstructKind = - CXXConstructExpr::CK_Complete; - - if (Entity.getKind() == InitializedEntity::EK_Base) { - ConstructKind = Entity.getBaseSpecifier()->isVirtual() ? - CXXConstructExpr::CK_VirtualBase : - CXXConstructExpr::CK_NonVirtualBase; - } else if (Entity.getKind() == InitializedEntity::EK_Delegating) { - 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(); - - // If the entity allows NRVO, mark the construction as elidable - // unconditionally. - if (Entity.allowsNRVO()) - CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), - Constructor, /*Elidable=*/true, - move_arg(ConstructorArgs), - HadMultipleCandidates, - ConstructorInitRequiresZeroInit, - ConstructKind, - parenRange); - else - CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), - Constructor, - move_arg(ConstructorArgs), - HadMultipleCandidates, - ConstructorInitRequiresZeroInit, - ConstructKind, - parenRange); - } - if (CurInit.isInvalid()) - return ExprError(); + case SK_ListConstructorCall: { + // 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. + // FIXME: This is a hack. What we really should do is create a user + // conversion step for this case, but this makes it considerably more + // complicated. For now, this will do. + InitializedEntity TempEntity = InitializedEntity::InitializeTemporary( + Entity.getType().getNonReferenceType()); + bool UseTemporary = Entity.getType()->isReferenceType(); + InitListExpr *InitList = cast<InitListExpr>(CurInit.get()); + MultiExprArg Arg(InitList->getInits(), InitList->getNumInits()); + CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity : + Entity, + Kind, move(Arg), *Step, + ConstructorInitRequiresZeroInit); + break; + } - // Only check access if all of that succeeded. - S.CheckConstructorAccess(Loc, Constructor, Entity, - Step->Function.FoundDecl.getAccess()); - S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Loc); + case SK_UnwrapInitList: + CurInit = S.Owned(cast<InitListExpr>(CurInit.take())->getInit(0)); + break; - if (shouldBindAsTemporary(Entity)) - CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); + case SK_RewrapInitList: { + Expr *E = CurInit.take(); + InitListExpr *Syntactic = Step->WrappingSyntacticList; + InitListExpr *ILE = new (S.Context) InitListExpr(S.Context, + Syntactic->getLBraceLoc(), &E, 1, Syntactic->getRBraceLoc()); + ILE->setSyntacticForm(Syntactic); + ILE->setType(E->getType()); + ILE->setValueKind(E->getValueKind()); + CurInit = S.Owned(ILE); + break; + } + case SK_ConstructorInitialization: { + // 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. + // FIXME: This is a hack. What we really should do is create a user + // conversion step for this case, but this makes it considerably more + // complicated. For now, this will do. + InitializedEntity TempEntity = InitializedEntity::InitializeTemporary( + Entity.getType().getNonReferenceType()); + bool UseTemporary = Entity.getType()->isReferenceType(); + CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity + : Entity, + Kind, move(Args), *Step, + ConstructorInitRequiresZeroInit); break; } @@ -4733,7 +5203,7 @@ InitializationSequence::Perform(Sema &S, // the call to the object's constructor within the next step. ConstructorInitRequiresZeroInit = true; } else if (Kind.getKind() == InitializationKind::IK_Value && - S.getLangOptions().CPlusPlus && + S.getLangOpts().CPlusPlus && !Kind.isImplicitValueInit()) { TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); if (!TSInfo) @@ -4819,6 +5289,13 @@ InitializationSequence::Perform(Sema &S, } break; + case SK_ParenthesizedArrayInit: + // Okay: we checked everything before creating this step. Note that + // this is a GNU extension. + S.Diag(Kind.getLocation(), diag::ext_array_init_parens) + << CurInit.get()->getSourceRange(); + break; + case SK_PassByIndirectCopyRestore: case SK_PassByIndirectRestore: checkIndirectCopyRestoreSource(S, CurInit.get()); @@ -4832,6 +5309,54 @@ InitializationSequence::Perform(Sema &S, CK_ARCProduceObject, CurInit.take(), 0, VK_RValue)); break; + + case SK_StdInitializerList: { + QualType Dest = Step->Type; + QualType E; + bool Success = S.isStdInitializerList(Dest, &E); + (void)Success; + assert(Success && "Destination type changed?"); + + // If the element type has a destructor, check it. + if (CXXRecordDecl *RD = E->getAsCXXRecordDecl()) { + if (!RD->hasIrrelevantDestructor()) { + if (CXXDestructorDecl *Destructor = S.LookupDestructor(RD)) { + S.MarkFunctionReferenced(Kind.getLocation(), Destructor); + S.CheckDestructorAccess(Kind.getLocation(), Destructor, + S.PDiag(diag::err_access_dtor_temp) << E); + S.DiagnoseUseOfDecl(Destructor, Kind.getLocation()); + } + } + } + + InitListExpr *ILE = cast<InitListExpr>(CurInit.take()); + unsigned NumInits = ILE->getNumInits(); + SmallVector<Expr*, 16> Converted(NumInits); + InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary( + S.Context.getConstantArrayType(E, + llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()), + NumInits), + ArrayType::Normal, 0)); + InitializedEntity Element =InitializedEntity::InitializeElement(S.Context, + 0, HiddenArray); + for (unsigned i = 0; i < NumInits; ++i) { + Element.setElementIndex(i); + ExprResult Init = S.Owned(ILE->getInit(i)); + ExprResult Res = S.PerformCopyInitialization(Element, + Init.get()->getExprLoc(), + Init); + assert(!Res.isInvalid() && "Result changed since try phase."); + Converted[i] = Res.take(); + } + InitListExpr *Semantic = new (S.Context) + InitListExpr(S.Context, ILE->getLBraceLoc(), + Converted.data(), NumInits, ILE->getRBraceLoc()); + Semantic->setSyntacticForm(ILE); + Semantic->setType(Dest); + Semantic->setInitializesStdInitializerList(); + CurInit = S.Owned(Semantic); + break; + } } } @@ -4884,6 +5409,11 @@ bool InitializationSequence::Diagnose(Sema &S, << Args[0]->getSourceRange(); break; + case FK_VariableLengthArrayHasInitializer: + S.Diag(Kind.getLocation(), diag::err_variable_object_no_init) + << Args[0]->getSourceRange(); + break; + case FK_AddressOfOverloadFailed: { DeclAccessPair Found; S.ResolveAddressOfOverloadedFunction(Args[0], @@ -4906,14 +5436,16 @@ bool InitializationSequence::Diagnose(Sema &S, << DestType << Args[0]->getType() << Args[0]->getSourceRange(); - FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args, NumArgs); + FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, + llvm::makeArrayRef(Args, NumArgs)); break; case OR_No_Viable_Function: S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition) << Args[0]->getType() << DestType.getNonReferenceType() << Args[0]->getSourceRange(); - FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args, NumArgs); + FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); break; case OR_Deleted: { @@ -4925,8 +5457,7 @@ bool InitializationSequence::Diagnose(Sema &S, = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best, true); if (Ovl == OR_Deleted) { - S.Diag(Best->Function->getLocation(), diag::note_unavailable_here) - << 1 << Best->Function->isDeleted(); + S.NoteDeletedFunction(Best->Function); } else { llvm_unreachable("Inconsistent overload resolution?"); } @@ -4935,11 +5466,20 @@ bool InitializationSequence::Diagnose(Sema &S, case OR_Success: llvm_unreachable("Conversion did not fail!"); - break; } break; case FK_NonConstLValueReferenceBindingToTemporary: + if (isa<InitListExpr>(Args[0])) { + S.Diag(Kind.getLocation(), + diag::err_lvalue_reference_bind_to_initlist) + << DestType.getNonReferenceType().isVolatileQualified() + << DestType.getNonReferenceType() + << Args[0]->getSourceRange(); + break; + } + // Intentional fallthrough + case FK_NonConstLValueReferenceBindingToUnrelated: S.Diag(Kind.getLocation(), Failure == FK_NonConstLValueReferenceBindingToTemporary @@ -4977,12 +5517,14 @@ bool InitializationSequence::Diagnose(Sema &S, case FK_ConversionFailed: { QualType FromType = Args[0]->getType(); - S.Diag(Kind.getLocation(), diag::err_init_conversion_failed) + PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed) << (int)Entity.getKind() << DestType << Args[0]->isLValue() << FromType << Args[0]->getSourceRange(); + S.HandleFunctionTypeMismatch(PDiag, FromType, DestType); + S.Diag(Kind.getLocation(), PDiag); if (DestType.getNonReferenceType()->isObjCObjectPointerType() && Args[0]->getType()->isObjCObjectPointerType()) S.EmitRelatedResultTypeNote(Args[0]); @@ -5022,12 +5564,20 @@ bool InitializationSequence::Diagnose(Sema &S, << (DestType->isRecordType()) << DestType << Args[0]->getSourceRange(); break; + case FK_ListConstructorOverloadFailed: case FK_ConstructorOverloadFailed: { SourceRange ArgsRange; if (NumArgs) ArgsRange = SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd()); + if (Failure == FK_ListConstructorOverloadFailed) { + assert(NumArgs == 1 && "List construction from other than 1 argument."); + InitListExpr *InitList = cast<InitListExpr>(Args[0]); + Args = InitList->getInits(); + NumArgs = InitList->getNumInits(); + } + // FIXME: Using "DestType" for the entity we're printing is probably // bad. switch (FailedOverloadResult) { @@ -5035,7 +5585,7 @@ bool InitializationSequence::Diagnose(Sema &S, S.Diag(Kind.getLocation(), diag::err_ovl_ambiguous_init) << DestType << ArgsRange; FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, - Args, NumArgs); + llvm::makeArrayRef(Args, NumArgs)); break; case OR_No_Viable_Function: @@ -5080,30 +5630,41 @@ bool InitializationSequence::Diagnose(Sema &S, S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init) << DestType << ArgsRange; - FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args, NumArgs); + FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); break; case OR_Deleted: { - S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init) - << true << DestType << ArgsRange; OverloadCandidateSet::iterator Best; OverloadingResult Ovl = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best); - if (Ovl == OR_Deleted) { - S.Diag(Best->Function->getLocation(), diag::note_unavailable_here) - << 1 << Best->Function->isDeleted(); - } else { + if (Ovl != OR_Deleted) { + S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init) + << true << DestType << ArgsRange; llvm_unreachable("Inconsistent overload resolution?"); + break; } + + // If this is a defaulted or implicitly-declared function, then + // it was implicitly deleted. Make it clear that the deletion was + // implicit. + if (S.isImplicitlyDeleted(Best->Function)) + S.Diag(Kind.getLocation(), diag::err_ovl_deleted_special_init) + << S.getSpecialMember(cast<CXXMethodDecl>(Best->Function)) + << DestType << ArgsRange; + else + S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init) + << true << DestType << ArgsRange; + + S.NoteDeletedFunction(Best->Function); break; } case OR_Success: llvm_unreachable("Conversion did not fail!"); - break; } - break; } + break; case FK_DefaultInitOfConst: if (Entity.getKind() == InitializedEntity::EK_Member && @@ -5126,7 +5687,7 @@ bool InitializationSequence::Diagnose(Sema &S, break; case FK_Incomplete: - S.RequireCompleteType(Kind.getLocation(), DestType, + S.RequireCompleteType(Kind.getLocation(), FailedIncompleteType, diag::err_init_incomplete_type); break; @@ -5135,11 +5696,62 @@ bool InitializationSequence::Diagnose(Sema &S, InitListExpr* InitList = cast<InitListExpr>(Args[0]); QualType DestType = Entity.getType(); InitListChecker DiagnoseInitList(S, Entity, InitList, - DestType, /*VerifyOnly=*/false); + DestType, /*VerifyOnly=*/false, + Kind.getKind() != InitializationKind::IK_DirectList || + !S.getLangOpts().CPlusPlus0x); assert(DiagnoseInitList.HadError() && "Inconsistent init list check result."); break; } + + case FK_PlaceholderType: { + // FIXME: Already diagnosed! + break; + } + + case FK_InitListElementCopyFailure: { + // Try to perform all copies again. + InitListExpr* InitList = cast<InitListExpr>(Args[0]); + unsigned NumInits = InitList->getNumInits(); + QualType DestType = Entity.getType(); + QualType E; + bool Success = S.isStdInitializerList(DestType, &E); + (void)Success; + assert(Success && "Where did the std::initializer_list go?"); + InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary( + S.Context.getConstantArrayType(E, + llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()), + NumInits), + ArrayType::Normal, 0)); + InitializedEntity Element = InitializedEntity::InitializeElement(S.Context, + 0, HiddenArray); + // Show at most 3 errors. Otherwise, you'd get a lot of errors for errors + // where the init list type is wrong, e.g. + // std::initializer_list<void*> list = { 1, 2, 3, 4, 5, 6, 7, 8 }; + // FIXME: Emit a note if we hit the limit? + int ErrorCount = 0; + for (unsigned i = 0; i < NumInits && ErrorCount < 3; ++i) { + Element.setElementIndex(i); + ExprResult Init = S.Owned(InitList->getInit(i)); + if (S.PerformCopyInitialization(Element, Init.get()->getExprLoc(), Init) + .isInvalid()) + ++ErrorCount; + } + break; + } + + case FK_ExplicitConstructor: { + S.Diag(Kind.getLocation(), diag::err_selected_explicit_constructor) + << Args[0]->getSourceRange(); + OverloadCandidateSet::iterator Best; + OverloadingResult Ovl + = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best); + (void)Ovl; + assert(Ovl == OR_Success && "Inconsistent overload resolution"); + CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function); + S.Diag(CtorDecl->getLocation(), diag::note_constructor_declared_here); + break; + } } PrintInitLocationNote(S, Entity); @@ -5237,6 +5849,27 @@ void InitializationSequence::dump(raw_ostream &OS) const { case FK_ListInitializationFailed: OS << "list initialization checker failure"; + break; + + case FK_VariableLengthArrayHasInitializer: + OS << "variable length array has an initializer"; + break; + + case FK_PlaceholderType: + OS << "initializer expression isn't contextually valid"; + break; + + case FK_ListConstructorOverloadFailed: + OS << "list constructor overloading failed"; + break; + + case FK_InitListElementCopyFailure: + OS << "copy construction of initializer list element failed"; + break; + + case FK_ExplicitConstructor: + OS << "list copy initialization chose explicit constructor"; + break; } OS << '\n'; return; @@ -5291,9 +5924,11 @@ void InitializationSequence::dump(raw_ostream &OS) const { case SK_QualificationConversionRValue: OS << "qualification conversion (rvalue)"; + break; case SK_QualificationConversionXValue: OS << "qualification conversion (xvalue)"; + break; case SK_QualificationConversionLValue: OS << "qualification conversion (lvalue)"; @@ -5313,6 +5948,14 @@ void InitializationSequence::dump(raw_ostream &OS) const { OS << "list initialization via constructor"; break; + case SK_UnwrapInitList: + OS << "unwrap reference initializer list"; + break; + + case SK_RewrapInitList: + OS << "rewrap reference initializer list"; + break; + case SK_ConstructorInitialization: OS << "constructor initialization"; break; @@ -5337,6 +5980,10 @@ void InitializationSequence::dump(raw_ostream &OS) const { OS << "array initialization"; break; + case SK_ParenthesizedArrayInit: + OS << "parenthesized array initialization"; + break; + case SK_PassByIndirectCopyRestore: OS << "pass by indirect copy and restore"; break; @@ -5348,6 +5995,10 @@ void InitializationSequence::dump(raw_ostream &OS) const { case SK_ProduceObjCObject: OS << "Objective-C object retension"; break; + + case SK_StdInitializerList: + OS << "std::initializer_list from initializer list"; + break; } } } @@ -5356,27 +6007,93 @@ void InitializationSequence::dump() const { dump(llvm::errs()); } -static void DiagnoseNarrowingInInitList( - Sema& S, QualType EntityType, const Expr *InitE, - bool Constant, const APValue &ConstantValue) { - if (Constant) { - S.Diag(InitE->getLocStart(), - S.getLangOptions().CPlusPlus0x && !S.getLangOptions().MicrosoftExt - ? diag::err_init_list_constant_narrowing - : diag::warn_init_list_constant_narrowing) - << InitE->getSourceRange() - << ConstantValue +static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq, + QualType EntityType, + const Expr *PreInit, + const Expr *PostInit) { + if (Seq.step_begin() == Seq.step_end() || PreInit->isValueDependent()) + return; + + // A narrowing conversion can only appear as the final implicit conversion in + // an initialization sequence. + const InitializationSequence::Step &LastStep = Seq.step_end()[-1]; + if (LastStep.Kind != InitializationSequence::SK_ConversionSequence) + return; + + const ImplicitConversionSequence &ICS = *LastStep.ICS; + const StandardConversionSequence *SCS = 0; + switch (ICS.getKind()) { + case ImplicitConversionSequence::StandardConversion: + SCS = &ICS.Standard; + break; + case ImplicitConversionSequence::UserDefinedConversion: + SCS = &ICS.UserDefined.After; + break; + case ImplicitConversionSequence::AmbiguousConversion: + case ImplicitConversionSequence::EllipsisConversion: + case ImplicitConversionSequence::BadConversion: + return; + } + + // Determine the type prior to the narrowing conversion. If a conversion + // operator was used, this may be different from both the type of the entity + // and of the pre-initialization expression. + QualType PreNarrowingType = PreInit->getType(); + if (Seq.step_begin() + 1 != Seq.step_end()) + PreNarrowingType = Seq.step_end()[-2].Type; + + // C++11 [dcl.init.list]p7: Check whether this is a narrowing conversion. + APValue ConstantValue; + QualType ConstantType; + switch (SCS->getNarrowingKind(S.Context, PostInit, ConstantValue, + ConstantType)) { + case NK_Not_Narrowing: + // No narrowing occurred. + return; + + case NK_Type_Narrowing: + // This was a floating-to-integer conversion, which is always considered a + // narrowing conversion even if the value is a constant and can be + // represented exactly as an integer. + S.Diag(PostInit->getLocStart(), + S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus0x? + diag::warn_init_list_type_narrowing + : S.isSFINAEContext()? + diag::err_init_list_type_narrowing_sfinae + : diag::err_init_list_type_narrowing) + << PostInit->getSourceRange() + << PreNarrowingType.getLocalUnqualifiedType() << EntityType.getLocalUnqualifiedType(); - } else - S.Diag(InitE->getLocStart(), - S.getLangOptions().CPlusPlus0x && !S.getLangOptions().MicrosoftExt - ? diag::err_init_list_variable_narrowing - : diag::warn_init_list_variable_narrowing) - << InitE->getSourceRange() - << InitE->getType().getLocalUnqualifiedType() + break; + + case NK_Constant_Narrowing: + // A constant value was narrowed. + S.Diag(PostInit->getLocStart(), + S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus0x? + diag::warn_init_list_constant_narrowing + : S.isSFINAEContext()? + diag::err_init_list_constant_narrowing_sfinae + : diag::err_init_list_constant_narrowing) + << PostInit->getSourceRange() + << ConstantValue.getAsString(S.getASTContext(), ConstantType) << EntityType.getLocalUnqualifiedType(); + break; - llvm::SmallString<128> StaticCast; + case NK_Variable_Narrowing: + // A variable's value may have been narrowed. + S.Diag(PostInit->getLocStart(), + S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus0x? + diag::warn_init_list_variable_narrowing + : S.isSFINAEContext()? + diag::err_init_list_variable_narrowing_sfinae + : diag::err_init_list_variable_narrowing) + << PostInit->getSourceRange() + << PreNarrowingType.getLocalUnqualifiedType() + << EntityType.getLocalUnqualifiedType(); + break; + } + + SmallString<128> StaticCast; llvm::raw_svector_ostream OS(StaticCast); OS << "static_cast<"; if (const TypedefType *TT = EntityType->getAs<TypedefType>()) { @@ -5387,18 +6104,18 @@ static void DiagnoseNarrowingInInitList( // getQualifiedNameAsString() includes non-machine-parsable components. OS << *TT->getDecl(); } else if (const BuiltinType *BT = EntityType->getAs<BuiltinType>()) - OS << BT->getName(S.getLangOptions()); + OS << BT->getName(S.getLangOpts()); else { // Oops, we didn't find the actual type of the variable. Don't emit a fixit // with a broken cast. return; } OS << ">("; - S.Diag(InitE->getLocStart(), diag::note_init_list_narrowing_override) - << InitE->getSourceRange() - << FixItHint::CreateInsertion(InitE->getLocStart(), OS.str()) + S.Diag(PostInit->getLocStart(), diag::note_init_list_narrowing_override) + << PostInit->getSourceRange() + << FixItHint::CreateInsertion(PostInit->getLocStart(), OS.str()) << FixItHint::CreateInsertion( - S.getPreprocessor().getLocForEndOfToken(InitE->getLocEnd()), ")"); + S.getPreprocessor().getLocForEndOfToken(PostInit->getLocEnd()), ")"); } //===----------------------------------------------------------------------===// @@ -5423,7 +6140,8 @@ ExprResult Sema::PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, - bool TopLevelOfInitList) { + bool TopLevelOfInitList, + bool AllowExplicit) { if (Init.isInvalid()) return ExprError(); @@ -5434,16 +6152,16 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity, EqualLoc = InitE->getLocStart(); InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(), - EqualLoc); + EqualLoc, + AllowExplicit); InitializationSequence Seq(*this, Entity, Kind, &InitE, 1); Init.release(); - bool Constant = false; - APValue Result; - if (TopLevelOfInitList && - Seq.endsWithNarrowing(Context, InitE, &Constant, &Result)) { - DiagnoseNarrowingInInitList(*this, Entity.getType(), InitE, - Constant, Result); - } - return Seq.Perform(*this, Entity, Kind, MultiExprArg(&InitE, 1)); + ExprResult Result = Seq.Perform(*this, Entity, Kind, MultiExprArg(&InitE, 1)); + + if (!Result.isInvalid() && TopLevelOfInitList) + DiagnoseNarrowingInInitList(*this, Seq, Entity.getType(), + InitE, Result.get()); + + return Result; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp new file mode 100644 index 0000000..6ef8d88 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp @@ -0,0 +1,820 @@ +//===--- SemaLambda.cpp - Semantic Analysis for C++11 Lambdas -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for C++ lambda expressions. +// +//===----------------------------------------------------------------------===// +#include "clang/Sema/DeclSpec.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/Lex/Preprocessor.h" +#include "clang/AST/ExprCXX.h" +using namespace clang; +using namespace sema; + +CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange, + bool KnownDependent) { + DeclContext *DC = CurContext; + while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext())) + DC = DC->getParent(); + + // Start constructing the lambda class. + CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, + IntroducerRange.getBegin(), + KnownDependent); + DC->addDecl(Class); + + return Class; +} + +/// \brief Determine whether the given context is or is enclosed in an inline +/// function. +static bool isInInlineFunction(const DeclContext *DC) { + while (!DC->isFileContext()) { + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) + if (FD->isInlined()) + return true; + + DC = DC->getLexicalParent(); + } + + return false; +} + +CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, + SourceRange IntroducerRange, + TypeSourceInfo *MethodType, + SourceLocation EndLoc, + llvm::ArrayRef<ParmVarDecl *> Params, + llvm::Optional<unsigned> ManglingNumber, + Decl *ContextDecl) { + // C++11 [expr.prim.lambda]p5: + // The closure type for a lambda-expression has a public inline function + // call operator (13.5.4) whose parameters and return type are described by + // the lambda-expression's parameter-declaration-clause and + // trailing-return-type respectively. + DeclarationName MethodName + = Context.DeclarationNames.getCXXOperatorName(OO_Call); + DeclarationNameLoc MethodNameLoc; + MethodNameLoc.CXXOperatorName.BeginOpNameLoc + = IntroducerRange.getBegin().getRawEncoding(); + MethodNameLoc.CXXOperatorName.EndOpNameLoc + = IntroducerRange.getEnd().getRawEncoding(); + CXXMethodDecl *Method + = CXXMethodDecl::Create(Context, Class, EndLoc, + DeclarationNameInfo(MethodName, + IntroducerRange.getBegin(), + MethodNameLoc), + MethodType->getType(), MethodType, + /*isStatic=*/false, + SC_None, + /*isInline=*/true, + /*isConstExpr=*/false, + EndLoc); + Method->setAccess(AS_public); + + // Temporarily set the lexical declaration context to the current + // context, so that the Scope stack matches the lexical nesting. + Method->setLexicalDeclContext(CurContext); + + // Add parameters. + if (!Params.empty()) { + Method->setParams(Params); + CheckParmsForFunctionDef(const_cast<ParmVarDecl **>(Params.begin()), + 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); + } + + // If we don't already have a mangling number for this lambda expression, + // allocate one now. + if (!ManglingNumber) { + ContextDecl = ExprEvalContexts.back().LambdaContextDecl; + + enum ContextKind { + Normal, + DefaultArgument, + DataMember, + StaticDataMember + } Kind = Normal; + + // Default arguments of member function parameters that appear in a class + // definition, as well as the initializers of data members, receive special + // treatment. Identify them. + if (ContextDecl) { + if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ContextDecl)) { + if (const DeclContext *LexicalDC + = Param->getDeclContext()->getLexicalParent()) + if (LexicalDC->isRecord()) + Kind = DefaultArgument; + } else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) { + if (Var->getDeclContext()->isRecord()) + Kind = StaticDataMember; + } else if (isa<FieldDecl>(ContextDecl)) { + Kind = DataMember; + } + } + + switch (Kind) { + case Normal: + if (CurContext->isDependentContext() || isInInlineFunction(CurContext)) + ManglingNumber = Context.getLambdaManglingNumber(Method); + else + ManglingNumber = 0; + + // There is no special context for this lambda. + ContextDecl = 0; + break; + + case StaticDataMember: + if (!CurContext->isDependentContext()) { + ManglingNumber = 0; + ContextDecl = 0; + break; + } + // Fall through to assign a mangling number. + + case DataMember: + case DefaultArgument: + ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext() + .getManglingNumber(Method); + break; + } + } + + Class->setLambdaMangling(*ManglingNumber, ContextDecl); + return Method; +} + +LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator, + SourceRange IntroducerRange, + LambdaCaptureDefault CaptureDefault, + bool ExplicitParams, + bool ExplicitResultType, + bool Mutable) { + PushLambdaScope(CallOperator->getParent(), CallOperator); + LambdaScopeInfo *LSI = getCurLambda(); + if (CaptureDefault == LCD_ByCopy) + LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval; + else if (CaptureDefault == LCD_ByRef) + LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref; + LSI->IntroducerRange = IntroducerRange; + LSI->ExplicitParams = ExplicitParams; + LSI->Mutable = Mutable; + + if (ExplicitResultType) { + LSI->ReturnType = CallOperator->getResultType(); + + if (!LSI->ReturnType->isDependentType() && + !LSI->ReturnType->isVoidType()) { + if (RequireCompleteType(CallOperator->getLocStart(), LSI->ReturnType, + diag::err_lambda_incomplete_result)) { + // Do nothing. + } else if (LSI->ReturnType->isObjCObjectOrInterfaceType()) { + Diag(CallOperator->getLocStart(), diag::err_lambda_objc_object_result) + << LSI->ReturnType; + } + } + } else { + LSI->HasImplicitReturnType = true; + } + + return LSI; +} + +void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) { + LSI->finishedExplicitCaptures(); +} + +void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) { + // Introduce our parameters into the function scope + for (unsigned p = 0, NumParams = CallOperator->getNumParams(); + p < NumParams; ++p) { + ParmVarDecl *Param = CallOperator->getParamDecl(p); + + // If this has an identifier, add it to the scope stack. + if (CurScope && Param->getIdentifier()) { + CheckShadow(CurScope, Param); + + PushOnScopeChains(Param, CurScope); + } + } +} + +void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, + Declarator &ParamInfo, + Scope *CurScope) { + // Determine if we're within a context where we know that the lambda will + // be dependent, because there are template parameters in scope. + bool KnownDependent = false; + if (Scope *TmplScope = CurScope->getTemplateParamParent()) + if (!TmplScope->decl_empty()) + KnownDependent = true; + + CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, KnownDependent); + + // Determine the signature of the call operator. + TypeSourceInfo *MethodTyInfo; + bool ExplicitParams = true; + bool ExplicitResultType = true; + SourceLocation EndLoc; + llvm::ArrayRef<ParmVarDecl *> Params; + if (ParamInfo.getNumTypeObjects() == 0) { + // C++11 [expr.prim.lambda]p4: + // If a lambda-expression does not include a lambda-declarator, it is as + // if the lambda-declarator were (). + FunctionProtoType::ExtProtoInfo EPI; + EPI.HasTrailingReturn = true; + EPI.TypeQuals |= DeclSpec::TQ_const; + QualType MethodTy = Context.getFunctionType(Context.DependentTy, + /*Args=*/0, /*NumArgs=*/0, EPI); + MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy); + ExplicitParams = false; + ExplicitResultType = false; + EndLoc = Intro.Range.getEnd(); + } else { + assert(ParamInfo.isFunctionDeclarator() && + "lambda-declarator is a function"); + DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo(); + + // C++11 [expr.prim.lambda]p5: + // This function call operator is declared const (9.3.1) if and only if + // the lambda-expression's parameter-declaration-clause is not followed + // by mutable. It is neither virtual nor declared volatile. [...] + if (!FTI.hasMutableQualifier()) + FTI.TypeQuals |= DeclSpec::TQ_const; + + MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope); + assert(MethodTyInfo && "no type from lambda-declarator"); + EndLoc = ParamInfo.getSourceRange().getEnd(); + + ExplicitResultType + = MethodTyInfo->getType()->getAs<FunctionType>()->getResultType() + != Context.DependentTy; + + TypeLoc TL = MethodTyInfo->getTypeLoc(); + FunctionProtoTypeLoc Proto = cast<FunctionProtoTypeLoc>(TL); + Params = llvm::ArrayRef<ParmVarDecl *>(Proto.getParmArray(), + Proto.getNumArgs()); + } + + CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, + MethodTyInfo, EndLoc, Params); + + if (ExplicitParams) + CheckCXXDefaultArguments(Method); + + // Attributes on the lambda apply to the method. + ProcessDeclAttributes(CurScope, Method, ParamInfo); + + // Introduce the function call operator as the current declaration context. + PushDeclContext(CurScope, Method); + + // Introduce the lambda scope. + LambdaScopeInfo *LSI + = enterLambdaScope(Method, Intro.Range, Intro.Default, ExplicitParams, + ExplicitResultType, + (Method->getTypeQualifiers() & Qualifiers::Const) == 0); + + // Handle explicit captures. + SourceLocation PrevCaptureLoc + = Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc; + for (llvm::SmallVector<LambdaCapture, 4>::const_iterator + 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)); + continue; + } + + // C++11 [expr.prim.lambda]p8: + // If a lambda-capture includes a capture-default that is =, the + // 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)); + continue; + } + + // C++11 [expr.prim.lambda]p12: + // If this is captured by a local lambda expression, its nearest + // enclosing function shall be a non-static member function. + QualType ThisCaptureType = getCurrentThisType(); + if (ThisCaptureType.isNull()) { + Diag(C->Loc, diag::err_this_capture) << true; + continue; + } + + CheckCXXThisCapture(C->Loc, /*Explicit=*/true); + continue; + } + + assert(C->Id && "missing identifier for capture"); + + // C++11 [expr.prim.lambda]p8: + // If a lambda-capture includes a capture-default that is &, the + // identifiers in the lambda-capture shall not be preceded by &. + // If a lambda-capture includes a capture-default that is =, [...] + // 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)); + 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)); + continue; + } + + DeclarationNameInfo Name(C->Id, C->Loc); + LookupResult R(*this, Name, LookupOrdinaryName); + LookupName(R, CurScope); + if (R.isAmbiguous()) + continue; + if (R.empty()) { + // FIXME: Disable corrections that would add qualification? + CXXScopeSpec ScopeSpec; + DeclFilterCCC<VarDecl> Validator; + if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator)) + continue; + } + + // C++11 [expr.prim.lambda]p10: + // The identifiers in a capture-list are looked up using the usual rules + // for unqualified name lookup (3.4.1); each such lookup shall find a + // variable with automatic storage duration declared in the reaching + // scope of the local lambda expression. + // + // Note that the 'reaching scope' check happens in tryCaptureVariable(). + VarDecl *Var = R.getAsSingle<VarDecl>(); + if (!Var) { + Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id; + continue; + } + + if (!Var->hasLocalStorage()) { + Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id; + Diag(Var->getLocation(), diag::note_previous_decl) << C->Id; + continue; + } + + // C++11 [expr.prim.lambda]p8: + // An identifier or this shall not appear more than once in a + // lambda-capture. + if (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)); + continue; + } + + // C++11 [expr.prim.lambda]p23: + // A capture followed by an ellipsis is a pack expansion (14.5.3). + SourceLocation EllipsisLoc; + if (C->EllipsisLoc.isValid()) { + if (Var->isParameterPack()) { + EllipsisLoc = C->EllipsisLoc; + } else { + Diag(C->EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << SourceRange(C->Loc); + + // Just ignore the ellipsis. + } + } else if (Var->isParameterPack()) { + Diag(C->Loc, diag::err_lambda_unexpanded_pack); + continue; + } + + TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef : + TryCapture_ExplicitByVal; + tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc); + } + finishLambdaExplicitCaptures(LSI); + + // Add lambda parameters into scope. + addLambdaParameters(Method, CurScope); + + // Enter a new evaluation context to insulate the lambda from any + // cleanups from the enclosing full-expression. + PushExpressionEvaluationContext(PotentiallyEvaluated); +} + +void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope, + bool IsInstantiation) { + // Leave the expression-evaluation context. + DiscardCleanupsInEvaluationContext(); + PopExpressionEvaluationContext(); + + // Leave the context of the lambda. + if (!IsInstantiation) + PopDeclContext(); + + // Finalize the lambda. + LambdaScopeInfo *LSI = getCurLambda(); + CXXRecordDecl *Class = LSI->Lambda; + Class->setInvalidDecl(); + SmallVector<Decl*, 4> Fields(Class->field_begin(), Class->field_end()); + ActOnFields(0, Class->getLocation(), Class, Fields, + SourceLocation(), SourceLocation(), 0); + CheckCompletedCXXClass(Class); + + PopFunctionScopeInfo(); +} + +/// \brief Add a lambda's conversion to function pointer, as described in +/// C++11 [expr.prim.lambda]p6. +static void addFunctionPointerConversion(Sema &S, + SourceRange IntroducerRange, + CXXRecordDecl *Class, + CXXMethodDecl *CallOperator) { + // Add the conversion to function pointer. + const FunctionProtoType *Proto + = CallOperator->getType()->getAs<FunctionProtoType>(); + QualType FunctionPtrTy; + QualType FunctionTy; + { + FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo(); + ExtInfo.TypeQuals = 0; + FunctionTy = S.Context.getFunctionType(Proto->getResultType(), + Proto->arg_type_begin(), + Proto->getNumArgs(), + ExtInfo); + FunctionPtrTy = S.Context.getPointerType(FunctionTy); + } + + FunctionProtoType::ExtProtoInfo ExtInfo; + ExtInfo.TypeQuals = Qualifiers::Const; + QualType ConvTy = S.Context.getFunctionType(FunctionPtrTy, 0, 0, ExtInfo); + + SourceLocation Loc = IntroducerRange.getBegin(); + DeclarationName Name + = S.Context.DeclarationNames.getCXXConversionFunctionName( + S.Context.getCanonicalType(FunctionPtrTy)); + DeclarationNameLoc NameLoc; + NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(FunctionPtrTy, + Loc); + CXXConversionDecl *Conversion + = CXXConversionDecl::Create(S.Context, Class, Loc, + DeclarationNameInfo(Name, Loc, NameLoc), + ConvTy, + S.Context.getTrivialTypeSourceInfo(ConvTy, + Loc), + /*isInline=*/false, /*isExplicit=*/false, + /*isConstexpr=*/false, + CallOperator->getBody()->getLocEnd()); + Conversion->setAccess(AS_public); + Conversion->setImplicit(true); + Class->addDecl(Conversion); + + // Add a non-static member function "__invoke" that will be the result of + // the conversion. + Name = &S.Context.Idents.get("__invoke"); + CXXMethodDecl *Invoke + = CXXMethodDecl::Create(S.Context, Class, Loc, + DeclarationNameInfo(Name, Loc), FunctionTy, + CallOperator->getTypeSourceInfo(), + /*IsStatic=*/true, SC_Static, /*IsInline=*/true, + /*IsConstexpr=*/false, + CallOperator->getBody()->getLocEnd()); + SmallVector<ParmVarDecl *, 4> InvokeParams; + for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) { + ParmVarDecl *From = CallOperator->getParamDecl(I); + InvokeParams.push_back(ParmVarDecl::Create(S.Context, Invoke, + From->getLocStart(), + From->getLocation(), + From->getIdentifier(), + From->getType(), + From->getTypeSourceInfo(), + From->getStorageClass(), + From->getStorageClassAsWritten(), + /*DefaultArg=*/0)); + } + Invoke->setParams(InvokeParams); + Invoke->setAccess(AS_private); + Invoke->setImplicit(true); + Class->addDecl(Invoke); +} + +/// \brief Add a lambda's conversion to block pointer. +static void addBlockPointerConversion(Sema &S, + SourceRange IntroducerRange, + CXXRecordDecl *Class, + CXXMethodDecl *CallOperator) { + const FunctionProtoType *Proto + = CallOperator->getType()->getAs<FunctionProtoType>(); + QualType BlockPtrTy; + { + FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo(); + ExtInfo.TypeQuals = 0; + QualType FunctionTy + = S.Context.getFunctionType(Proto->getResultType(), + Proto->arg_type_begin(), + Proto->getNumArgs(), + ExtInfo); + BlockPtrTy = S.Context.getBlockPointerType(FunctionTy); + } + + FunctionProtoType::ExtProtoInfo ExtInfo; + ExtInfo.TypeQuals = Qualifiers::Const; + QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, 0, 0, ExtInfo); + + SourceLocation Loc = IntroducerRange.getBegin(); + DeclarationName Name + = S.Context.DeclarationNames.getCXXConversionFunctionName( + S.Context.getCanonicalType(BlockPtrTy)); + DeclarationNameLoc NameLoc; + NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(BlockPtrTy, Loc); + CXXConversionDecl *Conversion + = CXXConversionDecl::Create(S.Context, Class, Loc, + DeclarationNameInfo(Name, Loc, NameLoc), + ConvTy, + S.Context.getTrivialTypeSourceInfo(ConvTy, Loc), + /*isInline=*/false, /*isExplicit=*/false, + /*isConstexpr=*/false, + CallOperator->getBody()->getLocEnd()); + Conversion->setAccess(AS_public); + Conversion->setImplicit(true); + Class->addDecl(Conversion); +} + +ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, + Scope *CurScope, + bool IsInstantiation) { + // Collect information from the lambda scope. + llvm::SmallVector<LambdaExpr::Capture, 4> Captures; + llvm::SmallVector<Expr *, 4> CaptureInits; + LambdaCaptureDefault CaptureDefault; + CXXRecordDecl *Class; + CXXMethodDecl *CallOperator; + SourceRange IntroducerRange; + bool ExplicitParams; + bool ExplicitResultType; + bool LambdaExprNeedsCleanups; + llvm::SmallVector<VarDecl *, 4> ArrayIndexVars; + llvm::SmallVector<unsigned, 4> ArrayIndexStarts; + { + LambdaScopeInfo *LSI = getCurLambda(); + CallOperator = LSI->CallOperator; + Class = LSI->Lambda; + IntroducerRange = LSI->IntroducerRange; + ExplicitParams = LSI->ExplicitParams; + ExplicitResultType = !LSI->HasImplicitReturnType; + LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups; + ArrayIndexVars.swap(LSI->ArrayIndexVars); + ArrayIndexStarts.swap(LSI->ArrayIndexStarts); + + // Translate captures. + for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) { + LambdaScopeInfo::Capture From = LSI->Captures[I]; + assert(!From.isBlockCapture() && "Cannot capture __block variables"); + bool IsImplicit = I >= LSI->NumExplicitCaptures; + + // Handle 'this' capture. + if (From.isThisCapture()) { + Captures.push_back(LambdaExpr::Capture(From.getLocation(), + IsImplicit, + LCK_This)); + CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(), + getCurrentThisType(), + /*isImplicit=*/true)); + continue; + } + + VarDecl *Var = From.getVariable(); + LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef; + Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit, + Kind, Var, From.getEllipsisLoc())); + CaptureInits.push_back(From.getCopyExpr()); + } + + switch (LSI->ImpCaptureStyle) { + case CapturingScopeInfo::ImpCap_None: + CaptureDefault = LCD_None; + break; + + case CapturingScopeInfo::ImpCap_LambdaByval: + CaptureDefault = LCD_ByCopy; + break; + + case CapturingScopeInfo::ImpCap_LambdaByref: + CaptureDefault = LCD_ByRef; + break; + + case CapturingScopeInfo::ImpCap_Block: + llvm_unreachable("block capture in lambda"); + break; + } + + // C++11 [expr.prim.lambda]p4: + // If a lambda-expression does not include a + // trailing-return-type, it is as if the trailing-return-type + // denotes the following type: + // FIXME: Assumes current resolution to core issue 975. + if (LSI->HasImplicitReturnType) { + // - if there are no return statements in the + // compound-statement, or all return statements return + // either an expression of type void or no expression or + // braced-init-list, the type void; + if (LSI->ReturnType.isNull()) { + LSI->ReturnType = Context.VoidTy; + } else { + // C++11 [expr.prim.lambda]p4: + // - if the compound-statement is of the form + // + // { attribute-specifier-seq[opt] return expression ; } + // + // the type of the returned expression after + // lvalue-to-rvalue conversion (4.1), array-to-pointer + // conver- sion (4.2), and function-to-pointer conversion + // (4.3); + // + // Since we're accepting the resolution to a post-C++11 core + // issue with a non-trivial extension, provide a warning (by + // default). + CompoundStmt *CompoundBody = cast<CompoundStmt>(Body); + if (!(CompoundBody->size() == 1 && + isa<ReturnStmt>(*CompoundBody->body_begin())) && + !Context.hasSameType(LSI->ReturnType, Context.VoidTy)) + Diag(IntroducerRange.getBegin(), + diag::ext_lambda_implies_void_return); + } + + // Create a function type with the inferred return type. + const FunctionProtoType *Proto + = CallOperator->getType()->getAs<FunctionProtoType>(); + QualType FunctionTy + = Context.getFunctionType(LSI->ReturnType, + Proto->arg_type_begin(), + Proto->getNumArgs(), + Proto->getExtProtoInfo()); + CallOperator->setType(FunctionTy); + } + + // C++ [expr.prim.lambda]p7: + // The lambda-expression's compound-statement yields the + // function-body (8.4) of the function call operator [...]. + ActOnFinishFunctionBody(CallOperator, Body, IsInstantiation); + CallOperator->setLexicalDeclContext(Class); + Class->addDecl(CallOperator); + PopExpressionEvaluationContext(); + + // C++11 [expr.prim.lambda]p6: + // The closure type for a lambda-expression with no lambda-capture + // has a public non-virtual non-explicit const conversion function + // to pointer to function having the same parameter and return + // types as the closure type's function call operator. + if (Captures.empty() && CaptureDefault == LCD_None) + addFunctionPointerConversion(*this, IntroducerRange, Class, + CallOperator); + + // Objective-C++: + // The closure type for a lambda-expression has a public non-virtual + // non-explicit const conversion function to a block pointer having the + // same parameter and return types as the closure type's function call + // operator. + if (getLangOpts().Blocks && getLangOpts().ObjC1) + addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator); + + // Finalize the lambda class. + SmallVector<Decl*, 4> Fields(Class->field_begin(), Class->field_end()); + ActOnFields(0, Class->getLocation(), Class, Fields, + SourceLocation(), SourceLocation(), 0); + CheckCompletedCXXClass(Class); + } + + if (LambdaExprNeedsCleanups) + ExprNeedsCleanups = true; + + LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, + CaptureDefault, Captures, + ExplicitParams, ExplicitResultType, + CaptureInits, ArrayIndexVars, + ArrayIndexStarts, Body->getLocEnd()); + + // C++11 [expr.prim.lambda]p2: + // A lambda-expression shall not appear in an unevaluated operand + // (Clause 5). + if (!CurContext->isDependentContext()) { + switch (ExprEvalContexts.back().Context) { + case Unevaluated: + // We don't actually diagnose this case immediately, because we + // could be within a context where we might find out later that + // the expression is potentially evaluated (e.g., for typeid). + ExprEvalContexts.back().Lambdas.push_back(Lambda); + break; + + case ConstantEvaluated: + case PotentiallyEvaluated: + case PotentiallyEvaluatedIfUsed: + break; + } + } + + return MaybeBindToTemporary(Lambda); +} + +ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, + SourceLocation ConvLocation, + CXXConversionDecl *Conv, + Expr *Src) { + // Make sure that the lambda call operator is marked used. + CXXRecordDecl *Lambda = Conv->getParent(); + CXXMethodDecl *CallOperator + = cast<CXXMethodDecl>( + *Lambda->lookup( + Context.DeclarationNames.getCXXOperatorName(OO_Call)).first); + CallOperator->setReferenced(); + CallOperator->setUsed(); + + ExprResult Init = PerformCopyInitialization( + InitializedEntity::InitializeBlock(ConvLocation, + Src->getType(), + /*NRVO=*/false), + CurrentLocation, Src); + if (!Init.isInvalid()) + Init = ActOnFinishFullExpr(Init.take()); + + if (Init.isInvalid()) + return ExprError(); + + // Create the new block to be returned. + BlockDecl *Block = BlockDecl::Create(Context, CurContext, ConvLocation); + + // Set the type information. + Block->setSignatureAsWritten(CallOperator->getTypeSourceInfo()); + Block->setIsVariadic(CallOperator->isVariadic()); + Block->setBlockMissingReturnType(false); + + // Add parameters. + SmallVector<ParmVarDecl *, 4> BlockParams; + for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) { + ParmVarDecl *From = CallOperator->getParamDecl(I); + BlockParams.push_back(ParmVarDecl::Create(Context, Block, + From->getLocStart(), + From->getLocation(), + From->getIdentifier(), + From->getType(), + From->getTypeSourceInfo(), + From->getStorageClass(), + From->getStorageClassAsWritten(), + /*DefaultArg=*/0)); + } + Block->setParams(BlockParams); + + Block->setIsConversionFromLambda(true); + + // Add capture. The capture uses a fake variable, which doesn't correspond + // to any actual memory location. However, the initializer copy-initializes + // the lambda object. + TypeSourceInfo *CapVarTSI = + Context.getTrivialTypeSourceInfo(Src->getType()); + VarDecl *CapVar = VarDecl::Create(Context, Block, ConvLocation, + ConvLocation, 0, + Src->getType(), CapVarTSI, + SC_None, SC_None); + BlockDecl::Capture Capture(/*Variable=*/CapVar, /*ByRef=*/false, + /*Nested=*/false, /*Copy=*/Init.take()); + Block->setCaptures(Context, &Capture, &Capture + 1, + /*CapturesCXXThis=*/false); + + // Add a fake function body to the block. IR generation is responsible + // for filling in the actual body, which cannot be expressed as an AST. + Block->setBody(new (Context) CompoundStmt(Context, 0, 0, + ConvLocation, + ConvLocation)); + + // Create the block literal expression. + Expr *BuildBlock = new (Context) BlockExpr(Block, Conv->getConversionType()); + ExprCleanupObjects.push_back(Block); + ExprNeedsCleanups = true; + + return BuildBlock; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp index d5bee1d..966eb90 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp @@ -25,26 +25,28 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclLookups.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/LangOptions.h" -#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/TinyPtrVector.h" +#include "llvm/ADT/edit_distance.h" #include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <iterator> #include <limits> #include <list> +#include <map> #include <set> -#include <vector> -#include <iterator> #include <utility> -#include <algorithm> -#include <map> +#include <vector> using namespace clang; using namespace sema; @@ -105,13 +107,15 @@ namespace { assert(InnermostFileDC && InnermostFileDC->isFileContext()); for (; S; S = S->getParent()) { - if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) { - DeclContext *EffectiveDC = (Ctx->isFileContext() ? Ctx : InnermostFileDC); - visit(Ctx, EffectiveDC); - } else { + // C++ [namespace.udir]p1: + // A using-directive shall not appear in class scope, but may + // appear in namespace scope or in block scope. + DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()); + 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); } @@ -280,7 +284,7 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind, } void LookupResult::configure() { - IDNS = getIDNS(LookupKind, SemaRef.getLangOptions().CPlusPlus, + IDNS = getIDNS(LookupKind, SemaRef.getLangOpts().CPlusPlus, isForRedeclaration()); // If we're looking for one of the allocation or deallocation @@ -301,7 +305,9 @@ void LookupResult::configure() { } } -void LookupResult::sanity() const { +void LookupResult::sanityImpl() const { + // Note that this function is never called by NDEBUG builds. See + // LookupResult::sanity(). assert(ResultKind != NotFound || Decls.size() == 0); assert(ResultKind != Found || Decls.size() == 1); assert(ResultKind != FoundOverloaded || Decls.size() > 1 || @@ -321,6 +327,12 @@ void LookupResult::deletePaths(CXXBasePaths *Paths) { delete Paths; } +static NamedDecl *getVisibleDecl(NamedDecl *D); + +NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const { + return getVisibleDecl(D); +} + /// Resolves the result kind of this lookup. void LookupResult::resolveKind() { unsigned N = Decls.size(); @@ -488,7 +500,7 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) { if (unsigned BuiltinID = II->getBuiltinID()) { // In C++, we don't have any predefined library functions like // 'malloc'. Instead, we'll just error. - if (S.getLangOptions().CPlusPlus && + if (S.getLangOpts().CPlusPlus && S.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) return false; @@ -518,10 +530,6 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) { /// the class at this point. static bool CanDeclareSpecialMemberFunction(ASTContext &Context, const CXXRecordDecl *Class) { - // Don't do it if the class is invalid. - if (Class->isInvalidDecl()) - return false; - // We need to have a definition for the class. if (!Class->getDefinition() || Class->isDependentContext()) return false; @@ -550,7 +558,7 @@ void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) { if (!Class->hasDeclaredCopyAssignment()) DeclareImplicitCopyAssignment(Class); - if (getLangOptions().CPlusPlus0x) { + if (getLangOpts().CPlusPlus0x) { // If the move constructor has not yet been declared, do so now. if (Class->needsImplicitMoveConstructor()) DeclareImplicitMoveConstructor(Class); // might not actually do it @@ -601,7 +609,7 @@ static void DeclareImplicitMemberFunctionsWithName(Sema &S, S.DeclareImplicitDefaultConstructor(Class); if (!Record->hasDeclaredCopyConstructor()) S.DeclareImplicitCopyConstructor(Class); - if (S.getLangOptions().CPlusPlus0x && + if (S.getLangOpts().CPlusPlus0x && Record->needsImplicitMoveConstructor()) S.DeclareImplicitMoveConstructor(Class); } @@ -624,7 +632,7 @@ static void DeclareImplicitMemberFunctionsWithName(Sema &S, CXXRecordDecl *Class = const_cast<CXXRecordDecl *>(Record); if (!Record->hasDeclaredCopyAssignment()) S.DeclareImplicitCopyAssignment(Class); - if (S.getLangOptions().CPlusPlus0x && + if (S.getLangOpts().CPlusPlus0x && Record->needsImplicitMoveAssignment()) S.DeclareImplicitMoveAssignment(Class); } @@ -642,14 +650,14 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { bool Found = false; // Lazily declare C++ special member functions. - if (S.getLangOptions().CPlusPlus) + if (S.getLangOpts().CPlusPlus) DeclareImplicitMemberFunctionsWithName(S, R.getLookupName(), DC); // Perform lookup into this declaration context. DeclContext::lookup_const_iterator I, E; for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) { NamedDecl *D = *I; - if (R.isAcceptableDecl(D)) { + if ((D = R.getAcceptableDecl(D))) { R.addDecl(D); Found = true; } @@ -830,7 +838,7 @@ static std::pair<DeclContext *, bool> findOuterContext(Scope *S) { } bool Sema::CppLookupName(LookupResult &R, Scope *S) { - assert(getLangOptions().CPlusPlus && "Can perform only C++ lookup"); + assert(getLangOpts().CPlusPlus && "Can perform only C++ lookup"); DeclarationName Name = R.getLookupName(); @@ -875,9 +883,9 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // Check whether the IdResolver has anything in this scope. bool Found = false; for (; I != IEnd && S->isDeclScope(*I); ++I) { - if (R.isAcceptableDecl(*I)) { + if (NamedDecl *ND = R.getAcceptableDecl(*I)) { Found = true; - R.addDecl(*I); + R.addDecl(ND); } } if (Found) { @@ -926,8 +934,8 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable( Name.getAsIdentifierInfo(), ClassDeclared)) { - if (R.isAcceptableDecl(Ivar)) { - R.addDecl(Ivar); + if (NamedDecl *ND = R.getAcceptableDecl(Ivar)) { + R.addDecl(ND); R.resolveKind(); return true; } @@ -977,13 +985,13 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // Check whether the IdResolver has anything in this scope. bool Found = false; for (; I != IEnd && S->isDeclScope(*I); ++I) { - if (R.isAcceptableDecl(*I)) { + if (NamedDecl *ND = R.getAcceptableDecl(*I)) { // We found something. Look for anything else in our scope // with this same name and in an acceptable identifier // namespace, so that we can construct an overload set if we // need to. Found = true; - R.addDecl(*I); + R.addDecl(ND); } } @@ -1047,6 +1055,29 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { return !R.empty(); } +/// \brief Retrieve the visible declaration corresponding to D, if any. +/// +/// This routine determines whether the declaration D is visible in the current +/// module, with the current imports. If not, it checks whether any +/// redeclaration of D is visible, and if so, returns that declaration. +/// +/// \returns D, or a visible previous declaration of D, whichever is more recent +/// and visible. If no declaration of D is visible, returns null. +static NamedDecl *getVisibleDecl(NamedDecl *D) { + if (LookupResult::isVisible(D)) + return D; + + for (Decl::redecl_iterator RD = D->redecls_begin(), RDEnd = D->redecls_end(); + RD != RDEnd; ++RD) { + if (NamedDecl *ND = dyn_cast<NamedDecl>(*RD)) { + if (LookupResult::isVisible(ND)) + return ND; + } + } + + return 0; +} + /// @brief Perform unqualified name lookup starting from a given /// scope. /// @@ -1084,7 +1115,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { LookupNameKind NameKind = R.getLookupKind(); - if (!getLangOptions().CPlusPlus) { + if (!getLangOpts().CPlusPlus) { // Unqualified name lookup in C/Objective-C is purely lexical, so // search in the declarations attached to the name. if (NameKind == Sema::LookupRedeclarationWithLinkage) { @@ -1123,29 +1154,58 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { !isa<ImplicitParamDecl>(*I)) continue; - R.addDecl(*I); - - if ((*I)->getAttr<OverloadableAttr>()) { - // If this declaration has the "overloadable" attribute, we - // might have a set of overloaded functions. - - // Figure out what scope the identifier is in. - while (!(S->getFlags() & Scope::DeclScope) || - !S->isDeclScope(*I)) + // If this declaration is module-private and it came from an AST + // file, we can't see it. + NamedDecl *D = R.isHiddenDeclarationVisible()? *I : getVisibleDecl(*I); + if (!D) + continue; + + R.addDecl(D); + + // Check whether there are any other declarations with the same name + // and in the same scope. + if (I != IEnd) { + // Find the scope in which this declaration was declared (if it + // actually exists in a Scope). + while (S && !S->isDeclScope(D)) S = S->getParent(); - - // Find the last declaration in this scope (with the same - // name, naturally). + + // If the scope containing the declaration is the translation unit, + // then we'll need to perform our checks based on the matching + // DeclContexts rather than matching scopes. + if (S && isNamespaceOrTranslationUnitScope(S)) + S = 0; + + // Compute the DeclContext, if we need it. + DeclContext *DC = 0; + if (!S) + DC = (*I)->getDeclContext()->getRedeclContext(); + IdentifierResolver::iterator LastI = I; for (++LastI; LastI != IEnd; ++LastI) { - if (!S->isDeclScope(*LastI)) - break; - R.addDecl(*LastI); + if (S) { + // Match based on scope. + if (!S->isDeclScope(*LastI)) + break; + } else { + // Match based on DeclContext. + DeclContext *LastDC + = (*LastI)->getDeclContext()->getRedeclContext(); + if (!LastDC->Equals(DC)) + break; + } + + // If the declaration isn't in the right namespace, skip it. + if (!(*LastI)->isInIdentifierNamespace(IDNS)) + continue; + + D = R.isHiddenDeclarationVisible()? *LastI : getVisibleDecl(*LastI); + if (D) + R.addDecl(D); } - } - - R.resolveKind(); + R.resolveKind(); + } return true; } } else { @@ -1203,7 +1263,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, if (I == E) return false; // We have at least added all these contexts to the queue. - llvm::DenseSet<DeclContext*> Visited; + llvm::SmallPtrSet<DeclContext*, 8> Visited; Visited.insert(StartDC); // We have not yet looked into these namespaces, much less added @@ -1214,7 +1274,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, // with its using-children. for (; I != E; ++I) { NamespaceDecl *ND = (*I)->getNominatedNamespace()->getOriginalNamespace(); - if (Visited.insert(ND).second) + if (Visited.insert(ND)) Queue.push_back(ND); } @@ -1263,7 +1323,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, for (llvm::tie(I,E) = ND->getUsingDirectives(); I != E; ++I) { NamespaceDecl *Nom = (*I)->getNominatedNamespace(); - if (Visited.insert(Nom).second) + if (Visited.insert(Nom)) Queue.push_back(Nom); } } @@ -1354,8 +1414,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, assert((!isa<TagDecl>(LookupCtx) || LookupCtx->isDependentContext() || cast<TagDecl>(LookupCtx)->isCompleteDefinition() || - Context.getTypeDeclType(cast<TagDecl>(LookupCtx))->getAs<TagType>() - ->isBeingDefined()) && + cast<TagDecl>(LookupCtx)->isBeingDefined()) && "Declaration context must already be complete!"); // Perform qualified name lookup into the LookupCtx. @@ -1561,13 +1620,14 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, return false; R.setContextRange(SS->getRange()); - return LookupQualifiedName(R, DC); } // We could not resolve the scope specified to a specific declaration // context, which means that SS refers to an unknown specialization. // Name lookup can't find anything in this case. + R.setNotFoundInCurrentInstantiation(); + R.setContextRange(SS->getRange()); return false; } @@ -1673,7 +1733,6 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { } llvm_unreachable("unknown ambiguity kind"); - return true; } namespace { @@ -2022,7 +2081,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { /// namespaces searched by argument-dependent lookup /// (C++ [basic.lookup.argdep]) for a given set of arguments. void -Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, +Sema::FindAssociatedClassesAndNamespaces(llvm::ArrayRef<Expr *> Args, AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses) { AssociatedNamespaces.clear(); @@ -2037,7 +2096,7 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, // classes is determined entirely by the types of the function // arguments (and the namespace of any template template // argument). - for (unsigned ArgIdx = 0; ArgIdx != NumArgs; ++ArgIdx) { + for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) { Expr *Arg = Args[ArgIdx]; if (Arg->getType() != Context.OverloadTy) { @@ -2124,9 +2183,10 @@ NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name, /// \brief Find the protocol with the given name, if any. ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II, - SourceLocation IdLoc) { + SourceLocation IdLoc, + RedeclarationKind Redecl) { Decl *D = LookupSingleName(TUScope, II, IdLoc, - LookupObjCProtocolName); + LookupObjCProtocolName, Redecl); return cast_or_null<ObjCProtocolDecl>(D); } @@ -2215,8 +2275,9 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, CXXDestructorDecl *DD = RD->getDestructor(); assert(DD && "record without a destructor"); Result->setMethod(DD); - Result->setSuccess(DD->isDeleted()); - Result->setConstParamMatch(false); + Result->setKind(DD->isDeleted() ? + SpecialMemberOverloadResult::NoMemberOrDeleted : + SpecialMemberOverloadResult::SuccessNonConst); return Result; } @@ -2237,13 +2298,13 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, Name = Context.DeclarationNames.getCXXConstructorName(CanTy); if (!RD->hasDeclaredCopyConstructor()) DeclareImplicitCopyConstructor(RD); - if (getLangOptions().CPlusPlus0x && RD->needsImplicitMoveConstructor()) + if (getLangOpts().CPlusPlus0x && RD->needsImplicitMoveConstructor()) DeclareImplicitMoveConstructor(RD); } else { Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); if (!RD->hasDeclaredCopyAssignment()) DeclareImplicitCopyAssignment(RD); - if (getLangOptions().CPlusPlus0x && RD->needsImplicitMoveAssignment()) + if (getLangOpts().CPlusPlus0x && RD->needsImplicitMoveAssignment()) DeclareImplicitMoveAssignment(RD); } @@ -2286,7 +2347,8 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, // will always be a (possibly implicit) declaration to shadow any others. OverloadCandidateSet OCS((SourceLocation())); DeclContext::lookup_iterator I, E; - Result->setConstParamMatch(false); + SpecialMemberOverloadResult::Kind SuccessKind = + SpecialMemberOverloadResult::SuccessNonConst; llvm::tie(I, E) = RD->lookup(Name); assert((I != E) && @@ -2311,10 +2373,11 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(Cand)) { if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) AddMethodCandidate(M, DeclAccessPair::make(M, AS_public), RD, ThisTy, - Classification, &Arg, NumArgs, OCS, true); + Classification, llvm::makeArrayRef(&Arg, NumArgs), + OCS, true); else - AddOverloadCandidate(M, DeclAccessPair::make(M, AS_public), &Arg, - NumArgs, OCS, true); + AddOverloadCandidate(M, DeclAccessPair::make(M, AS_public), + llvm::makeArrayRef(&Arg, NumArgs), OCS, true); // Here we're looking for a const parameter to speed up creation of // implicit copy methods. @@ -2324,17 +2387,19 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, QualType ArgType = M->getType()->getAs<FunctionProtoType>()->getArgType(0); if (!ArgType->isReferenceType() || ArgType->getPointeeType().isConstQualified()) - Result->setConstParamMatch(true); + SuccessKind = SpecialMemberOverloadResult::SuccessConst; } } else if (FunctionTemplateDecl *Tmpl = dyn_cast<FunctionTemplateDecl>(Cand)) { if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) AddMethodTemplateCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public), - RD, 0, ThisTy, Classification, &Arg, NumArgs, + RD, 0, ThisTy, Classification, + llvm::makeArrayRef(&Arg, NumArgs), OCS, true); else AddTemplateOverloadCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public), - 0, &Arg, NumArgs, OCS, true); + 0, llvm::makeArrayRef(&Arg, NumArgs), + OCS, true); } else { assert(isa<UsingDecl>(Cand) && "illegal Kind of operator = Decl"); } @@ -2344,18 +2409,22 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, switch (OCS.BestViableFunction(*this, SourceLocation(), Best)) { case OR_Success: Result->setMethod(cast<CXXMethodDecl>(Best->Function)); - Result->setSuccess(true); + Result->setKind(SuccessKind); break; case OR_Deleted: Result->setMethod(cast<CXXMethodDecl>(Best->Function)); - Result->setSuccess(false); + Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted); break; case OR_Ambiguous: + Result->setMethod(0); + Result->setKind(SpecialMemberOverloadResult::Ambiguous); + break; + case OR_No_Viable_Function: Result->setMethod(0); - Result->setSuccess(false); + Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted); break; } @@ -2404,7 +2473,7 @@ DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) { DeclareImplicitDefaultConstructor(Class); if (!Class->hasDeclaredCopyConstructor()) DeclareImplicitCopyConstructor(Class); - if (getLangOptions().CPlusPlus0x && Class->needsImplicitMoveConstructor()) + if (getLangOpts().CPlusPlus0x && Class->needsImplicitMoveConstructor()) DeclareImplicitMoveConstructor(Class); } @@ -2460,6 +2529,105 @@ CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) { false, false)->getMethod()); } +/// LookupLiteralOperator - Determine which literal operator should be used for +/// a user-defined literal, per C++11 [lex.ext]. +/// +/// Normal overload resolution is not used to select which literal operator to +/// call for a user-defined literal. Look up the provided literal operator name, +/// and filter the results to the appropriate set for the given argument types. +Sema::LiteralOperatorLookupResult +Sema::LookupLiteralOperator(Scope *S, LookupResult &R, + ArrayRef<QualType> ArgTys, + bool AllowRawAndTemplate) { + LookupName(R, S); + assert(R.getResultKind() != LookupResult::Ambiguous && + "literal operator lookup can't be ambiguous"); + + // Filter the lookup results appropriately. + LookupResult::Filter F = R.makeFilter(); + + bool FoundTemplate = false; + bool FoundRaw = false; + bool FoundExactMatch = false; + + while (F.hasNext()) { + Decl *D = F.next(); + if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) + D = USD->getTargetDecl(); + + bool IsTemplate = isa<FunctionTemplateDecl>(D); + bool IsRaw = false; + bool IsExactMatch = false; + + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + if (FD->getNumParams() == 1 && + FD->getParamDecl(0)->getType()->getAs<PointerType>()) + IsRaw = true; + else { + IsExactMatch = true; + for (unsigned ArgIdx = 0; ArgIdx != ArgTys.size(); ++ArgIdx) { + QualType ParamTy = FD->getParamDecl(ArgIdx)->getType(); + if (!Context.hasSameUnqualifiedType(ArgTys[ArgIdx], ParamTy)) { + IsExactMatch = false; + break; + } + } + } + } + + if (IsExactMatch) { + FoundExactMatch = true; + AllowRawAndTemplate = false; + if (FoundRaw || FoundTemplate) { + // Go through again and remove the raw and template decls we've + // already found. + F.restart(); + FoundRaw = FoundTemplate = false; + } + } else if (AllowRawAndTemplate && (IsTemplate || IsRaw)) { + FoundTemplate |= IsTemplate; + FoundRaw |= IsRaw; + } else { + F.erase(); + } + } + + F.done(); + + // C++11 [lex.ext]p3, p4: If S contains a literal operator with a matching + // parameter type, that is used in preference to a raw literal operator + // or literal operator template. + if (FoundExactMatch) + return LOLR_Cooked; + + // C++11 [lex.ext]p3, p4: S shall contain a raw literal operator or a literal + // 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)); + } + return LOLR_Error; + } + + if (FoundRaw) + return LOLR_Raw; + + if (FoundTemplate) + return LOLR_Template; + + // Didn't find anything we could use. + Diag(R.getNameLoc(), diag::err_ovl_no_viable_literal_operator) + << R.getLookupName() << (int)ArgTys.size() << ArgTys[0] + << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRawAndTemplate; + return LOLR_Error; +} + void ADLResult::insert(NamedDecl *New) { NamedDecl *&Old = Decls[cast<NamedDecl>(New->getCanonicalDecl())]; @@ -2482,7 +2650,7 @@ void ADLResult::insert(NamedDecl *New) { FunctionDecl *Cursor = NewFD; while (true) { - Cursor = Cursor->getPreviousDeclaration(); + Cursor = Cursor->getPreviousDecl(); // If we got to the end without finding OldFD, OldFD is the newer // declaration; leave things as they are. @@ -2498,14 +2666,15 @@ void ADLResult::insert(NamedDecl *New) { } void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, - Expr **Args, unsigned NumArgs, + SourceLocation Loc, + llvm::ArrayRef<Expr *> Args, ADLResult &Result, bool StdNamespaceIsAssociated) { // Find all of the associated namespaces and classes based on the // arguments we have. AssociatedNamespaceSet AssociatedNamespaces; AssociatedClassSet AssociatedClasses; - FindAssociatedClassesAndNamespaces(Args, NumArgs, + FindAssociatedClassesAndNamespaces(Args, AssociatedNamespaces, AssociatedClasses); if (StdNamespaceIsAssociated && StdNamespace) @@ -2514,10 +2683,17 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, QualType T1, T2; if (Operator) { T1 = Args[0]->getType(); - if (NumArgs >= 2) + if (Args.size() >= 2) T2 = Args[1]->getType(); } + // Try to complete all associated classes, in case they contain a + // declaration of a friend function. + for (AssociatedClassSet::iterator C = AssociatedClasses.begin(), + CEnd = AssociatedClasses.end(); + C != CEnd; ++C) + RequireCompleteType(Loc, Context.getRecordType(*C), 0); + // 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 @@ -2700,42 +2876,15 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, Result.getSema().ForceDeclarationOfImplicitMembers(Class); // Enumerate all of the results in this context. - for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx; - CurCtx = CurCtx->getNextContext()) { - for (DeclContext::decl_iterator D = CurCtx->decls_begin(), - DEnd = CurCtx->decls_end(); - D != DEnd; ++D) { - if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) { - if (Result.isAcceptableDecl(ND)) { + for (DeclContext::all_lookups_iterator L = Ctx->lookups_begin(), + LEnd = Ctx->lookups_end(); + L != LEnd; ++L) { + for (DeclContext::lookup_result R = *L; R.first != R.second; ++R.first) { + if (NamedDecl *ND = dyn_cast<NamedDecl>(*R.first)) { + if ((ND = Result.getAcceptableDecl(ND))) { Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); Visited.add(ND); } - } else if (ObjCForwardProtocolDecl *ForwardProto - = dyn_cast<ObjCForwardProtocolDecl>(*D)) { - for (ObjCForwardProtocolDecl::protocol_iterator - P = ForwardProto->protocol_begin(), - PEnd = ForwardProto->protocol_end(); - P != PEnd; - ++P) { - if (Result.isAcceptableDecl(*P)) { - Consumer.FoundDecl(*P, Visited.checkHidden(*P), Ctx, InBaseClass); - Visited.add(*P); - } - } - } else if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D)) { - ObjCInterfaceDecl *IFace = Class->getForwardInterfaceDecl(); - if (Result.isAcceptableDecl(IFace)) { - Consumer.FoundDecl(IFace, Visited.checkHidden(IFace), Ctx, - InBaseClass); - Visited.add(IFace); - } - } - - // Visit transparent contexts and inline namespaces inside this context. - if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D)) { - if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace()) - LookupVisibleDecls(InnerCtx, Result, QualifiedNameLookup, InBaseClass, - Consumer, Visited); } } } @@ -2826,7 +2975,7 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, if (IFace->getImplementation()) { ShadowContextRAII Shadow(Visited); LookupVisibleDecls(IFace->getImplementation(), Result, - QualifiedNameLookup, true, Consumer, Visited); + QualifiedNameLookup, InBaseClass, Consumer, Visited); } } else if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Ctx)) { for (ObjCProtocolDecl::protocol_iterator I = Protocol->protocol_begin(), @@ -2867,7 +3016,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); D != DEnd; ++D) { if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) - if (Result.isAcceptableDecl(ND)) { + if ((ND = Result.getAcceptableDecl(ND))) { Consumer.FoundDecl(ND, Visited.checkHidden(ND), 0, false); Visited.add(ND); } @@ -2946,7 +3095,7 @@ void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind, // unqualified name lookup. Scope *Initial = S; UnqualUsingDirectiveSet UDirs; - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { // Find the first namespace or translation-unit scope. while (S && !isNamespaceOrTranslationUnitScope(S)) S = S->getParent(); @@ -3031,15 +3180,11 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer { /// whether there is a keyword with this name. TypoEditDistanceMap BestResults; - /// \brief The worst of the best N edit distances found so far. - unsigned MaxEditDistance; - Sema &SemaRef; public: explicit TypoCorrectionConsumer(Sema &SemaRef, IdentifierInfo *Typo) : Typo(Typo->getName()), - MaxEditDistance((std::numeric_limits<unsigned>::max)()), SemaRef(SemaRef) { } ~TypoCorrectionConsumer() { @@ -3070,12 +3215,12 @@ public: return (*BestResults.begin()->second)[Name]; } - unsigned getMaxEditDistance() const { - return MaxEditDistance; - } + unsigned getBestEditDistance(bool Normalized) { + if (BestResults.empty()) + return (std::numeric_limits<unsigned>::max)(); - unsigned getBestEditDistance() { - return (BestResults.empty()) ? MaxEditDistance : BestResults.begin()->first; + unsigned BestED = BestResults.begin()->first; + return Normalized ? TypoCorrection::NormalizeEditDistance(BestED) : BestED; } }; @@ -3101,40 +3246,22 @@ void TypoCorrectionConsumer::FoundName(StringRef Name) { // 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 > MaxEditDistance || (MinED && Typo.size() / MinED < 3)) + if (MinED && Typo.size() / MinED < 3) return; // Compute an upper bound on the allowable edit distance, so that the // edit-distance algorithm can short-circuit. - unsigned UpperBound = - std::min(unsigned((Typo.size() + 2) / 3), MaxEditDistance); + unsigned UpperBound = (Typo.size() + 2) / 3; // Compute the edit distance between the typo and the name of this - // entity. If this edit distance is not worse than the best edit - // distance we've seen so far, add it to the list of results. - unsigned ED = Typo.edit_distance(Name, true, UpperBound); - - if (ED > MaxEditDistance) { - // This result is worse than the best results we've seen so far; - // ignore it. - return; - } - - addName(Name, NULL, ED); + // entity, and add the identifier to the list of results. + addName(Name, NULL, Typo.edit_distance(Name, true, UpperBound)); } void TypoCorrectionConsumer::addKeywordResult(StringRef Keyword) { - // Compute the edit distance between the typo and this keyword. - // If this edit distance is not worse than the best edit - // distance we've seen so far, add it to the list of results. - unsigned ED = Typo.edit_distance(Keyword); - if (ED > MaxEditDistance) { - // This result is worse than the best results we've seen so far; - // ignore it. - return; - } - - addName(Keyword, NULL, ED, NULL, true); + // Compute the edit distance between the typo and this keyword, + // and add the keyword to the list of results. + addName(Keyword, NULL, Typo.edit_distance(Keyword), NULL, true); } void TypoCorrectionConsumer::addName(StringRef Name, @@ -3149,7 +3276,7 @@ void TypoCorrectionConsumer::addName(StringRef Name, void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) { StringRef Name = Correction.getCorrectionAsIdentifierInfo()->getName(); - TypoResultsMap *& Map = BestResults[Correction.getEditDistance()]; + TypoResultsMap *& Map = BestResults[Correction.getEditDistance(false)]; if (!Map) Map = new TypoResultsMap; @@ -3158,8 +3285,8 @@ void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) { // FIXME: The following should be rolled up into an operator< on // TypoCorrection with a more principled definition. CurrentCorrection.isKeyword() < Correction.isKeyword() || - Correction.getAsString(SemaRef.getLangOptions()) < - CurrentCorrection.getAsString(SemaRef.getLangOptions())) + Correction.getAsString(SemaRef.getLangOpts()) < + CurrentCorrection.getAsString(SemaRef.getLangOpts())) CurrentCorrection = Correction; while (BestResults.size() > MaxTypoDistanceResultSets) { @@ -3170,6 +3297,47 @@ void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) { } } +// 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(); + + const IdentifierInfo *II = NULL; + + switch (NNS->getKind()) { + case NestedNameSpecifier::Identifier: + II = NNS->getAsIdentifier(); + break; + + 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 { class SpecifierInfo { @@ -3188,6 +3356,8 @@ typedef SmallVector<SpecifierInfo, 16> SpecifierInfoList; class NamespaceSpecifierSet { ASTContext &Context; DeclContextList CurContextChain; + SmallVector<const IdentifierInfo*, 4> CurContextIdentifiers; + SmallVector<const IdentifierInfo*, 4> CurNameSpecifierIdentifiers; bool isSorted; SpecifierInfoList Specifiers; @@ -3201,9 +3371,23 @@ class NamespaceSpecifierSet { void SortNamespaces(); public: - explicit NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext) + NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext, + CXXScopeSpec *CurScopeSpec) : Context(Context), CurContextChain(BuildContextChain(CurContext)), - isSorted(true) {} + isSorted(true) { + if (CurScopeSpec && CurScopeSpec->getScopeRep()) + getNestedNameSpecifierIdentifiers(CurScopeSpec->getScopeRep(), + CurNameSpecifierIdentifiers); + // Build the list of identifiers that would be used for an absolute + // (from the global context) NestedNameSpecifier refering 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()); + } + } /// \brief Add the namespace to the set, computing the corresponding /// NestedNameSpecifier and its distance in the process. @@ -3241,7 +3425,7 @@ void NamespaceSpecifierSet::SortNamespaces() { Specifiers.clear(); for (SmallVector<unsigned, 4>::iterator DI = sortedDistances.begin(), - DIEnd = sortedDistances.end(); + DIEnd = sortedDistances.end(); DI != DIEnd; ++DI) { SpecifierInfoList &SpecList = DistanceMap[*DI]; Specifiers.append(SpecList.begin(), SpecList.end()); @@ -3255,8 +3439,9 @@ void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) { NestedNameSpecifier *NNS = NULL; unsigned NumSpecifiers = 0; DeclContextList NamespaceDeclChain(BuildContextChain(Ctx)); + DeclContextList FullNamespaceDeclChain(NamespaceDeclChain); - // Eliminate common elements from the two DeclContext chains + // Eliminate common elements from the two DeclContext chains. for (DeclContextList::reverse_iterator C = CurContextChain.rbegin(), CEnd = CurContextChain.rend(); C != CEnd && !NamespaceDeclChain.empty() && @@ -3264,6 +3449,21 @@ void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) { NamespaceDeclChain.pop_back(); } + // Add an explicit leading '::' specifier if needed. + if (NamespaceDecl *ND = + NamespaceDeclChain.empty() ? NULL : + dyn_cast_or_null<NamespaceDecl>(NamespaceDeclChain.back())) { + IdentifierInfo *Name = ND->getIdentifier(); + if (std::find(CurContextIdentifiers.begin(), CurContextIdentifiers.end(), + Name) != CurContextIdentifiers.end() || + std::find(CurNameSpecifierIdentifiers.begin(), + CurNameSpecifierIdentifiers.end(), + Name) != CurNameSpecifierIdentifiers.end()) { + NamespaceDeclChain = FullNamespaceDeclChain; + NNS = NestedNameSpecifier::GlobalSpecifier(Context); + } + } + // Build the NestedNameSpecifier from what is left of the NamespaceDeclChain for (DeclContextList::reverse_iterator C = NamespaceDeclChain.rbegin(), CEnd = NamespaceDeclChain.rend(); @@ -3275,6 +3475,18 @@ void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) { } } + // If the built NestedNameSpecifier would be replacing an existing + // NestedNameSpecifier, use the number of component identifiers that + // would need to be changed as the edit distance instead of the number + // of components in the built NestedNameSpecifier. + if (NNS && !CurNameSpecifierIdentifiers.empty()) { + SmallVector<const IdentifierInfo*, 4> NewNameSpecifierIdentifiers; + getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers); + NumSpecifiers = llvm::ComputeEditDistance( + llvm::ArrayRef<const IdentifierInfo*>(CurNameSpecifierIdentifiers), + llvm::ArrayRef<const IdentifierInfo*>(NewNameSpecifierIdentifiers)); + } + isSorted = false; Distances.insert(NumSpecifiers); DistanceMap[NumSpecifiers].push_back(SpecifierInfo(Ctx, NNS, NumSpecifiers)); @@ -3287,13 +3499,13 @@ static void LookupPotentialTypoResult(Sema &SemaRef, Scope *S, CXXScopeSpec *SS, DeclContext *MemberContext, bool EnteringContext, - Sema::CorrectTypoContext CTC) { + bool isObjCIvarLookup) { Res.suppressDiagnostics(); Res.clear(); Res.setLookupName(Name); if (MemberContext) { if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(MemberContext)) { - if (CTC == Sema::CTC_ObjCIvarLookup) { + if (isObjCIvarLookup) { if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable(Name)) { Res.addDecl(Ivar); Res.resolveKind(); @@ -3334,61 +3546,11 @@ static void LookupPotentialTypoResult(Sema &SemaRef, /// \brief Add keywords to the consumer as possible typo corrections. static void AddKeywordsToConsumer(Sema &SemaRef, TypoCorrectionConsumer &Consumer, - Scope *S, Sema::CorrectTypoContext CTC) { - // Add context-dependent keywords. - bool WantTypeSpecifiers = false; - bool WantExpressionKeywords = false; - bool WantCXXNamedCasts = false; - bool WantRemainingKeywords = false; - switch (CTC) { - case Sema::CTC_Unknown: - WantTypeSpecifiers = true; - WantExpressionKeywords = true; - WantCXXNamedCasts = true; - WantRemainingKeywords = true; - - if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) - if (Method->getClassInterface() && - Method->getClassInterface()->getSuperClass()) - Consumer.addKeywordResult("super"); - - break; - - case Sema::CTC_NoKeywords: - break; - - case Sema::CTC_Type: - WantTypeSpecifiers = true; - break; - - case Sema::CTC_ObjCMessageReceiver: - Consumer.addKeywordResult("super"); - // Fall through to handle message receivers like expressions. - - case Sema::CTC_Expression: - if (SemaRef.getLangOptions().CPlusPlus) - WantTypeSpecifiers = true; - WantExpressionKeywords = true; - // Fall through to get C++ named casts. - - case Sema::CTC_CXXCasts: - WantCXXNamedCasts = true; - break; - - case Sema::CTC_ObjCPropertyLookup: - // FIXME: Add "isa"? - break; - - case Sema::CTC_MemberLookup: - if (SemaRef.getLangOptions().CPlusPlus) - Consumer.addKeywordResult("template"); - break; - - case Sema::CTC_ObjCIvarLookup: - break; - } + Scope *S, CorrectionCandidateCallback &CCC) { + if (CCC.WantObjCSuper) + Consumer.addKeywordResult("super"); - if (WantTypeSpecifiers) { + if (CCC.WantTypeSpecifiers) { // Add type-specifier keywords to the set of results. const char *CTypeSpecs[] = { "char", "const", "double", "enum", "float", "int", "long", "short", @@ -3402,19 +3564,19 @@ static void AddKeywordsToConsumer(Sema &SemaRef, for (unsigned I = 0; I != NumCTypeSpecs; ++I) Consumer.addKeywordResult(CTypeSpecs[I]); - if (SemaRef.getLangOptions().C99) + if (SemaRef.getLangOpts().C99) Consumer.addKeywordResult("restrict"); - if (SemaRef.getLangOptions().Bool || SemaRef.getLangOptions().CPlusPlus) + if (SemaRef.getLangOpts().Bool || SemaRef.getLangOpts().CPlusPlus) Consumer.addKeywordResult("bool"); - else if (SemaRef.getLangOptions().C99) + else if (SemaRef.getLangOpts().C99) Consumer.addKeywordResult("_Bool"); - if (SemaRef.getLangOptions().CPlusPlus) { + if (SemaRef.getLangOpts().CPlusPlus) { Consumer.addKeywordResult("class"); Consumer.addKeywordResult("typename"); Consumer.addKeywordResult("wchar_t"); - if (SemaRef.getLangOptions().CPlusPlus0x) { + if (SemaRef.getLangOpts().CPlusPlus0x) { Consumer.addKeywordResult("char16_t"); Consumer.addKeywordResult("char32_t"); Consumer.addKeywordResult("constexpr"); @@ -3423,25 +3585,25 @@ static void AddKeywordsToConsumer(Sema &SemaRef, } } - if (SemaRef.getLangOptions().GNUMode) + if (SemaRef.getLangOpts().GNUMode) Consumer.addKeywordResult("typeof"); } - if (WantCXXNamedCasts && SemaRef.getLangOptions().CPlusPlus) { + if (CCC.WantCXXNamedCasts && SemaRef.getLangOpts().CPlusPlus) { Consumer.addKeywordResult("const_cast"); Consumer.addKeywordResult("dynamic_cast"); Consumer.addKeywordResult("reinterpret_cast"); Consumer.addKeywordResult("static_cast"); } - if (WantExpressionKeywords) { + if (CCC.WantExpressionKeywords) { Consumer.addKeywordResult("sizeof"); - if (SemaRef.getLangOptions().Bool || SemaRef.getLangOptions().CPlusPlus) { + if (SemaRef.getLangOpts().Bool || SemaRef.getLangOpts().CPlusPlus) { Consumer.addKeywordResult("false"); Consumer.addKeywordResult("true"); } - if (SemaRef.getLangOptions().CPlusPlus) { + if (SemaRef.getLangOpts().CPlusPlus) { const char *CXXExprs[] = { "delete", "new", "operator", "throw", "typeid" }; @@ -3453,14 +3615,14 @@ static void AddKeywordsToConsumer(Sema &SemaRef, cast<CXXMethodDecl>(SemaRef.CurContext)->isInstance()) Consumer.addKeywordResult("this"); - if (SemaRef.getLangOptions().CPlusPlus0x) { + if (SemaRef.getLangOpts().CPlusPlus0x) { Consumer.addKeywordResult("alignof"); Consumer.addKeywordResult("nullptr"); } } } - if (WantRemainingKeywords) { + if (CCC.WantRemainingKeywords) { if (SemaRef.getCurFunctionOrMethodDecl() || SemaRef.getCurBlock()) { // Statements. const char *CStmts[] = { @@ -3469,7 +3631,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef, for (unsigned I = 0; I != NumCStmts; ++I) Consumer.addKeywordResult(CStmts[I]); - if (SemaRef.getLangOptions().CPlusPlus) { + if (SemaRef.getLangOpts().CPlusPlus) { Consumer.addKeywordResult("catch"); Consumer.addKeywordResult("try"); } @@ -3485,7 +3647,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef, Consumer.addKeywordResult("default"); } } else { - if (SemaRef.getLangOptions().CPlusPlus) { + if (SemaRef.getLangOpts().CPlusPlus) { Consumer.addKeywordResult("namespace"); Consumer.addKeywordResult("template"); } @@ -3501,15 +3663,21 @@ static void AddKeywordsToConsumer(Sema &SemaRef, } } - if (SemaRef.getLangOptions().CPlusPlus) { + if (SemaRef.getLangOpts().CPlusPlus) { Consumer.addKeywordResult("using"); - if (SemaRef.getLangOptions().CPlusPlus0x) + if (SemaRef.getLangOpts().CPlusPlus0x) Consumer.addKeywordResult("static_assert"); } } } +static bool isCandidateViable(CorrectionCandidateCallback &CCC, + TypoCorrection &Candidate) { + Candidate.setCallbackDistance(CCC.RankCandidate(Candidate)); + return Candidate.getEditDistance(false) != TypoCorrection::InvalidDistance; +} + /// \brief Try to "correct" a typo in the source code by finding /// visible declarations whose names are similar to the name that was /// present in the source code. @@ -3524,15 +3692,16 @@ static void AddKeywordsToConsumer(Sema &SemaRef, /// \param SS the nested-name-specifier that precedes the name we're /// looking for, if present. /// +/// \param CCC A CorrectionCandidateCallback object that provides further +/// validation of typo correction candidates. It also provides flags for +/// determining the set of keywords permitted. +/// /// \param MemberContext if non-NULL, the context in which to look for /// a member access expression. /// /// \param EnteringContext whether we're entering the context described by /// the nested-name-specifier SS. /// -/// \param CTC The context in which typo correction occurs, which impacts the -/// set of keywords permitted. -/// /// \param OPT when non-NULL, the search for visible declarations will /// also walk the protocols in the qualified interfaces of \p OPT. /// @@ -3543,11 +3712,18 @@ static void AddKeywordsToConsumer(Sema &SemaRef, TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, + CorrectionCandidateCallback &CCC, DeclContext *MemberContext, bool EnteringContext, - CorrectTypoContext CTC, const ObjCObjectPointerType *OPT) { - if (Diags.hasFatalErrorOccurred() || !getLangOptions().SpellChecking) + if (Diags.hasFatalErrorOccurred() || !getLangOpts().SpellChecking) + return TypoCorrection(); + + // 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() && + isa<CXXMethodDecl>(CurContext)) return TypoCorrection(); // We only attempt to correct typos for identifiers. @@ -3565,12 +3741,18 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, if (!ActiveTemplateInstantiations.empty()) return TypoCorrection(); - NamespaceSpecifierSet Namespaces(Context, CurContext); + NamespaceSpecifierSet Namespaces(Context, CurContext, SS); TypoCorrectionConsumer Consumer(*this, Typo); + // If a callback object considers an empty typo correction candidate to be + // viable, assume it does not do any actual validation of the candidates. + TypoCorrection EmptyCorrection; + bool ValidatingCallback = !isCandidateViable(CCC, EmptyCorrection); + // Perform name lookup to find visible, similarly-named entities. bool IsUnqualifiedLookup = false; + DeclContext *QualifiedDC = MemberContext; if (MemberContext) { LookupVisibleDecls(MemberContext, LookupKind, Consumer); @@ -3582,8 +3764,8 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, LookupVisibleDecls(*I, LookupKind, Consumer); } } else if (SS && SS->isSet()) { - DeclContext *DC = computeDeclContext(*SS, EnteringContext); - if (!DC) + QualifiedDC = computeDeclContext(*SS, EnteringContext); + if (!QualifiedDC) return TypoCorrection(); // Provide a stop gap for files that are just seriously broken. Trying @@ -3593,49 +3775,65 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, return TypoCorrection(); ++TyposCorrected; - LookupVisibleDecls(DC, LookupKind, Consumer); + LookupVisibleDecls(QualifiedDC, LookupKind, Consumer); } else { IsUnqualifiedLookup = true; UnqualifiedTyposCorrectedMap::iterator Cached = UnqualifiedTyposCorrected.find(Typo); + if (Cached != UnqualifiedTyposCorrected.end()) { + // Add the cached value, unless it's a keyword or fails validation. In the + // keyword case, we'll end up adding the keyword below. + if (Cached->second) { + if (!Cached->second.isKeyword() && + isCandidateViable(CCC, Cached->second)) + Consumer.addCorrection(Cached->second); + } else { + // Only honor no-correction cache hits when a callback that will validate + // correction candidates is not being used. + if (!ValidatingCallback) + return TypoCorrection(); + } + } if (Cached == UnqualifiedTyposCorrected.end()) { // Provide a stop gap for files that are just seriously broken. Trying // to correct all typos can turn into a HUGE performance penalty, causing // some files to take minutes to get rejected by the parser. if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20) return TypoCorrection(); + } + } - // For unqualified lookup, look through all of the names that we have - // seen in this translation unit. - for (IdentifierTable::iterator I = Context.Idents.begin(), - IEnd = Context.Idents.end(); - I != IEnd; ++I) - Consumer.FoundName(I->getKey()); - - // Walk through identifiers in external identifier sources. - if (IdentifierInfoLookup *External - = Context.Idents.getExternalIdentifierLookup()) { - llvm::OwningPtr<IdentifierIterator> Iter(External->getIdentifiers()); - do { - StringRef Name = Iter->Next(); - if (Name.empty()) - break; + // Determine whether we are going to search in the various namespaces for + // corrections. + bool SearchNamespaces + = getLangOpts().CPlusPlus && + (IsUnqualifiedLookup || (QualifiedDC && QualifiedDC->isNamespace())); + + if (IsUnqualifiedLookup || SearchNamespaces) { + // 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()); - Consumer.FoundName(Name); - } while (true); - } - } else { - // Use the cached value, unless it's a keyword. In the keyword case, we'll - // end up adding the keyword below. - if (!Cached->second) - return TypoCorrection(); + // 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()); + do { + StringRef Name = Iter->Next(); + if (Name.empty()) + break; - if (!Cached->second.isKeyword()) - Consumer.addCorrection(Cached->second); + Consumer.FoundName(Name); + } while (true); } } - AddKeywordsToConsumer(*this, Consumer, S, CTC); + AddKeywordsToConsumer(*this, Consumer, S, CCC); // If we haven't found anything, we're done. if (Consumer.empty()) { @@ -3648,7 +3846,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // Make sure that the user typed at least 3 characters for each correction // made. Otherwise, we don't even both looking at the results. - unsigned ED = Consumer.getBestEditDistance(); + unsigned ED = Consumer.getBestEditDistance(true); if (ED > 0 && Typo->getName().size() / ED < 3) { // If this was an unqualified lookup, note that no correction was found. if (IsUnqualifiedLookup) @@ -3657,8 +3855,9 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, return TypoCorrection(); } - // Build the NestedNameSpecifiers for the KnownNamespaces - if (getLangOptions().CPlusPlus) { + // Build the NestedNameSpecifiers for the KnownNamespaces, if we're going + // to search those namespaces. + if (SearchNamespaces) { // Load any externally-known namespaces. if (ExternalSource && !LoadedExternalKnownNamespaces) { SmallVector<NamespaceDecl *, 4> ExternalKnownNamespaces; @@ -3675,8 +3874,9 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, Namespaces.AddNamespace(KNI->first); } - // Weed out any names that could not be found by name lookup. - llvm::SmallPtrSet<IdentifierInfo*, 16> QualifiedResults; + // Weed out any names that could not be found by name lookup or, if a + // CorrectionCandidateCallback object was provided, failed validation. + llvm::SmallVector<TypoCorrection, 16> QualifiedResults; LookupResult TmpRes(*this, TypoName, LookupKind); TmpRes.suppressDiagnostics(); while (!Consumer.empty()) { @@ -3685,22 +3885,27 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, for (TypoCorrectionConsumer::result_iterator I = DI->second->begin(), IEnd = DI->second->end(); I != IEnd; /* Increment in loop. */) { - // If the item already has been looked up or is a keyword, keep it + // 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. if (I->second.isResolved()) { + TypoCorrectionConsumer::result_iterator Prev = I; ++I; + if (!isCandidateViable(CCC, Prev->second)) + DI->second->erase(Prev); continue; } // Perform name lookup on this name. IdentifierInfo *Name = I->second.getCorrectionAsIdentifierInfo(); LookupPotentialTypoResult(*this, TmpRes, Name, S, SS, MemberContext, - EnteringContext, CTC); + EnteringContext, CCC.IsObjCIvarLookup); switch (TmpRes.getResultKind()) { case LookupResult::NotFound: case LookupResult::NotFoundInCurrentInstantiation: case LookupResult::FoundUnresolvedValue: - QualifiedResults.insert(Name); + QualifiedResults.push_back(I->second); // We didn't find this name in our scope, or didn't like what we found; // ignore it. { @@ -3716,32 +3921,40 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, return TypoCorrection(); 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) I->second.addCorrectionDecl(*TRD); ++I; + if (!isCandidateViable(CCC, Prev->second)) + DI->second->erase(Prev); break; } - case LookupResult::Found: + case LookupResult::Found: { + TypoCorrectionConsumer::result_iterator Prev = I; I->second.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>()); ++I; + if (!isCandidateViable(CCC, Prev->second)) + DI->second->erase(Prev); break; } + + } } if (DI->second->empty()) Consumer.erase(DI); - else if (!getLangOptions().CPlusPlus || QualifiedResults.empty() || !ED) + else if (!getLangOpts().CPlusPlus || QualifiedResults.empty() || !ED) // If there are results in the closest possible bucket, stop break; // Only perform the qualified lookups for C++ - if (getLangOptions().CPlusPlus) { + if (SearchNamespaces) { TmpRes.suppressDiagnostics(); - for (llvm::SmallPtrSet<IdentifierInfo*, + for (llvm::SmallVector<TypoCorrection, 16>::iterator QRI = QualifiedResults.begin(), QRIEnd = QualifiedResults.end(); QRI != QRIEnd; ++QRI) { @@ -3749,30 +3962,35 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, NIEnd = Namespaces.end(); NI != NIEnd; ++NI) { DeclContext *Ctx = NI->DeclCtx; - unsigned QualifiedED = ED + NI->EditDistance; - // Stop searching once the namespaces are too far away to create + // FIXME: Stop searching once the namespaces are too far away to create // acceptable corrections for this identifier (since the namespaces - // are sorted in ascending order by edit distance) - if (QualifiedED > Consumer.getMaxEditDistance()) break; + // are sorted in ascending order by edit distance). TmpRes.clear(); - TmpRes.setLookupName(*QRI); + 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: - Consumer.addName((*QRI)->getName(), TmpRes.getAsSingle<NamedDecl>(), - QualifiedED, NI->NameSpecifier); + case LookupResult::Found: { + TypoCorrection TC(*QRI); + TC.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>()); + TC.setCorrectionSpecifier(NI->NameSpecifier); + TC.setQualifierDistance(NI->EditDistance); + Consumer.addCorrection(TC); break; + } case LookupResult::FoundOverloaded: { - TypoCorrection corr(&Context.Idents.get((*QRI)->getName()), NULL, - NI->NameSpecifier, QualifiedED); + TypoCorrection TC(*QRI); + TC.setCorrectionSpecifier(NI->NameSpecifier); + TC.setQualifierDistance(NI->EditDistance); for (LookupResult::iterator TRD = TmpRes.begin(), TRDEnd = TmpRes.end(); TRD != TRDEnd; ++TRD) - corr.addCorrectionDecl(*TRD); - Consumer.addCorrection(corr); + TC.addCorrectionDecl(*TRD); + Consumer.addCorrection(TC); break; } case LookupResult::NotFound: @@ -3792,32 +4010,18 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, if (Consumer.empty()) return TypoCorrection(); TypoResultsMap &BestResults = *Consumer.begin()->second; - ED = Consumer.begin()->first; + ED = TypoCorrection::NormalizeEditDistance(Consumer.begin()->first); if (ED > 0 && Typo->getName().size() / ED < 3) { - // If this was an unqualified lookup, note that no correction was found. - if (IsUnqualifiedLookup) + // If this was an unqualified lookup and we believe the callback + // object wouldn't have filtered out possible corrections, note + // that no correction was found. + if (IsUnqualifiedLookup && !ValidatingCallback) (void)UnqualifiedTyposCorrected[Typo]; return TypoCorrection(); } - // If we have multiple possible corrections, eliminate the ones where we - // added namespace qualifiers to try to resolve the ambiguity (and to favor - // corrections without additional namespace qualifiers) - if (getLangOptions().CPlusPlus && BestResults.size() > 1) { - TypoCorrectionConsumer::distance_iterator DI = Consumer.begin(); - for (TypoCorrectionConsumer::result_iterator I = DI->second->begin(), - IEnd = DI->second->end(); - I != IEnd; /* Increment in loop. */) { - if (I->second.getCorrectionSpecifier() != NULL) { - TypoCorrectionConsumer::result_iterator Cur = I; - ++I; - DI->second->erase(Cur); - } else ++I; - } - } - // If only a single name remains, return that result. if (BestResults.size() == 1) { const llvm::StringMapEntry<TypoCorrection> &Correction = *(BestResults.begin()); @@ -3833,7 +4037,12 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, return Result; } - else if (BestResults.size() > 1 && CTC == CTC_ObjCMessageReceiver + 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"].isKeyword()) { // Prefer 'super' when we're completing in a message-receiver // context. @@ -3849,7 +4058,9 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, return BestResults["super"]; } - if (IsUnqualifiedLookup) + // 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 TypoCorrection(); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp index 751f553..5ece8f1 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp @@ -17,7 +17,9 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ASTMutationListener.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallString.h" using namespace clang; @@ -99,6 +101,7 @@ static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) { } Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, + SourceLocation LParenLoc, FieldDeclarator &FD, ObjCDeclSpec &ODS, Selector GetterSel, @@ -109,9 +112,9 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, unsigned Attributes = ODS.getPropertyAttributes(); TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S); QualType T = TSI->getType(); - if ((getLangOptions().getGC() != LangOptions::NonGC && + if ((getLangOpts().getGC() != LangOptions::NonGC && T.isObjCGCWeak()) || - (getLangOptions().ObjCAutoRefCount && + (getLangOpts().ObjCAutoRefCount && T.getObjCLifetime() == Qualifiers::OCL_Weak)) Attributes |= ObjCDeclSpec::DQ_PR_weak; @@ -133,43 +136,80 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) if (CDecl->IsClassExtension()) { - Decl *Res = HandlePropertyInClassExtension(S, AtLoc, + Decl *Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc, FD, GetterSel, SetterSel, isAssign, isReadWrite, Attributes, + ODS.getPropertyAttributes(), isOverridingProperty, TSI, MethodImplKind); if (Res) { CheckObjCPropertyAttributes(Res, AtLoc, Attributes); - if (getLangOptions().ObjCAutoRefCount) + if (getLangOpts().ObjCAutoRefCount) checkARCPropertyDecl(*this, cast<ObjCPropertyDecl>(Res)); } return Res; } - ObjCPropertyDecl *Res = CreatePropertyDecl(S, ClassDecl, AtLoc, FD, + ObjCPropertyDecl *Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD, GetterSel, SetterSel, isAssign, isReadWrite, - Attributes, TSI, MethodImplKind); + Attributes, + ODS.getPropertyAttributes(), + TSI, MethodImplKind); if (lexicalDC) Res->setLexicalDeclContext(lexicalDC); // Validate the attributes on the @property. CheckObjCPropertyAttributes(Res, AtLoc, Attributes); - if (getLangOptions().ObjCAutoRefCount) + if (getLangOpts().ObjCAutoRefCount) checkARCPropertyDecl(*this, Res); return Res; } +static ObjCPropertyDecl::PropertyAttributeKind +makePropertyAttributesAsWritten(unsigned Attributes) { + unsigned attributesAsWritten = 0; + if (Attributes & ObjCDeclSpec::DQ_PR_readonly) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readonly; + if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readwrite; + if (Attributes & ObjCDeclSpec::DQ_PR_getter) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_getter; + if (Attributes & ObjCDeclSpec::DQ_PR_setter) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_setter; + if (Attributes & ObjCDeclSpec::DQ_PR_assign) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_assign; + if (Attributes & ObjCDeclSpec::DQ_PR_retain) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_retain; + if (Attributes & ObjCDeclSpec::DQ_PR_strong) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_strong; + if (Attributes & ObjCDeclSpec::DQ_PR_weak) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_weak; + if (Attributes & ObjCDeclSpec::DQ_PR_copy) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_copy; + if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_unsafe_unretained; + if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_nonatomic; + if (Attributes & ObjCDeclSpec::DQ_PR_atomic) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_atomic; + + return (ObjCPropertyDecl::PropertyAttributeKind)attributesAsWritten; +} + Decl * Sema::HandlePropertyInClassExtension(Scope *S, - SourceLocation AtLoc, FieldDeclarator &FD, + SourceLocation AtLoc, + SourceLocation LParenLoc, + FieldDeclarator &FD, Selector GetterSel, Selector SetterSel, const bool isAssign, const bool isReadWrite, const unsigned Attributes, + const unsigned AttributesAsWritten, bool *isOverridingProperty, TypeSourceInfo *T, tok::ObjCKeywordKind MethodImplKind) { @@ -198,7 +238,9 @@ Sema::HandlePropertyInClassExtension(Scope *S, // FIXME. We should really be using CreatePropertyDecl for this. ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(), - PropertyId, AtLoc, T); + PropertyId, AtLoc, LParenLoc, T); + PDecl->setPropertyAttributesAsWritten( + makePropertyAttributesAsWritten(AttributesAsWritten)); if (Attributes & ObjCDeclSpec::DQ_PR_readonly) PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) @@ -224,23 +266,40 @@ Sema::HandlePropertyInClassExtension(Scope *S, if (!PIDecl) { // No matching property found in the primary class. Just fall thru // and add property to continuation class's primary class. - ObjCPropertyDecl *PDecl = - CreatePropertyDecl(S, CCPrimary, AtLoc, + ObjCPropertyDecl *PrimaryPDecl = + CreatePropertyDecl(S, CCPrimary, AtLoc, LParenLoc, FD, GetterSel, SetterSel, isAssign, isReadWrite, - Attributes, T, MethodImplKind, DC); + Attributes,AttributesAsWritten, T, MethodImplKind, DC); // 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(PDecl, CCPrimary, /* redeclaredProperty = */ 0, + ProcessPropertyDecl(PrimaryPDecl, CCPrimary, /* redeclaredProperty = */ 0, /* lexicalDC = */ CDecl); - return PDecl; + PDecl->setGetterMethodDecl(PrimaryPDecl->getGetterMethodDecl()); + PDecl->setSetterMethodDecl(PrimaryPDecl->getSetterMethodDecl()); + if (ASTMutationListener *L = Context.getASTMutationListener()) + L->AddedObjCPropertyInClassExtension(PrimaryPDecl, /*OrigProp=*/0, CDecl); + return PrimaryPDecl; } - if (PIDecl->getType().getCanonicalType() - != PDecl->getType().getCanonicalType()) { - Diag(AtLoc, - diag::warn_type_mismatch_continuation_class) << PDecl->getType(); - Diag(PIDecl->getLocation(), diag::note_property_declare); + if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) { + bool IncompatibleObjC = false; + QualType ConvertedType; + // Relax the strict type matching for property type in continuation class. + // Allow property object type of continuation class to be different as long + // as it narrows the object type in its primary class property. Note that + // this conversion is safe only because the wider type is for a 'readonly' + // property in primary class and 'narrowed' type for a 'readwrite' property + // in continuation class. + if (!isa<ObjCObjectPointerType>(PIDecl->getType()) || + !isa<ObjCObjectPointerType>(PDecl->getType()) || + (!isObjCPointerConversion(PDecl->getType(), PIDecl->getType(), + ConvertedType, IncompatibleObjC)) + || IncompatibleObjC) { + Diag(AtLoc, + diag::err_type_mismatch_continuation_class) << PDecl->getType(); + Diag(PIDecl->getLocation(), diag::note_property_declare); + } } // The property 'PIDecl's readonly attribute will be over-ridden @@ -273,7 +332,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, ContextRAII SavedContext(*this, CCPrimary); Decl *ProtocolPtrTy = - ActOnProperty(S, AtLoc, FD, ProtocolPropertyODS, + ActOnProperty(S, AtLoc, LParenLoc, FD, ProtocolPropertyODS, PIDecl->getGetterName(), PIDecl->getSetterName(), isOverridingProperty, @@ -306,18 +365,24 @@ Sema::HandlePropertyInClassExtension(Scope *S, *isOverridingProperty = true; // Make sure setter decl is synthesized, and added to primary class's list. ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl); + PDecl->setGetterMethodDecl(PIDecl->getGetterMethodDecl()); + PDecl->setSetterMethodDecl(PIDecl->getSetterMethodDecl()); + if (ASTMutationListener *L = Context.getASTMutationListener()) + L->AddedObjCPropertyInClassExtension(PDecl, PIDecl, CDecl); return 0; } ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, ObjCContainerDecl *CDecl, SourceLocation AtLoc, + SourceLocation LParenLoc, FieldDeclarator &FD, Selector GetterSel, Selector SetterSel, const bool isAssign, const bool isReadWrite, const unsigned Attributes, + const unsigned AttributesAsWritten, TypeSourceInfo *TInfo, tok::ObjCKeywordKind MethodImplKind, DeclContext *lexicalDC){ @@ -326,7 +391,7 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, // Issue a warning if property is 'assign' as default and its object, which is // gc'able conforms to NSCopying protocol - if (getLangOptions().getGC() != LangOptions::NonGC && + if (getLangOpts().getGC() != LangOptions::NonGC && isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign)) if (const ObjCObjectPointerType *ObjPtrTy = T->getAs<ObjCObjectPointerType>()) { @@ -343,7 +408,7 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, DeclContext *DC = cast<DeclContext>(CDecl); ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(), - PropertyId, AtLoc, TInfo); + PropertyId, AtLoc, LParenLoc, TInfo); if (ObjCPropertyDecl *prevDecl = ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) { @@ -368,35 +433,8 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, // selector names in anticipation of declaration of setter/getter methods. PDecl->setGetterName(GetterSel); PDecl->setSetterName(SetterSel); - - unsigned attributesAsWritten = 0; - if (Attributes & ObjCDeclSpec::DQ_PR_readonly) - attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readonly; - if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) - attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readwrite; - if (Attributes & ObjCDeclSpec::DQ_PR_getter) - attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_getter; - if (Attributes & ObjCDeclSpec::DQ_PR_setter) - attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_setter; - if (Attributes & ObjCDeclSpec::DQ_PR_assign) - attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_assign; - if (Attributes & ObjCDeclSpec::DQ_PR_retain) - attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_retain; - if (Attributes & ObjCDeclSpec::DQ_PR_strong) - attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_strong; - if (Attributes & ObjCDeclSpec::DQ_PR_weak) - attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_weak; - if (Attributes & ObjCDeclSpec::DQ_PR_copy) - attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_copy; - if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) - attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_unsafe_unretained; - if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) - attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_nonatomic; - if (Attributes & ObjCDeclSpec::DQ_PR_atomic) - attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_atomic; - PDecl->setPropertyAttributesAsWritten( - (ObjCPropertyDecl::PropertyAttributeKind)attributesAsWritten); + makePropertyAttributesAsWritten(AttributesAsWritten)); if (Attributes & ObjCDeclSpec::DQ_PR_readonly) PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); @@ -502,6 +540,33 @@ static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc, S.Diag(property->getLocation(), diag::note_property_declare); } +/// setImpliedPropertyAttributeForReadOnlyProperty - +/// This routine evaludates life-time attributes for a 'readonly' +/// property with no known lifetime of its own, using backing +/// 'ivar's attribute, if any. If no backing 'ivar', property's +/// life-time is assumed 'strong'. +static void setImpliedPropertyAttributeForReadOnlyProperty( + ObjCPropertyDecl *property, ObjCIvarDecl *ivar) { + Qualifiers::ObjCLifetime propertyLifetime = + getImpliedARCOwnership(property->getPropertyAttributes(), + property->getType()); + if (propertyLifetime != Qualifiers::OCL_None) + return; + + if (!ivar) { + // if no backing ivar, make property 'strong'. + property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); + return; + } + // property assumes owenership of backing ivar. + QualType ivarType = ivar->getType(); + Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime(); + if (ivarLifetime == Qualifiers::OCL_Strong) + property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); + else if (ivarLifetime == Qualifiers::OCL_Weak) + property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak); + return; +} /// ActOnPropertyImplDecl - This routine performs semantic checks and /// builds the AST node for a property implementation declaration; declared @@ -521,6 +586,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, Diag(AtLoc, diag::error_missing_property_context); return 0; } + if (PropertyIvarLoc.isInvalid()) + PropertyIvarLoc = PropertyLoc; ObjCPropertyDecl *property = 0; ObjCInterfaceDecl* IDecl = 0; // Find the class or category class where this property must have @@ -592,16 +659,26 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, // @synthesize if (!PropertyIvar) PropertyIvar = PropertyId; - ObjCPropertyDecl::PropertyAttributeKind kind - = property->getPropertyAttributes(); + // Check that this is a previously declared 'ivar' in 'IDecl' interface + ObjCInterfaceDecl *ClassDeclared; + Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); QualType PropType = property->getType(); - QualType PropertyIvarType = PropType.getNonReferenceType(); + + if (getLangOpts().ObjCAutoRefCount && + (property->getPropertyAttributesAsWritten() & + ObjCPropertyDecl::OBJC_PR_readonly) && + PropertyIvarType->isObjCRetainableType()) { + setImpliedPropertyAttributeForReadOnlyProperty(property, Ivar); + } + + ObjCPropertyDecl::PropertyAttributeKind kind + = property->getPropertyAttributes(); // Add GC __weak to the ivar type if the property is weak. if ((kind & ObjCPropertyDecl::OBJC_PR_weak) && - getLangOptions().getGC() != LangOptions::NonGC) { - assert(!getLangOptions().ObjCAutoRefCount); + getLangOpts().getGC() != LangOptions::NonGC) { + assert(!getLangOpts().ObjCAutoRefCount); if (PropertyIvarType.isObjCGCStrong()) { Diag(PropertyLoc, diag::err_gc_weak_property_strong_type); Diag(property->getLocation(), diag::note_property_declare); @@ -611,13 +688,10 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, } } - // Check that this is a previously declared 'ivar' in 'IDecl' interface - ObjCInterfaceDecl *ClassDeclared; - Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); if (!Ivar) { // In ARC, give the ivar a lifetime qualifier based on the // property attributes. - if (getLangOptions().ObjCAutoRefCount && + if (getLangOpts().ObjCAutoRefCount && !PropertyIvarType.getObjCLifetime() && PropertyIvarType->isObjCRetainableType()) { @@ -632,13 +706,21 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, Qualifiers::ObjCLifetime lifetime = getImpliedARCOwnership(kind, PropertyIvarType); assert(lifetime && "no lifetime for property?"); - - if (lifetime == Qualifiers::OCL_Weak && - !getLangOptions().ObjCRuntimeHasWeak) { - Diag(PropertyLoc, diag::err_arc_weak_no_runtime); - Diag(property->getLocation(), diag::note_property_declare); + if (lifetime == Qualifiers::OCL_Weak) { + bool err = false; + if (const ObjCObjectPointerType *ObjT = + PropertyIvarType->getAs<ObjCObjectPointerType>()) + if (ObjT->getInterfaceDecl()->isArcWeakrefUnavailable()) { + Diag(PropertyLoc, diag::err_arc_weak_unavailable_property); + Diag(property->getLocation(), diag::note_property_declare); + err = true; + } + if (!err && !getLangOpts().ObjCRuntimeHasWeak) { + Diag(PropertyLoc, diag::err_arc_weak_no_runtime); + Diag(property->getLocation(), diag::note_property_declare); + } } - + Qualifiers qs; qs.addObjCLifetime(lifetime); PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs); @@ -646,27 +728,27 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, } if (kind & ObjCPropertyDecl::OBJC_PR_weak && - !getLangOptions().ObjCAutoRefCount && - getLangOptions().getGC() == LangOptions::NonGC) { + !getLangOpts().ObjCAutoRefCount && + getLangOpts().getGC() == LangOptions::NonGC) { Diag(PropertyLoc, diag::error_synthesize_weak_non_arc_or_gc); Diag(property->getLocation(), diag::note_property_declare); } Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, - PropertyLoc, PropertyLoc, PropertyIvar, + PropertyIvarLoc,PropertyIvarLoc, PropertyIvar, PropertyIvarType, /*Dinfo=*/0, ObjCIvarDecl::Private, (Expr *)0, true); ClassImpDecl->addDecl(Ivar); - IDecl->makeDeclVisibleInContext(Ivar, false); + IDecl->makeDeclVisibleInContext(Ivar); property->setPropertyIvarDecl(Ivar); - if (!getLangOptions().ObjCNonFragileABI) + if (!getLangOpts().ObjCNonFragileABI) Diag(PropertyLoc, diag::error_missing_property_ivar_decl) << PropertyId; // Note! I deliberately want it to fall thru so, we have a // a property implementation and to avoid future warnings. - } else if (getLangOptions().ObjCNonFragileABI && - ClassDeclared != IDecl) { + } else if (getLangOpts().ObjCNonFragileABI && + !declaresSameEntity(ClassDeclared, IDecl)) { Diag(PropertyLoc, diag::error_ivar_in_superclass_use) << property->getDeclName() << Ivar->getDeclName() << ClassDeclared->getDeclName(); @@ -686,10 +768,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, PropertyIvarType->getAs<ObjCObjectPointerType>(), IvarType->getAs<ObjCObjectPointerType>()); else { - SourceLocation Loc = PropertyIvarLoc; - if (Loc.isInvalid()) - Loc = PropertyLoc; - compat = (CheckAssignmentConstraints(Loc, PropertyIvarType, IvarType) + compat = (CheckAssignmentConstraints(PropertyIvarLoc, PropertyIvarType, + IvarType) == Compatible); } if (!compat) { @@ -716,7 +796,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, } // __weak is explicit. So it works on Canonical type. if ((PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() && - getLangOptions().getGC() != LangOptions::NonGC)) { + getLangOpts().getGC() != LangOptions::NonGC)) { Diag(PropertyLoc, diag::error_weak_property) << property->getDeclName() << Ivar->getDeclName(); Diag(Ivar->getLocation(), diag::note_ivar_decl); @@ -725,13 +805,13 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, // Fall thru - see previous comment if ((property->getType()->isObjCObjectPointerType() || PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() && - getLangOptions().getGC() != LangOptions::NonGC) { + getLangOpts().getGC() != LangOptions::NonGC) { Diag(PropertyLoc, diag::error_strong_property) << property->getDeclName() << Ivar->getDeclName(); // Fall thru - see previous comment } } - if (getLangOptions().ObjCAutoRefCount) + if (getLangOpts().ObjCAutoRefCount) checkARCPropertyImpl(*this, PropertyLoc, property, Ivar); } else if (PropertyIvar) // @dynamic @@ -747,14 +827,14 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, Ivar, PropertyIvarLoc); if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) { getterMethod->createImplicitParams(Context, IDecl); - if (getLangOptions().CPlusPlus && Synthesize && + if (getLangOpts().CPlusPlus && Synthesize && Ivar->getType()->isRecordType()) { // For Objective-C++, need to synthesize the AST for the IVAR object to be // returned by the getter as it must conform to C++'s copy-return rules. // FIXME. Eventually we want to do this for Objective-C as well. ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl(); DeclRefExpr *SelfExpr = - new (Context) DeclRefExpr(SelfDecl, SelfDecl->getType(), + new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(), VK_RValue, SourceLocation()); Expr *IvarRefExpr = new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, @@ -782,22 +862,20 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, } if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) { setterMethod->createImplicitParams(Context, IDecl); - if (getLangOptions().CPlusPlus && Synthesize + if (getLangOpts().CPlusPlus && Synthesize && Ivar->getType()->isRecordType()) { // FIXME. Eventually we want to do this for Objective-C as well. ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl(); DeclRefExpr *SelfExpr = - new (Context) DeclRefExpr(SelfDecl, SelfDecl->getType(), + new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(), VK_RValue, SourceLocation()); Expr *lhs = new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, SelfExpr, true, true); ObjCMethodDecl::param_iterator P = setterMethod->param_begin(); ParmVarDecl *Param = (*P); - QualType T = Param->getType(); - if (T->isReferenceType()) - T = T->getAs<ReferenceType>()->getPointeeType(); - Expr *rhs = new (Context) DeclRefExpr(Param, T, + QualType T = Param->getType().getNonReferenceType(); + Expr *rhs = new (Context) DeclRefExpr(Param, false, T, VK_LValue, SourceLocation()); ExprResult Res = BuildBinOp(S, lhs->getLocEnd(), BO_Assign, lhs, rhs); @@ -808,9 +886,13 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, dyn_cast_or_null<CXXOperatorCallExpr>(callExpr)) if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee()) if (!FuncDecl->isTrivial()) - Diag(PropertyLoc, - diag::warn_atomic_property_nontrivial_assign_op) + if (property->getType()->isReferenceType()) { + Diag(PropertyLoc, + diag::err_atomic_property_nontrivial_assign_op) << property->getType(); + Diag(FuncDecl->getLocStart(), + diag::note_callee_decl) << FuncDecl; + } } PIDecl->setSetterCXXAssignment(Res.takeAs<Expr>()); } @@ -833,8 +915,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, return 0; } IC->addPropertyImplementation(PIDecl); - if (getLangOptions().ObjCDefaultSynthProperties && - getLangOptions().ObjCNonFragileABI2) { + if (getLangOpts().ObjCDefaultSynthProperties && + getLangOpts().ObjCNonFragileABI2 && + !IDecl->isObjCRequiresPropertyDefs()) { // 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. @@ -848,7 +931,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, } // Issue diagnostics only if Ivar belongs to current class. if (Ivar && Ivar->getSynthesize() && - IC->getClassInterface() == ClassDeclared) { + declaresSameEntity(IC->getClassInterface(), ClassDeclared)) { Diag(Ivar->getLocation(), diag::err_undeclared_var_use) << PropertyId; Ivar->setInvalidDecl(); @@ -948,7 +1031,8 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, ObjCMethodDecl *GetterMethod, SourceLocation Loc) { if (GetterMethod && - GetterMethod->getResultType() != property->getType()) { + !Context.hasSameType(GetterMethod->getResultType().getNonReferenceType(), + property->getType().getNonReferenceType())) { AssignConvertType result = Incompatible; if (property->getType()->isObjCObjectPointerType()) result = CheckAssignmentConstraints(Loc, GetterMethod->getResultType(), @@ -1201,7 +1285,8 @@ static void CollectClassPropertyImplementations(ObjCContainerDecl *CDecl, for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), E = PDecl->prop_end(); P != E; ++P) { ObjCPropertyDecl *Prop = (*P); - PropMap[Prop->getIdentifier()] = Prop; + if (!PropMap.count(Prop->getIdentifier())) + PropMap[Prop->getIdentifier()] = Prop; } // scan through protocol's protocols. for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), @@ -1265,7 +1350,7 @@ ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, static IdentifierInfo * getDefaultSynthIvarName(ObjCPropertyDecl *Prop, ASTContext &Ctx) { - llvm::SmallString<128> ivarName; + SmallString<128> ivarName; { llvm::raw_svector_ostream os(ivarName); os << '_' << Prop->getIdentifier()->getName(); @@ -1305,7 +1390,13 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, if (IMPDecl->getInstanceMethod(Prop->getSetterName())) continue; } - + if (isa<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); + continue; + } // We use invalid SourceLocations for the synthesized ivars since they // aren't really synthesized at a particular location; they just exist. @@ -1326,7 +1417,8 @@ void Sema::DefaultSynthesizeProperties(Scope *S, Decl *D) { if (!IC) return; if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) - DefaultSynthesizeProperties(S, IC, IDecl); + if (!IDecl->isObjCRequiresPropertyDefs()) + DefaultSynthesizeProperties(S, IC, IDecl); } void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, @@ -1363,6 +1455,11 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, << Prop->getDeclName() << Prop->getGetterName(); Diag(Prop->getLocation(), diag::note_property_declare); + if (LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCNonFragileABI2) + if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl)) + if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs()) + Diag(RID->getLocation(), diag::note_suppressed_class_declare); + } if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) { @@ -1373,6 +1470,10 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, << Prop->getDeclName() << Prop->getSetterName(); Diag(Prop->getLocation(), diag::note_property_declare); + if (LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCNonFragileABI2) + if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl)) + if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs()) + Diag(RID->getLocation(), diag::note_suppressed_class_declare); } } } @@ -1381,7 +1482,7 @@ void Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, ObjCContainerDecl* IDecl) { // Rules apply in non-GC mode only - if (getLangOptions().getGC() != LangOptions::NonGC) + if (getLangOpts().getGC() != LangOptions::NonGC) return; for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(), E = IDecl->prop_end(); @@ -1433,7 +1534,34 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, Diag(MethodLoc, diag::warn_atomic_property_rule) << Property->getIdentifier() << (GetterMethod != 0) << (SetterMethod != 0); - Diag(MethodLoc, diag::note_atomic_property_fixup_suggest); + // fixit stuff. + if (!AttributesAsWritten) { + if (Property->getLParenLoc().isValid()) { + // @property () ... case. + SourceRange PropSourceRange(Property->getAtLoc(), + Property->getLParenLoc()); + Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) << + FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic"); + } + else { + //@property id etc. + SourceLocation endLoc = + Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); + endLoc = endLoc.getLocWithOffset(-1); + SourceRange PropSourceRange(Property->getAtLoc(), endLoc); + Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) << + FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic) "); + } + } + else if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) { + // @property () ... case. + SourceLocation endLoc = Property->getLParenLoc(); + SourceRange PropSourceRange(Property->getAtLoc(), endLoc); + Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) << + FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic, "); + } + else + Diag(MethodLoc, diag::note_atomic_property_fixup_suggest); Diag(Property->getLocation(), diag::note_property_declare); } } @@ -1441,7 +1569,7 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, } void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D) { - if (getLangOptions().getGC() == LangOptions::GCOnly) + if (getLangOpts().getGC() == LangOptions::GCOnly) return; for (ObjCImplementationDecl::propimpl_iterator @@ -1459,7 +1587,7 @@ void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D ObjCMethodFamily family = method->getMethodFamily(); if (family == OMF_alloc || family == OMF_copy || family == OMF_mutableCopy || family == OMF_new) { - if (getLangOptions().ObjCAutoRefCount) + if (getLangOpts().ObjCAutoRefCount) Diag(PID->getLocation(), diag::err_ownin_getter_rule); else Diag(PID->getLocation(), diag::warn_owning_getter_rule); @@ -1510,7 +1638,8 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, Diag(SetterMethod->getLocation(), diag::err_setter_type_void); if (SetterMethod->param_size() != 1 || !Context.hasSameUnqualifiedType( - (*SetterMethod->param_begin())->getType(), property->getType())) { + (*SetterMethod->param_begin())->getType().getNonReferenceType(), + property->getType().getNonReferenceType())) { Diag(property->getLocation(), diag::warn_accessor_property_type_mismatch) << property->getDeclName() @@ -1636,6 +1765,21 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl, ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl); QualType PropertyTy = PropertyDecl->getType(); + if (getLangOpts().ObjCAutoRefCount && + (Attributes & ObjCDeclSpec::DQ_PR_readonly) && + PropertyTy->isObjCRetainableType()) { + // 'readonly' property with no obvious lifetime. + // its life time will be determined by its backing ivar. + unsigned rel = (ObjCDeclSpec::DQ_PR_unsafe_unretained | + ObjCDeclSpec::DQ_PR_copy | + ObjCDeclSpec::DQ_PR_retain | + ObjCDeclSpec::DQ_PR_strong | + ObjCDeclSpec::DQ_PR_weak | + ObjCDeclSpec::DQ_PR_assign); + if ((Attributes & rel) == 0) + return; + } + // readonly and readwrite/assign/retain/copy conflict. if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && (Attributes & (ObjCDeclSpec::DQ_PR_readwrite | @@ -1669,6 +1813,7 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl, Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain (or strong)"); Attributes &= ~(ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong); + PropertyDecl->setInvalidDecl(); } // Check for more than one of { assign, copy, retain }. @@ -1688,7 +1833,7 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl, << "assign" << "strong"; Attributes &= ~ObjCDeclSpec::DQ_PR_strong; } - if (getLangOptions().ObjCAutoRefCount && + if (getLangOpts().ObjCAutoRefCount && (Attributes & ObjCDeclSpec::DQ_PR_weak)) { Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) << "assign" << "weak"; @@ -1710,7 +1855,7 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl, << "unsafe_unretained" << "strong"; Attributes &= ~ObjCDeclSpec::DQ_PR_strong; } - if (getLangOptions().ObjCAutoRefCount && + if (getLangOpts().ObjCAutoRefCount && (Attributes & ObjCDeclSpec::DQ_PR_weak)) { Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) << "unsafe_unretained" << "weak"; @@ -1759,20 +1904,28 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl, ObjCDeclSpec::DQ_PR_unsafe_unretained | ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak)) && - !(Attributes & ObjCDeclSpec::DQ_PR_readonly) && PropertyTy->isObjCObjectPointerType()) { - if (getLangOptions().ObjCAutoRefCount) + if (getLangOpts().ObjCAutoRefCount) // With arc, @property definitions should default to (strong) when - // not specified + // not specified; including when property is 'readonly'. PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); - else { + else if (!(Attributes & ObjCDeclSpec::DQ_PR_readonly)) { + bool isAnyClassTy = + (PropertyTy->isObjCClassType() || + PropertyTy->isObjCQualifiedClassType()); + // In non-gc, non-arc mode, 'Class' is treated as a 'void *' no need to + // issue any warning. + if (isAnyClassTy && getLangOpts().getGC() == LangOptions::NonGC) + ; + else { // Skip this warning in gc-only mode. - if (getLangOptions().getGC() != LangOptions::GCOnly) + if (getLangOpts().getGC() != LangOptions::GCOnly) Diag(Loc, diag::warn_objc_property_no_assignment_attribute); // If non-gc code warn that this is likely inappropriate. - if (getLangOptions().getGC() == LangOptions::NonGC) + if (getLangOpts().getGC() == LangOptions::NonGC) Diag(Loc, diag::warn_objc_property_default_assign_on_object); + } } // FIXME: Implement warning dependent on NSCopying being @@ -1783,13 +1936,18 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl, if (!(Attributes & ObjCDeclSpec::DQ_PR_copy) &&!(Attributes & ObjCDeclSpec::DQ_PR_readonly) - && getLangOptions().getGC() == LangOptions::GCOnly + && getLangOpts().getGC() == LangOptions::GCOnly && PropertyTy->isBlockPointerType()) Diag(Loc, diag::warn_objc_property_copy_missing_on_block); - else if (getLangOptions().ObjCAutoRefCount && + else if (getLangOpts().ObjCAutoRefCount && (Attributes & ObjCDeclSpec::DQ_PR_retain) && !(Attributes & ObjCDeclSpec::DQ_PR_readonly) && !(Attributes & ObjCDeclSpec::DQ_PR_strong) && PropertyTy->isBlockPointerType()) Diag(Loc, diag::warn_objc_property_retain_of_block); + + if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && + (Attributes & ObjCDeclSpec::DQ_PR_setter)) + Diag(Loc, diag::warn_objc_readonly_property_has_setter); + } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp index b0dd5e2..284c8de 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp @@ -40,7 +40,7 @@ static ExprResult CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, bool HadMultipleCandidates, SourceLocation Loc = SourceLocation(), const DeclarationNameLoc &LocInfo = DeclarationNameLoc()){ - DeclRefExpr *DRE = new (S.Context) DeclRefExpr(Fn, Fn->getType(), + DeclRefExpr *DRE = new (S.Context) DeclRefExpr(Fn, false, Fn->getType(), VK_LValue, Loc, LocInfo); if (HadMultipleCandidates) DRE->setHadMultipleCandidates(true); @@ -258,6 +258,172 @@ isPointerConversionToVoidPointer(ASTContext& Context) const { return false; } +/// Skip any implicit casts which could be either part of a narrowing conversion +/// or after one in an implicit conversion. +static const Expr *IgnoreNarrowingConversion(const Expr *Converted) { + while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Converted)) { + switch (ICE->getCastKind()) { + case CK_NoOp: + case CK_IntegralCast: + case CK_IntegralToBoolean: + case CK_IntegralToFloating: + case CK_FloatingToIntegral: + case CK_FloatingToBoolean: + case CK_FloatingCast: + Converted = ICE->getSubExpr(); + continue; + + default: + return Converted; + } + } + + return Converted; +} + +/// Check if this standard conversion sequence represents a narrowing +/// conversion, according to C++11 [dcl.init.list]p7. +/// +/// \param Ctx The AST context. +/// \param Converted The result of applying this standard conversion sequence. +/// \param ConstantValue If this is an NK_Constant_Narrowing conversion, the +/// value of the expression prior to the narrowing conversion. +/// \param ConstantType If this is an NK_Constant_Narrowing conversion, the +/// type of the expression prior to the narrowing conversion. +NarrowingKind +StandardConversionSequence::getNarrowingKind(ASTContext &Ctx, + const Expr *Converted, + APValue &ConstantValue, + QualType &ConstantType) const { + assert(Ctx.getLangOpts().CPlusPlus && "narrowing check outside C++"); + + // C++11 [dcl.init.list]p7: + // A narrowing conversion is an implicit conversion ... + QualType FromType = getToType(0); + QualType ToType = getToType(1); + switch (Second) { + // -- from a floating-point type to an integer type, or + // + // -- from an integer type or unscoped enumeration type to a floating-point + // type, except where the source is a constant expression and the actual + // value after conversion will fit into the target type and will produce + // the original value when converted back to the original type, or + case ICK_Floating_Integral: + if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) { + return NK_Type_Narrowing; + } else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) { + llvm::APSInt IntConstantValue; + const Expr *Initializer = IgnoreNarrowingConversion(Converted); + if (Initializer && + Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) { + // Convert the integer to the floating type. + llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType)); + Result.convertFromAPInt(IntConstantValue, IntConstantValue.isSigned(), + llvm::APFloat::rmNearestTiesToEven); + // And back. + llvm::APSInt ConvertedValue = IntConstantValue; + bool ignored; + Result.convertToInteger(ConvertedValue, + llvm::APFloat::rmTowardZero, &ignored); + // If the resulting value is different, this was a narrowing conversion. + if (IntConstantValue != ConvertedValue) { + ConstantValue = APValue(IntConstantValue); + ConstantType = Initializer->getType(); + return NK_Constant_Narrowing; + } + } else { + // Variables are always narrowings. + return NK_Variable_Narrowing; + } + } + return NK_Not_Narrowing; + + // -- from long double to double or float, or from double to float, except + // where the source is a constant expression and the actual value after + // conversion is within the range of values that can be represented (even + // if it cannot be represented exactly), or + case ICK_Floating_Conversion: + if (FromType->isRealFloatingType() && ToType->isRealFloatingType() && + Ctx.getFloatingTypeOrder(FromType, ToType) == 1) { + // FromType is larger than ToType. + const Expr *Initializer = IgnoreNarrowingConversion(Converted); + if (Initializer->isCXX11ConstantExpr(Ctx, &ConstantValue)) { + // Constant! + assert(ConstantValue.isFloat()); + llvm::APFloat FloatVal = ConstantValue.getFloat(); + // Convert the source value into the target type. + bool ignored; + llvm::APFloat::opStatus ConvertStatus = FloatVal.convert( + Ctx.getFloatTypeSemantics(ToType), + llvm::APFloat::rmNearestTiesToEven, &ignored); + // If there was no overflow, the source value is within the range of + // values that can be represented. + if (ConvertStatus & llvm::APFloat::opOverflow) { + ConstantType = Initializer->getType(); + return NK_Constant_Narrowing; + } + } else { + return NK_Variable_Narrowing; + } + } + return NK_Not_Narrowing; + + // -- from an integer type or unscoped enumeration type to an integer type + // that cannot represent all the values of the original type, except where + // the source is a constant expression and the actual value after + // conversion will fit into the target type and will produce the original + // value when converted back to the original type. + case ICK_Boolean_Conversion: // Bools are integers too. + if (!FromType->isIntegralOrUnscopedEnumerationType()) { + // Boolean conversions can be from pointers and pointers to members + // [conv.bool], and those aren't considered narrowing conversions. + return NK_Not_Narrowing; + } // Otherwise, fall through to the integral case. + case ICK_Integral_Conversion: { + assert(FromType->isIntegralOrUnscopedEnumerationType()); + assert(ToType->isIntegralOrUnscopedEnumerationType()); + const bool FromSigned = FromType->isSignedIntegerOrEnumerationType(); + const unsigned FromWidth = Ctx.getIntWidth(FromType); + const bool ToSigned = ToType->isSignedIntegerOrEnumerationType(); + const unsigned ToWidth = Ctx.getIntWidth(ToType); + + if (FromWidth > ToWidth || + (FromWidth == ToWidth && FromSigned != ToSigned)) { + // Not all values of FromType can be represented in ToType. + llvm::APSInt InitializerValue; + const Expr *Initializer = IgnoreNarrowingConversion(Converted); + if (Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) { + ConstantValue = APValue(InitializerValue); + + // Add a bit to the InitializerValue so we don't have to worry about + // signed vs. unsigned comparisons. + InitializerValue = InitializerValue.extend( + InitializerValue.getBitWidth() + 1); + // Convert the initializer to and from the target width and signed-ness. + llvm::APSInt ConvertedValue = InitializerValue; + ConvertedValue = ConvertedValue.trunc(ToWidth); + ConvertedValue.setIsSigned(ToSigned); + ConvertedValue = ConvertedValue.extend(InitializerValue.getBitWidth()); + ConvertedValue.setIsSigned(InitializerValue.isSigned()); + // If the result is different, this was a narrowing conversion. + if (ConvertedValue != InitializerValue) { + ConstantType = Initializer->getType(); + return NK_Constant_Narrowing; + } + } else { + // Variables are always narrowings. + return NK_Variable_Narrowing; + } + } + return NK_Not_Narrowing; + } + + default: + // Other kinds of conversions are not narrowings. + return NK_Not_Narrowing; + } +} + /// DebugPrint - Print this standard conversion sequence to standard /// error. Useful for debugging overloading issues. void StandardConversionSequence::DebugPrint() const { @@ -305,7 +471,10 @@ void UserDefinedConversionSequence::DebugPrint() const { Before.DebugPrint(); OS << " -> "; } - OS << '\'' << *ConversionFunction << '\''; + if (ConversionFunction) + OS << '\'' << *ConversionFunction << '\''; + else + OS << "aggregate initialization"; if (After.First || After.Second || After.Third) { OS << " -> "; After.DebugPrint(); @@ -538,10 +707,85 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() { } void OverloadCandidateSet::clear() { - inherited::clear(); + for (iterator i = begin(), e = end(); i != e; ++i) + for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii) + i->Conversions[ii].~ImplicitConversionSequence(); + NumInlineSequences = 0; + Candidates.clear(); Functions.clear(); } +namespace { + class UnbridgedCastsSet { + struct Entry { + Expr **Addr; + Expr *Saved; + }; + SmallVector<Entry, 2> Entries; + + public: + void save(Sema &S, Expr *&E) { + assert(E->hasPlaceholderType(BuiltinType::ARCUnbridgedCast)); + Entry entry = { &E, E }; + Entries.push_back(entry); + E = S.stripARCUnbridgedCast(E); + } + + void restore() { + for (SmallVectorImpl<Entry>::iterator + i = Entries.begin(), e = Entries.end(); i != e; ++i) + *i->Addr = i->Saved; + } + }; +} + +/// checkPlaceholderForOverload - Do any interesting placeholder-like +/// preprocessing on the given expression. +/// +/// \param unbridgedCasts a collection to which to add unbridged casts; +/// without this, they will be immediately diagnosed as errors +/// +/// Return true on unrecoverable error. +static bool checkPlaceholderForOverload(Sema &S, Expr *&E, + UnbridgedCastsSet *unbridgedCasts = 0) { + if (const BuiltinType *placeholder = E->getType()->getAsPlaceholderType()) { + // We can't handle overloaded expressions here because overload + // resolution might reasonably tweak them. + if (placeholder->getKind() == BuiltinType::Overload) return false; + + // If the context potentially accepts unbridged ARC casts, strip + // the unbridged cast and add it to the collection for later restoration. + if (placeholder->getKind() == BuiltinType::ARCUnbridgedCast && + unbridgedCasts) { + unbridgedCasts->save(S, E); + return false; + } + + // Go ahead and check everything else. + ExprResult result = S.CheckPlaceholderExpr(E); + if (result.isInvalid()) + return true; + + E = result.take(); + return false; + } + + // Nothing to do. + return false; +} + +/// checkArgPlaceholdersForOverload - Check a set of call operands for +/// placeholders. +static bool checkArgPlaceholdersForOverload(Sema &S, Expr **args, + unsigned numArgs, + UnbridgedCastsSet &unbridged) { + for (unsigned i = 0; i != numArgs; ++i) + if (checkPlaceholderForOverload(S, args[i], &unbridged)) + return true; + + return false; +} + // IsOverload - Determine whether the given New declaration is an // overload of the declarations in Old. This routine returns false if // New and Old cannot be overloaded, e.g., if New has the same @@ -750,6 +994,86 @@ bool Sema::isFunctionConsideredUnavailable(FunctionDecl *FD) { return FD->isUnavailable() && !cast<Decl>(CurContext)->isUnavailable(); } +/// \brief Tries a user-defined conversion from From to ToType. +/// +/// Produces an implicit conversion sequence for when a standard conversion +/// is not an option. See TryImplicitConversion for more information. +static ImplicitConversionSequence +TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType, + bool SuppressUserConversions, + bool AllowExplicit, + bool InOverloadResolution, + bool CStyle, + bool AllowObjCWritebackConversion) { + ImplicitConversionSequence ICS; + + if (SuppressUserConversions) { + // We're not in the case above, so there is no conversion that + // we can perform. + ICS.setBad(BadConversionSequence::no_conversion, From, ToType); + return ICS; + } + + // Attempt user-defined conversion. + OverloadCandidateSet Conversions(From->getExprLoc()); + OverloadingResult UserDefResult + = IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions, + AllowExplicit); + + if (UserDefResult == OR_Success) { + ICS.setUserDefined(); + // 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 + // expression of class type to a base class of that type is + // given Conversion rank, in spite of the fact that a copy + // constructor (i.e., a user-defined conversion function) is + // called for those cases. + if (CXXConstructorDecl *Constructor + = dyn_cast<CXXConstructorDecl>(ICS.UserDefined.ConversionFunction)) { + QualType FromCanon + = S.Context.getCanonicalType(From->getType().getUnqualifiedType()); + QualType ToCanon + = S.Context.getCanonicalType(ToType).getUnqualifiedType(); + if (Constructor->isCopyConstructor() && + (FromCanon == ToCanon || S.IsDerivedFrom(FromCanon, ToCanon))) { + // Turn this into a "standard" conversion sequence, so that it + // gets ranked with standard conversion sequences. + ICS.setStandard(); + ICS.Standard.setAsIdentityConversion(); + ICS.Standard.setFromType(From->getType()); + ICS.Standard.setAllToTypes(ToType); + ICS.Standard.CopyConstructor = Constructor; + if (ToCanon != FromCanon) + 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()); + ICS.Ambiguous.setToType(ToType); + for (OverloadCandidateSet::iterator Cand = Conversions.begin(); + Cand != Conversions.end(); ++Cand) + if (Cand->Viable) + ICS.Ambiguous.addConversion(Cand->Function); + } else { + ICS.setBad(BadConversionSequence::no_conversion, From, ToType); + } + + return ICS; +} + /// TryImplicitConversion - Attempt to perform an implicit conversion /// from the given expression (Expr) to the given type (ToType). This /// function returns an implicit conversion sequence that can be used @@ -791,7 +1115,7 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType, return ICS; } - if (!S.getLangOptions().CPlusPlus) { + if (!S.getLangOpts().CPlusPlus) { ICS.setBad(BadConversionSequence::no_conversion, From, ToType); return ICS; } @@ -825,71 +1149,9 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType, return ICS; } - if (SuppressUserConversions) { - // We're not in the case above, so there is no conversion that - // we can perform. - ICS.setBad(BadConversionSequence::no_conversion, From, ToType); - return ICS; - } - - // Attempt user-defined conversion. - OverloadCandidateSet Conversions(From->getExprLoc()); - OverloadingResult UserDefResult - = IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions, - AllowExplicit); - - if (UserDefResult == OR_Success) { - ICS.setUserDefined(); - // 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 - // expression of class type to a base class of that type is - // given Conversion rank, in spite of the fact that a copy - // constructor (i.e., a user-defined conversion function) is - // called for those cases. - if (CXXConstructorDecl *Constructor - = dyn_cast<CXXConstructorDecl>(ICS.UserDefined.ConversionFunction)) { - QualType FromCanon - = S.Context.getCanonicalType(From->getType().getUnqualifiedType()); - QualType ToCanon - = S.Context.getCanonicalType(ToType).getUnqualifiedType(); - if (Constructor->isCopyConstructor() && - (FromCanon == ToCanon || S.IsDerivedFrom(FromCanon, ToCanon))) { - // Turn this into a "standard" conversion sequence, so that it - // gets ranked with standard conversion sequences. - ICS.setStandard(); - ICS.Standard.setAsIdentityConversion(); - ICS.Standard.setFromType(From->getType()); - ICS.Standard.setAllToTypes(ToType); - ICS.Standard.CopyConstructor = Constructor; - if (ToCanon != FromCanon) - 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()); - ICS.Ambiguous.setToType(ToType); - for (OverloadCandidateSet::iterator Cand = Conversions.begin(); - Cand != Conversions.end(); ++Cand) - if (Cand->Viable) - ICS.Ambiguous.addConversion(Cand->Function); - } else { - ICS.setBad(BadConversionSequence::no_conversion, From, ToType); - } - - return ICS; + return TryUserDefinedConversion(S, From, ToType, SuppressUserConversions, + AllowExplicit, InOverloadResolution, CStyle, + AllowObjCWritebackConversion); } ImplicitConversionSequence @@ -912,21 +1174,21 @@ Sema::TryImplicitConversion(Expr *From, QualType ToType, /// explicit user-defined conversions are permitted. ExprResult Sema::PerformImplicitConversion(Expr *From, QualType ToType, - AssignmentAction Action, bool AllowExplicit, - bool Diagnose) { + AssignmentAction Action, bool AllowExplicit) { ImplicitConversionSequence ICS; - return PerformImplicitConversion(From, ToType, Action, AllowExplicit, ICS, - Diagnose); + return PerformImplicitConversion(From, ToType, Action, AllowExplicit, ICS); } ExprResult Sema::PerformImplicitConversion(Expr *From, QualType ToType, AssignmentAction Action, bool AllowExplicit, - ImplicitConversionSequence& ICS, - bool Diagnose) { + ImplicitConversionSequence& ICS) { + if (checkPlaceholderForOverload(*this, From)) + return ExprError(); + // Objective-C ARC: Determine whether we will allow the writeback conversion. bool AllowObjCWritebackConversion - = getLangOptions().ObjCAutoRefCount && + = getLangOpts().ObjCAutoRefCount && (Action == AA_Passing || Action == AA_Sending); ICS = clang::TryImplicitConversion(*this, From, ToType, @@ -935,8 +1197,6 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, /*InOverloadResolution=*/false, /*CStyle=*/false, AllowObjCWritebackConversion); - if (!Diagnose && ICS.isFailure()) - return ExprError(); return PerformImplicitConversion(From, ToType, ICS, Action); } @@ -1024,7 +1284,7 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType, // same size if (ToType->isVectorType() && FromType->isVectorType()) { if (Context.areCompatibleVectorTypes(FromType, ToType) || - (Context.getLangOptions().LaxVectorConversions && + (Context.getLangOpts().LaxVectorConversions && (Context.getTypeSize(FromType) == Context.getTypeSize(ToType)))) { ICK = ICK_Vector_Conversion; return true; @@ -1034,6 +1294,11 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType, return false; } +static bool tryAtomicConversion(Sema &S, Expr *From, QualType ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS, + bool CStyle); + /// IsStandardConversion - Determines whether there is a standard /// conversion sequence (C++ [conv], C++ [over.ics.scs]) from the /// expression From to the type ToType. Standard conversion sequences @@ -1059,7 +1324,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // There are no standard conversions for class types in C++, so // abort early. When overloading in C, however, we do permit if (FromType->isRecordType() || ToType->isRecordType()) { - if (S.getLangOptions().CPlusPlus) + if (S.getLangOpts().CPlusPlus) return false; // When we're overloading in C, we allow, as standard conversions, @@ -1129,6 +1394,12 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, S.Context.getCanonicalType(FromType) != S.Context.OverloadTy) { SCS.First = ICK_Lvalue_To_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 = FromType->getAs<AtomicType>()) + FromType = Atomic->getValueType(); + // If T is a non-class type, the type of the rvalue is the // cv-unqualified version of T. Otherwise, the type of the rvalue // is T (C++ 4.1p1). C++ can't get here with class types; in C, we @@ -1247,7 +1518,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, } else if (IsVectorConversion(S.Context, FromType, ToType, SecondICK)) { SCS.Second = SecondICK; FromType = ToType.getUnqualifiedType(); - } else if (!S.getLangOptions().CPlusPlus && + } else if (!S.getLangOpts().CPlusPlus && S.Context.typesAreCompatible(ToType, FromType)) { // Compatible conversions (Clang extension for C function overloading) SCS.Second = ICK_Compatible_Conversion; @@ -1260,6 +1531,11 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, SCS, CStyle)) { SCS.Second = ICK_TransparentUnionConversion; FromType = ToType; + } else if (tryAtomicConversion(S, From, ToType, InOverloadResolution, SCS, + CStyle)) { + // tryAtomicConversion has updated the standard conversion sequence + // appropriately. + return true; } else { // No second conversion required. SCS.Second = ICK_Identity; @@ -1480,7 +1756,7 @@ bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) { // C99 6.3.1.5p1: // When a float is promoted to double or long double, or a // double is promoted to long double [...]. - if (!getLangOptions().CPlusPlus && + if (!getLangOpts().CPlusPlus && (FromBuiltin->getKind() == BuiltinType::Float || FromBuiltin->getKind() == BuiltinType::Double) && (ToBuiltin->getKind() == BuiltinType::LongDouble)) @@ -1646,7 +1922,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, // , including objective-c pointers. QualType ToPointeeType = ToTypePtr->getPointeeType(); if (FromType->isObjCObjectPointerType() && ToPointeeType->isVoidType() && - !getLangOptions().ObjCAutoRefCount) { + !getLangOpts().ObjCAutoRefCount) { ConvertedType = BuildSimilarlyQualifiedPointerType( FromType->getAs<ObjCObjectPointerType>(), ToPointeeType, @@ -1677,7 +1953,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, } // MSVC allows implicit function to void* type conversion. - if (getLangOptions().MicrosoftExt && FromPointeeType->isFunctionType() && + if (getLangOpts().MicrosoftExt && FromPointeeType->isFunctionType() && ToPointeeType->isVoidType()) { ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, ToPointeeType, @@ -1687,7 +1963,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, // When we're overloading in C, we allow a special kind of pointer // conversion for compatible-but-not-identical pointee types. - if (!getLangOptions().CPlusPlus && + if (!getLangOpts().CPlusPlus && Context.typesAreCompatible(FromPointeeType, ToPointeeType)) { ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, ToPointeeType, @@ -1708,7 +1984,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, // // Note that we do not check for ambiguity or inaccessibility // here. That is handled by CheckPointerConversion. - if (getLangOptions().CPlusPlus && + if (getLangOpts().CPlusPlus && FromPointeeType->isRecordType() && ToPointeeType->isRecordType() && !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType) && !RequireCompleteType(From->getLocStart(), FromPointeeType, PDiag()) && @@ -1750,7 +2026,7 @@ static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, QualType& ConvertedType, bool &IncompatibleObjC) { - if (!getLangOptions().ObjC1) + if (!getLangOpts().ObjC1) return false; // The set of qualifiers on the type we're converting from. @@ -1789,7 +2065,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, if (Context.canAssignObjCInterfaces(ToObjCPtr, FromObjCPtr)) { const ObjCInterfaceType* LHS = ToObjCPtr->getInterfaceType(); const ObjCInterfaceType* RHS = FromObjCPtr->getInterfaceType(); - if (getLangOptions().CPlusPlus && LHS && RHS && + if (getLangOpts().CPlusPlus && LHS && RHS && !ToObjCPtr->getPointeeType().isAtLeastAsQualifiedAs( FromObjCPtr->getPointeeType())) return false; @@ -1945,7 +2221,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, /// this conversion. bool Sema::isObjCWritebackConversion(QualType FromType, QualType ToType, QualType &ConvertedType) { - if (!getLangOptions().ObjCAutoRefCount || + if (!getLangOpts().ObjCAutoRefCount || Context.hasSameUnqualifiedType(FromType, ToType)) return false; @@ -1959,7 +2235,7 @@ bool Sema::isObjCWritebackConversion(QualType FromType, QualType ToType, Qualifiers ToQuals = ToPointee.getQualifiers(); if (!ToPointee->isObjCLifetimeType() || ToQuals.getObjCLifetime() != Qualifiers::OCL_Autoreleasing || - !ToQuals.withoutObjCGLifetime().empty()) + !ToQuals.withoutObjCLifetime().empty()) return false; // Argument must be a pointer to __strong to __weak. @@ -2049,7 +2325,7 @@ bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType, } else { QualType RHS = FromFunctionType->getResultType(); QualType LHS = ToFunctionType->getResultType(); - if ((!getLangOptions().CPlusPlus || !RHS->isRecordType()) && + if ((!getLangOpts().CPlusPlus || !RHS->isRecordType()) && !RHS.hasQualifiers() && LHS.hasQualifiers()) LHS = LHS.getUnqualifiedType(); @@ -2091,22 +2367,131 @@ bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType, return true; } +enum { + ft_default, + ft_different_class, + ft_parameter_arity, + ft_parameter_mismatch, + ft_return_type, + ft_qualifer_mismatch +}; + +/// HandleFunctionTypeMismatch - Gives diagnostic information for differeing +/// function types. Catches different number of parameter, mismatch in +/// parameter types, and different return types. +void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, + QualType FromType, QualType ToType) { + // If either type is not valid, include no extra info. + if (FromType.isNull() || ToType.isNull()) { + PDiag << ft_default; + return; + } + + // Get the function type from the pointers. + if (FromType->isMemberPointerType() && ToType->isMemberPointerType()) { + const MemberPointerType *FromMember = FromType->getAs<MemberPointerType>(), + *ToMember = ToType->getAs<MemberPointerType>(); + if (FromMember->getClass() != ToMember->getClass()) { + PDiag << ft_different_class << QualType(ToMember->getClass(), 0) + << QualType(FromMember->getClass(), 0); + return; + } + FromType = FromMember->getPointeeType(); + ToType = ToMember->getPointeeType(); + } + + if (FromType->isPointerType()) + FromType = FromType->getPointeeType(); + if (ToType->isPointerType()) + ToType = ToType->getPointeeType(); + + // Remove references. + FromType = FromType.getNonReferenceType(); + ToType = ToType.getNonReferenceType(); + + // Don't print extra info for non-specialized template functions. + if (FromType->isInstantiationDependentType() && + !FromType->getAs<TemplateSpecializationType>()) { + PDiag << ft_default; + return; + } + + // No extra info for same types. + if (Context.hasSameType(FromType, ToType)) { + PDiag << ft_default; + return; + } + + const FunctionProtoType *FromFunction = FromType->getAs<FunctionProtoType>(), + *ToFunction = ToType->getAs<FunctionProtoType>(); + + // Both types need to be function types. + if (!FromFunction || !ToFunction) { + PDiag << ft_default; + return; + } + + if (FromFunction->getNumArgs() != ToFunction->getNumArgs()) { + PDiag << ft_parameter_arity << ToFunction->getNumArgs() + << FromFunction->getNumArgs(); + return; + } + + // Handle different parameter types. + unsigned ArgPos; + if (!FunctionArgTypesAreEqual(FromFunction, ToFunction, &ArgPos)) { + PDiag << ft_parameter_mismatch << ArgPos + 1 + << ToFunction->getArgType(ArgPos) + << FromFunction->getArgType(ArgPos); + return; + } + + // Handle different return type. + if (!Context.hasSameType(FromFunction->getResultType(), + ToFunction->getResultType())) { + PDiag << ft_return_type << ToFunction->getResultType() + << FromFunction->getResultType(); + return; + } + + unsigned FromQuals = FromFunction->getTypeQuals(), + ToQuals = ToFunction->getTypeQuals(); + if (FromQuals != ToQuals) { + PDiag << ft_qualifer_mismatch << ToQuals << FromQuals; + return; + } + + // Unable to find a difference, so add no extra info. + PDiag << ft_default; +} + /// FunctionArgTypesAreEqual - This routine checks two function proto types -/// for equlity of their argument types. Caller has already checked that +/// for equality of their argument types. Caller has already checked that /// they have same number of arguments. This routine assumes that Objective-C /// pointer types which only differ in their protocol qualifiers are equal. +/// If the parameters are different, ArgPos will have the the parameter index +/// of the first different parameter. bool Sema::FunctionArgTypesAreEqual(const FunctionProtoType *OldType, - const FunctionProtoType *NewType) { - if (!getLangOptions().ObjC1) - return std::equal(OldType->arg_type_begin(), OldType->arg_type_end(), - NewType->arg_type_begin()); + const FunctionProtoType *NewType, + unsigned *ArgPos) { + if (!getLangOpts().ObjC1) { + 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) { + if (!Context.hasSameType(*O, *N)) { + if (ArgPos) *ArgPos = O - OldType->arg_type_begin(); + return false; + } + } + return true; + } 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) { QualType ToType = (*O); QualType FromType = (*N); - if (ToType != FromType) { + if (!Context.hasSameType(ToType, FromType)) { if (const PointerType *PTTo = ToType->getAs<PointerType>()) { if (const PointerType *PTFr = FromType->getAs<PointerType>()) if ((PTTo->getPointeeType()->isObjCQualifiedIdType() && @@ -2119,9 +2504,12 @@ bool Sema::FunctionArgTypesAreEqual(const FunctionProtoType *OldType, ToType->getAs<ObjCObjectPointerType>()) { if (const ObjCObjectPointerType *PTFr = FromType->getAs<ObjCObjectPointerType>()) - if (PTTo->getInterfaceDecl() == PTFr->getInterfaceDecl()) + if (Context.hasSameUnqualifiedType( + PTTo->getObjectType()->getBaseType(), + PTFr->getObjectType()->getBaseType())) continue; } + if (ArgPos) *ArgPos = O - OldType->arg_type_begin(); return false; } } @@ -2386,6 +2774,121 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType, return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType); } +/// \brief - Determine whether this is a conversion from a scalar type to an +/// atomic type. +/// +/// If successful, updates \c SCS's second and third steps in the conversion +/// sequence to finish the conversion. +static bool tryAtomicConversion(Sema &S, Expr *From, QualType ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS, + bool CStyle) { + const AtomicType *ToAtomic = ToType->getAs<AtomicType>(); + if (!ToAtomic) + return false; + + StandardConversionSequence InnerSCS; + if (!IsStandardConversion(S, From, ToAtomic->getValueType(), + InOverloadResolution, InnerSCS, + CStyle, /*AllowObjCWritebackConversion=*/false)) + return false; + + SCS.Second = InnerSCS.Second; + SCS.setToType(1, InnerSCS.getToType(1)); + SCS.Third = InnerSCS.Third; + SCS.QualificationIncludesObjCLifetime + = InnerSCS.QualificationIncludesObjCLifetime; + SCS.setToType(2, InnerSCS.getToType(2)); + return true; +} + +static bool isFirstArgumentCompatibleWithType(ASTContext &Context, + CXXConstructorDecl *Constructor, + QualType Type) { + const FunctionProtoType *CtorType = + Constructor->getType()->getAs<FunctionProtoType>(); + if (CtorType->getNumArgs() > 0) { + QualType FirstArg = CtorType->getArgType(0); + if (Context.hasSameUnqualifiedType(Type, FirstArg.getNonReferenceType())) + return true; + } + return false; +} + +static OverloadingResult +IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, + CXXRecordDecl *To, + UserDefinedConversionSequence &User, + OverloadCandidateSet &CandidateSet, + bool AllowExplicit) { + DeclContext::lookup_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = S.LookupConstructors(To); + Con != ConEnd; ++Con) { + NamedDecl *D = *Con; + DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); + + // Find the constructor (which may be a template). + CXXConstructorDecl *Constructor = 0; + FunctionTemplateDecl *ConstructorTmpl + = dyn_cast<FunctionTemplateDecl>(D); + if (ConstructorTmpl) + Constructor + = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl()); + else + Constructor = cast<CXXConstructorDecl>(D); + + bool Usable = !Constructor->isInvalidDecl() && + S.isInitListConstructor(Constructor) && + (AllowExplicit || !Constructor->isExplicit()); + if (Usable) { + // If the first argument is (a reference to) the target type, + // suppress conversions. + bool SuppressUserConversions = + isFirstArgumentCompatibleWithType(S.Context, Constructor, ToType); + if (ConstructorTmpl) + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + /*ExplicitArgs*/ 0, + From, CandidateSet, + SuppressUserConversions); + else + S.AddOverloadCandidate(Constructor, FoundDecl, + From, CandidateSet, + SuppressUserConversions); + } + } + + bool HadMultipleCandidates = (CandidateSet.size() > 1); + + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) { + case OR_Success: { + // Record the standard conversion we used and the conversion function. + CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function); + S.MarkFunctionReferenced(From->getLocStart(), Constructor); + + QualType ThisType = Constructor->getThisType(S.Context); + // Initializer lists don't have conversions as such. + User.Before.setAsIdentityConversion(); + User.HadMultipleCandidates = HadMultipleCandidates; + User.ConversionFunction = Constructor; + User.FoundConversionFunction = Best->FoundDecl; + User.After.setAsIdentityConversion(); + User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType()); + User.After.setAllToTypes(ToType); + return OR_Success; + } + + case OR_No_Viable_Function: + return OR_No_Viable_Function; + case OR_Deleted: + return OR_Deleted; + case OR_Ambiguous: + return OR_Ambiguous; + } + + llvm_unreachable("Invalid OverloadResult!"); +} + /// Determines whether there is a user-defined conversion sequence /// (C++ [over.ics.user]) that converts expression From to the type /// ToType. If such a conversion exists, User will contain the @@ -2398,8 +2901,8 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType, /// functions (C++0x [class.conv.fct]p2). static OverloadingResult IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, - UserDefinedConversionSequence& User, - OverloadCandidateSet& CandidateSet, + UserDefinedConversionSequence &User, + OverloadCandidateSet &CandidateSet, bool AllowExplicit) { // Whether we will only visit constructors. bool ConstructorsOnly = false; @@ -2428,6 +2931,26 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // We're not going to find any constructors. } else if (CXXRecordDecl *ToRecordDecl = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) { + + Expr **Args = &From; + unsigned NumArgs = 1; + bool ListInitializing = false; + if (InitListExpr *InitList = dyn_cast<InitListExpr>(From)) { + // But first, see if there is an init-list-contructor that will work. + OverloadingResult Result = IsInitializerListConstructorConversion( + S, From, ToType, ToRecordDecl, User, CandidateSet, AllowExplicit); + if (Result != OR_No_Viable_Function) + return Result; + // Never mind. + CandidateSet.clear(); + + // If we're list-initializing, we pass the individual elements as + // arguments, not the entire list. + Args = InitList->getInits(); + NumArgs = InitList->getNumInits(); + ListInitializing = true; + } + DeclContext::lookup_iterator Con, ConEnd; for (llvm::tie(Con, ConEnd) = S.LookupConstructors(ToRecordDecl); Con != ConEnd; ++Con) { @@ -2444,28 +2967,40 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, else Constructor = cast<CXXConstructorDecl>(D); - if (!Constructor->isInvalidDecl() && - Constructor->isConvertingConstructor(AllowExplicit)) { + bool Usable = !Constructor->isInvalidDecl(); + if (ListInitializing) + Usable = Usable && (AllowExplicit || !Constructor->isExplicit()); + else + Usable = Usable &&Constructor->isConvertingConstructor(AllowExplicit); + if (Usable) { + bool SuppressUserConversions = !ConstructorsOnly; + if (SuppressUserConversions && ListInitializing) { + SuppressUserConversions = false; + if (NumArgs == 1) { + // If the first argument is (a reference to) the target type, + // suppress conversions. + SuppressUserConversions = isFirstArgumentCompatibleWithType( + S.Context, Constructor, ToType); + } + } if (ConstructorTmpl) S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, /*ExplicitArgs*/ 0, - &From, 1, CandidateSet, - /*SuppressUserConversions=*/ - !ConstructorsOnly); + llvm::makeArrayRef(Args, NumArgs), + CandidateSet, SuppressUserConversions); else // Allow one user-defined conversion when user specifies a // From->ToType conversion via an static cast (c-style, etc). S.AddOverloadCandidate(Constructor, FoundDecl, - &From, 1, CandidateSet, - /*SuppressUserConversions=*/ - !ConstructorsOnly); + llvm::makeArrayRef(Args, NumArgs), + CandidateSet, SuppressUserConversions); } } } } // Enumerate conversion functions, if we're allowed to. - if (ConstructorsOnly) { + if (ConstructorsOnly || isa<InitListExpr>(From)) { } else if (S.RequireCompleteType(From->getLocStart(), From->getType(), S.PDiag(0) << From->getSourceRange())) { // No conversion functions from incomplete types. @@ -2512,7 +3047,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // Record the standard conversion we used and the conversion function. if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Best->Function)) { - S.MarkDeclarationReferenced(From->getLocStart(), Constructor); + S.MarkFunctionReferenced(From->getLocStart(), Constructor); // C++ [over.ics.user]p1: // If the user-defined conversion is specified by a @@ -2521,11 +3056,16 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // the argument of the constructor. // QualType ThisType = Constructor->getThisType(S.Context); - if (Best->Conversions[0].isEllipsis()) - User.EllipsisConversion = true; - else { - User.Before = Best->Conversions[0].Standard; - User.EllipsisConversion = false; + if (isa<InitListExpr>(From)) { + // Initializer lists don't have conversions as such. + User.Before.setAsIdentityConversion(); + } else { + if (Best->Conversions[0].isEllipsis()) + User.EllipsisConversion = true; + else { + User.Before = Best->Conversions[0].Standard; + User.EllipsisConversion = false; + } } User.HadMultipleCandidates = HadMultipleCandidates; User.ConversionFunction = Constructor; @@ -2534,9 +3074,10 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType()); User.After.setAllToTypes(ToType); return OR_Success; - } else if (CXXConversionDecl *Conversion + } + if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(Best->Function)) { - S.MarkDeclarationReferenced(From->getLocStart(), Conversion); + S.MarkFunctionReferenced(From->getLocStart(), Conversion); // C++ [over.ics.user]p1: // @@ -2561,10 +3102,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // 13.3.3.1). User.After = Best->FinalConversion; return OR_Success; - } else { - llvm_unreachable("Not a constructor or conversion function?"); - return OR_No_Viable_Function; } + llvm_unreachable("Not a constructor or conversion function?"); case OR_No_Viable_Function: return OR_No_Viable_Function; @@ -2576,7 +3115,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, return OR_Ambiguous; } - return OR_No_Viable_Function; + llvm_unreachable("Invalid OverloadResult!"); } bool @@ -2587,19 +3126,54 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined, CandidateSet, false); if (OvResult == OR_Ambiguous) - Diag(From->getSourceRange().getBegin(), + Diag(From->getLocStart(), diag::err_typecheck_ambiguous_condition) << From->getType() << ToType << From->getSourceRange(); else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty()) - Diag(From->getSourceRange().getBegin(), + Diag(From->getLocStart(), diag::err_typecheck_nonviable_condition) << From->getType() << ToType << From->getSourceRange(); else return false; - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &From, 1); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, From); return true; } +/// \brief Compare the user-defined conversion functions or constructors +/// of two user-defined conversion sequences to determine whether any ordering +/// is possible. +static ImplicitConversionSequence::CompareKind +compareConversionFunctions(Sema &S, + FunctionDecl *Function1, + FunctionDecl *Function2) { + if (!S.getLangOpts().ObjC1 || !S.getLangOpts().CPlusPlus0x) + 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, + // 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); + 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 ImplicitConversionSequence::Indistinguishable; +} + /// 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). @@ -2624,7 +3198,7 @@ CompareImplicitConversionSequences(Sema &S, // from any other user-defined conversion sequence. if (ICS1.getKindRank() < ICS2.getKindRank()) return ImplicitConversionSequence::Better; - else if (ICS2.getKindRank() < ICS1.getKindRank()) + if (ICS2.getKindRank() < ICS1.getKindRank()) return ImplicitConversionSequence::Worse; // The following checks require both conversion sequences to be of @@ -2632,11 +3206,15 @@ CompareImplicitConversionSequences(Sema &S, if (ICS1.getKind() != ICS2.getKind()) return ImplicitConversionSequence::Indistinguishable; + ImplicitConversionSequence::CompareKind Result = + ImplicitConversionSequence::Indistinguishable; + // Two implicit conversion sequences of the same form are // indistinguishable conversion sequences unless one of the // following rules apply: (C++ 13.3.3.2p3): if (ICS1.isStandard()) - return CompareStandardConversionSequences(S, ICS1.Standard, ICS2.Standard); + Result = CompareStandardConversionSequences(S, + ICS1.Standard, ICS2.Standard); else if (ICS1.isUserDefined()) { // User-defined conversion sequence U1 is a better conversion // sequence than another user-defined conversion sequence U2 if @@ -2646,12 +3224,31 @@ CompareImplicitConversionSequences(Sema &S, // U2 (C++ 13.3.3.2p3). if (ICS1.UserDefined.ConversionFunction == ICS2.UserDefined.ConversionFunction) - return CompareStandardConversionSequences(S, - ICS1.UserDefined.After, - ICS2.UserDefined.After); + Result = CompareStandardConversionSequences(S, + ICS1.UserDefined.After, + ICS2.UserDefined.After); + else + Result = compareConversionFunctions(S, + ICS1.UserDefined.ConversionFunction, + ICS2.UserDefined.ConversionFunction); + } + + // List-initialization sequence L1 is a better conversion sequence than + // list-initialization sequence L2 if L1 converts to std::initializer_list<X> + // for some X and L2 does not. + if (Result == ImplicitConversionSequence::Indistinguishable && + !ICS1.isBad() && + ICS1.isListInitializationSequence() && + ICS2.isListInitializationSequence()) { + if (ICS1.isStdInitializerListElement() && + !ICS2.isStdInitializerListElement()) + return ImplicitConversionSequence::Better; + if (!ICS1.isStdInitializerListElement() && + ICS2.isStdInitializerListElement()) + return ImplicitConversionSequence::Worse; } - return ImplicitConversionSequence::Indistinguishable; + return Result; } static bool hasSimilarType(ASTContext &Context, QualType T1, QualType T2) { @@ -2899,7 +3496,7 @@ CompareStandardConversionSequences(Sema &S, // } // Here, MSVC will call f(int) instead of generating a compile error // as clang will do in standard mode. - if (S.getLangOptions().MicrosoftMode && + if (S.getLangOpts().MicrosoftMode && SCS1.Second == ICK_Integral_Conversion && SCS2.Second == ICK_Floating_Integral && S.Context.getTypeSize(SCS1.getFromType()) == @@ -3395,7 +3992,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, return false; if (Best->Function) - S.MarkDeclarationReferenced(DeclLoc, Best->Function); + S.MarkFunctionReferenced(DeclLoc, Best->Function); ICS.setUserDefined(); ICS.UserDefined.Before = Best->Conversions[0].Standard; ICS.UserDefined.After = Best->FinalConversion; @@ -3423,13 +4020,13 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, return false; } - return false; + llvm_unreachable("Invalid OverloadResult!"); } /// \brief Compute an implicit conversion sequence for reference /// initialization. static ImplicitConversionSequence -TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, +TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, SourceLocation DeclLoc, bool SuppressUserConversions, bool AllowExplicit) { @@ -3566,7 +4163,7 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // allow the use of rvalue references in C++98/03 for the benefit of // standard library implementors; therefore, we need the xvalue check here. ICS.Standard.DirectBinding = - S.getLangOptions().CPlusPlus0x || + S.getLangOpts().CPlusPlus0x || (InitCategory.isPRValue() && !T2->isRecordType()); ICS.Standard.IsLvalueReference = !isRValRef; ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); @@ -3692,6 +4289,216 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, return ICS; } +static ImplicitConversionSequence +TryCopyInitialization(Sema &S, Expr *From, QualType ToType, + bool SuppressUserConversions, + bool InOverloadResolution, + bool AllowObjCWritebackConversion, + bool AllowExplicit = false); + +/// TryListConversion - Try to copy-initialize a value of type ToType from the +/// initializer list From. +static ImplicitConversionSequence +TryListConversion(Sema &S, InitListExpr *From, QualType ToType, + bool SuppressUserConversions, + bool InOverloadResolution, + bool AllowObjCWritebackConversion) { + // C++11 [over.ics.list]p1: + // When an argument is an initializer list, it is not an expression and + // special rules apply for converting it to a parameter type. + + ImplicitConversionSequence Result; + Result.setBad(BadConversionSequence::no_conversion, From, ToType); + Result.setListInitializationSequence(); + + // We need a complete type for what follows. Incomplete types can never be + // initialized from init lists. + if (S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag())) + return Result; + + // C++11 [over.ics.list]p2: + // If the parameter type is std::initializer_list<X> or "array of X" and + // all the elements can be implicitly converted to X, the implicit + // conversion sequence is the worst conversion necessary to convert an + // element of the list to X. + bool toStdInitializerList = false; + QualType X; + if (ToType->isArrayType()) + X = S.Context.getBaseElementType(ToType); + else + toStdInitializerList = S.isStdInitializerList(ToType, &X); + if (!X.isNull()) { + for (unsigned i = 0, e = From->getNumInits(); i < e; ++i) { + Expr *Init = From->getInit(i); + ImplicitConversionSequence ICS = + TryCopyInitialization(S, Init, X, SuppressUserConversions, + InOverloadResolution, + AllowObjCWritebackConversion); + // If a single element isn't convertible, fail. + if (ICS.isBad()) { + Result = ICS; + break; + } + // Otherwise, look for the worst conversion. + if (Result.isBad() || + CompareImplicitConversionSequences(S, ICS, Result) == + ImplicitConversionSequence::Worse) + Result = ICS; + } + + // For an empty list, we won't have computed any conversion sequence. + // Introduce the identity conversion sequence. + if (From->getNumInits() == 0) { + Result.setStandard(); + Result.Standard.setAsIdentityConversion(); + Result.Standard.setFromType(ToType); + Result.Standard.setAllToTypes(ToType); + } + + Result.setListInitializationSequence(); + Result.setStdInitializerListElement(toStdInitializerList); + return Result; + } + + // C++11 [over.ics.list]p3: + // Otherwise, if the parameter is a non-aggregate class X and overload + // resolution chooses a single best constructor [...] the implicit + // conversion sequence is a user-defined conversion sequence. If multiple + // constructors are viable but none is better than the others, the + // implicit conversion sequence is a user-defined conversion sequence. + if (ToType->isRecordType() && !ToType->isAggregateType()) { + // This function can deal with initializer lists. + Result = TryUserDefinedConversion(S, From, ToType, SuppressUserConversions, + /*AllowExplicit=*/false, + InOverloadResolution, /*CStyle=*/false, + AllowObjCWritebackConversion); + Result.setListInitializationSequence(); + return Result; + } + + // C++11 [over.ics.list]p4: + // Otherwise, if the parameter has an aggregate type which can be + // initialized from the initializer list [...] the implicit conversion + // sequence is a user-defined conversion sequence. + if (ToType->isAggregateType()) { + // Type is an aggregate, argument is an init list. At this point it comes + // down to checking whether the initialization works. + // FIXME: Find out whether this parameter is consumed or not. + InitializedEntity Entity = + InitializedEntity::InitializeParameter(S.Context, ToType, + /*Consumed=*/false); + if (S.CanPerformCopyInitialization(Entity, S.Owned(From))) { + Result.setUserDefined(); + Result.UserDefined.Before.setAsIdentityConversion(); + // Initializer lists don't have a type. + Result.UserDefined.Before.setFromType(QualType()); + Result.UserDefined.Before.setAllToTypes(QualType()); + + Result.UserDefined.After.setAsIdentityConversion(); + Result.UserDefined.After.setFromType(ToType); + Result.UserDefined.After.setAllToTypes(ToType); + Result.UserDefined.ConversionFunction = 0; + } + return Result; + } + + // C++11 [over.ics.list]p5: + // Otherwise, if the parameter is a reference, see 13.3.3.1.4. + if (ToType->isReferenceType()) { + // The standard is notoriously unclear here, since 13.3.3.1.4 doesn't + // mention initializer lists in any way. So we go by what list- + // initialization would do and try to extrapolate from that. + + QualType T1 = ToType->getAs<ReferenceType>()->getPointeeType(); + + // If the initializer list has a single element that is reference-related + // to the parameter type, we initialize the reference from that. + if (From->getNumInits() == 1) { + Expr *Init = From->getInit(0); + + QualType T2 = Init->getType(); + + // If the initializer is the address of an overloaded function, try + // to resolve the overloaded function. If all goes well, T2 is the + // type of the resulting function. + if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) { + DeclAccessPair Found; + if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction( + Init, ToType, false, Found)) + T2 = Fn->getType(); + } + + // Compute some basic properties of the types and the initializer. + bool dummy1 = false; + bool dummy2 = false; + bool dummy3 = false; + Sema::ReferenceCompareResult RefRelationship + = S.CompareReferenceRelationship(From->getLocStart(), T1, T2, dummy1, + dummy2, dummy3); + + if (RefRelationship >= Sema::Ref_Related) + return TryReferenceInit(S, Init, ToType, + /*FIXME:*/From->getLocStart(), + SuppressUserConversions, + /*AllowExplicit=*/false); + } + + // Otherwise, we bind the reference to a temporary created from the + // initializer list. + Result = TryListConversion(S, From, T1, SuppressUserConversions, + InOverloadResolution, + AllowObjCWritebackConversion); + if (Result.isFailure()) + return Result; + assert(!Result.isEllipsis() && + "Sub-initialization cannot result in ellipsis conversion."); + + // Can we even bind to a temporary? + if (ToType->isRValueReferenceType() || + (T1.isConstQualified() && !T1.isVolatileQualified())) { + StandardConversionSequence &SCS = Result.isStandard() ? Result.Standard : + Result.UserDefined.After; + SCS.ReferenceBinding = true; + SCS.IsLvalueReference = ToType->isLValueReferenceType(); + SCS.BindsToRvalue = true; + SCS.BindsToFunctionLvalue = false; + SCS.BindsImplicitObjectArgumentWithoutRefQualifier = false; + SCS.ObjCLifetimeConversionBinding = false; + } else + Result.setBad(BadConversionSequence::lvalue_ref_to_rvalue, + From, ToType); + return Result; + } + + // C++11 [over.ics.list]p6: + // Otherwise, if the parameter type is not a class: + if (!ToType->isRecordType()) { + // - if the initializer list has one element, the implicit conversion + // sequence is the one required to convert the element to the + // parameter type. + unsigned NumInits = From->getNumInits(); + if (NumInits == 1) + Result = TryCopyInitialization(S, From->getInit(0), ToType, + SuppressUserConversions, + InOverloadResolution, + AllowObjCWritebackConversion); + // - if the initializer list has no elements, the implicit conversion + // sequence is the identity conversion. + else if (NumInits == 0) { + Result.setStandard(); + Result.Standard.setAsIdentityConversion(); + Result.Standard.setFromType(ToType); + Result.Standard.setAllToTypes(ToType); + } + Result.setListInitializationSequence(); + return Result; + } + + // C++11 [over.ics.list]p7: + // In all cases other than those enumerated above, no conversion is possible + return Result; +} + /// TryCopyInitialization - Try to copy-initialize a value of type /// ToType from the expression From. Return the implicit conversion /// sequence required to pass this argument, which may be a bad @@ -3702,12 +4509,17 @@ static ImplicitConversionSequence TryCopyInitialization(Sema &S, Expr *From, QualType ToType, bool SuppressUserConversions, bool InOverloadResolution, - bool AllowObjCWritebackConversion) { + bool AllowObjCWritebackConversion, + bool AllowExplicit) { + if (InitListExpr *FromInitList = dyn_cast<InitListExpr>(From)) + return TryListConversion(S, FromInitList, ToType, SuppressUserConversions, + InOverloadResolution,AllowObjCWritebackConversion); + if (ToType->isReferenceType()) return TryReferenceInit(S, From, ToType, /*FIXME:*/From->getLocStart(), SuppressUserConversions, - /*AllowExplicit=*/false); + AllowExplicit); return TryImplicitConversion(S, From, ToType, SuppressUserConversions, @@ -3877,7 +4689,7 @@ Sema::PerformObjectArgumentInitialization(Expr *From, Qualifiers ToQs = DestType.getQualifiers(); unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers(); if (CVR) { - Diag(From->getSourceRange().getBegin(), + Diag(From->getLocStart(), diag::err_member_function_call_bad_cvr) << Method->getDeclName() << FromRecordType << (CVR - 1) << From->getSourceRange(); @@ -3887,7 +4699,7 @@ Sema::PerformObjectArgumentInitialization(Expr *From, } } - return Diag(From->getSourceRange().getBegin(), + return Diag(From->getLocStart(), diag::err_implicit_object_parameter_init) << ImplicitParamRecordType << FromRecordType << From->getSourceRange(); } @@ -3902,7 +4714,7 @@ Sema::PerformObjectArgumentInitialization(Expr *From, if (!Context.hasSameType(From->getType(), DestType)) From = ImpCastExprToType(From, DestType, CK_NoOp, - From->getType()->isPointerType() ? VK_RValue : VK_LValue).take(); + From->getValueKind()).take(); return Owned(From); } @@ -3923,17 +4735,190 @@ TryContextuallyConvertToBool(Sema &S, Expr *From) { /// PerformContextuallyConvertToBool - Perform a contextual conversion /// of the expression From to bool (C++0x [conv]p3). ExprResult Sema::PerformContextuallyConvertToBool(Expr *From) { + if (checkPlaceholderForOverload(*this, From)) + return ExprError(); + ImplicitConversionSequence ICS = TryContextuallyConvertToBool(*this, From); if (!ICS.isBad()) return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting); if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy)) - return Diag(From->getSourceRange().getBegin(), + return Diag(From->getLocStart(), diag::err_typecheck_bool_condition) << From->getType() << From->getSourceRange(); return ExprError(); } +/// Check that the specified conversion is permitted in a converted constant +/// expression, according to C++11 [expr.const]p3. Return true if the conversion +/// is acceptable. +static bool CheckConvertedConstantConversions(Sema &S, + StandardConversionSequence &SCS) { + // Since we know that the target type is an integral or unscoped enumeration + // type, most conversion kinds are impossible. All possible First and Third + // conversions are fine. + switch (SCS.Second) { + case ICK_Identity: + case ICK_Integral_Promotion: + case ICK_Integral_Conversion: + return true; + + case ICK_Boolean_Conversion: + // Conversion from an integral or unscoped enumeration type to bool is + // classified as ICK_Boolean_Conversion, but it's also an integral + // conversion, so it's permitted in a converted constant expression. + return SCS.getFromType()->isIntegralOrUnscopedEnumerationType() && + SCS.getToType(2)->isBooleanType(); + + case ICK_Floating_Integral: + case ICK_Complex_Real: + return false; + + case ICK_Lvalue_To_Rvalue: + case ICK_Array_To_Pointer: + case ICK_Function_To_Pointer: + case ICK_NoReturn_Adjustment: + case ICK_Qualification: + case ICK_Compatible_Conversion: + case ICK_Vector_Conversion: + case ICK_Vector_Splat: + case ICK_Derived_To_Base: + case ICK_Pointer_Conversion: + case ICK_Pointer_Member: + case ICK_Block_Pointer_Conversion: + case ICK_Writeback_Conversion: + case ICK_Floating_Promotion: + case ICK_Complex_Promotion: + case ICK_Complex_Conversion: + case ICK_Floating_Conversion: + case ICK_TransparentUnionConversion: + llvm_unreachable("unexpected second conversion kind"); + + case ICK_Num_Conversion_Kinds: + break; + } + + llvm_unreachable("unknown conversion kind"); +} + +/// CheckConvertedConstantExpression - Check that the expression From is a +/// converted constant expression of type T, perform the conversion and produce +/// the converted expression, per C++11 [expr.const]p3. +ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T, + llvm::APSInt &Value, + CCEKind CCE) { + assert(LangOpts.CPlusPlus0x && "converted constant expression outside C++11"); + assert(T->isIntegralOrEnumerationType() && "unexpected converted const type"); + + if (checkPlaceholderForOverload(*this, From)) + return ExprError(); + + // C++11 [expr.const]p3 with proposed wording fixes: + // A converted constant expression of type T is a core constant expression, + // implicitly converted to a prvalue of type T, where the converted + // expression is a literal constant expression and the implicit conversion + // sequence contains only user-defined conversions, lvalue-to-rvalue + // conversions, integral promotions, and integral conversions other than + // narrowing conversions. + ImplicitConversionSequence ICS = + TryImplicitConversion(From, T, + /*SuppressUserConversions=*/false, + /*AllowExplicit=*/false, + /*InOverloadResolution=*/false, + /*CStyle=*/false, + /*AllowObjcWritebackConversion=*/false); + StandardConversionSequence *SCS = 0; + switch (ICS.getKind()) { + case ImplicitConversionSequence::StandardConversion: + if (!CheckConvertedConstantConversions(*this, ICS.Standard)) + return Diag(From->getLocStart(), + diag::err_typecheck_converted_constant_expression_disallowed) + << From->getType() << From->getSourceRange() << T; + SCS = &ICS.Standard; + break; + case ImplicitConversionSequence::UserDefinedConversion: + // We are converting from class type to an integral or enumeration type, so + // the Before sequence must be trivial. + if (!CheckConvertedConstantConversions(*this, ICS.UserDefined.After)) + return Diag(From->getLocStart(), + diag::err_typecheck_converted_constant_expression_disallowed) + << From->getType() << From->getSourceRange() << T; + SCS = &ICS.UserDefined.After; + break; + case ImplicitConversionSequence::AmbiguousConversion: + case ImplicitConversionSequence::BadConversion: + if (!DiagnoseMultipleUserDefinedConversion(From, T)) + return Diag(From->getLocStart(), + diag::err_typecheck_converted_constant_expression) + << From->getType() << From->getSourceRange() << T; + return ExprError(); + + case ImplicitConversionSequence::EllipsisConversion: + llvm_unreachable("ellipsis conversion in converted constant expression"); + } + + ExprResult Result = PerformImplicitConversion(From, T, ICS, AA_Converting); + if (Result.isInvalid()) + return Result; + + // Check for a narrowing implicit conversion. + APValue PreNarrowingValue; + QualType PreNarrowingType; + switch (SCS->getNarrowingKind(Context, Result.get(), PreNarrowingValue, + PreNarrowingType)) { + case NK_Variable_Narrowing: + // Implicit conversion to a narrower type, and the value is not a constant + // expression. We'll diagnose this in a moment. + case NK_Not_Narrowing: + break; + + case NK_Constant_Narrowing: + Diag(From->getLocStart(), + isSFINAEContext() ? diag::err_cce_narrowing_sfinae : + diag::err_cce_narrowing) + << CCE << /*Constant*/1 + << PreNarrowingValue.getAsString(Context, PreNarrowingType) << T; + break; + + case NK_Type_Narrowing: + Diag(From->getLocStart(), + isSFINAEContext() ? diag::err_cce_narrowing_sfinae : + diag::err_cce_narrowing) + << CCE << /*Constant*/0 << From->getType() << T; + break; + } + + // Check the expression is a constant expression. + llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + Expr::EvalResult Eval; + Eval.Diag = &Notes; + + if (!Result.get()->EvaluateAsRValue(Eval, Context)) { + // The expression can't be folded, so we can't keep it at this position in + // the AST. + Result = ExprError(); + } else { + Value = Eval.Val.getInt(); + + if (Notes.empty()) { + // It's a constant expression. + return Result; + } + } + + // It's not a constant expression. Produce an appropriate diagnostic. + if (Notes.size() == 1 && + Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr) + Diag(Notes[0].first, diag::err_expr_not_cce) << CCE; + else { + Diag(From->getLocStart(), diag::err_expr_not_cce) + << CCE << From->getSourceRange(); + for (unsigned I = 0; I < Notes.size(); ++I) + Diag(Notes[I].first, Notes[I].second); + } + return Result; +} + /// dropPointerConversions - If the given standard conversion sequence /// involves any pointer conversions, remove them. This may change /// the result type of the conversion sequence. @@ -3982,6 +4967,9 @@ TryContextuallyConvertToObjCPointer(Sema &S, Expr *From) { /// PerformContextuallyConvertToObjCPointer - Perform a contextual /// conversion of the expression From to an Objective-C pointer type. ExprResult Sema::PerformContextuallyConvertToObjCPointer(Expr *From) { + if (checkPlaceholderForOverload(*this, From)) + return ExprError(); + QualType Ty = Context.getObjCIdType(); ImplicitConversionSequence ICS = TryContextuallyConvertToObjCPointer(*this, From); @@ -3990,6 +4978,13 @@ ExprResult Sema::PerformContextuallyConvertToObjCPointer(Expr *From) { return ExprError(); } +/// Determine whether the provided type is an integral type, or an enumeration +/// type of a permitted flavor. +static bool isIntegralOrEnumerationType(QualType T, bool AllowScopedEnum) { + return AllowScopedEnum ? T->isIntegralOrEnumerationType() + : T->isIntegralOrUnscopedEnumerationType(); +} + /// \brief Attempt to convert the given expression to an integral or /// enumeration type. /// @@ -4024,6 +5019,9 @@ ExprResult Sema::PerformContextuallyConvertToObjCPointer(Expr *From) { /// \param ConvDiag The diagnostic to be emitted if we are calling a conversion /// function, which may be an extension in this case. /// +/// \param AllowScopedEnumerations Specifies whether conversions to scoped +/// enumerations should be considered. +/// /// \returns The expression, converted to an integral or enumeration type if /// successful. ExprResult @@ -4034,24 +5032,32 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, const PartialDiagnostic &ExplicitConvNote, const PartialDiagnostic &AmbigDiag, const PartialDiagnostic &AmbigNote, - const PartialDiagnostic &ConvDiag) { + const PartialDiagnostic &ConvDiag, + bool AllowScopedEnumerations) { // We can't perform any more checking for type-dependent expressions. if (From->isTypeDependent()) return Owned(From); + // Process placeholders immediately. + if (From->hasPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(From); + if (result.isInvalid()) return result; + From = result.take(); + } + // If the expression already has integral or enumeration type, we're golden. QualType T = From->getType(); - if (T->isIntegralOrEnumerationType()) - return Owned(From); + if (isIntegralOrEnumerationType(T, AllowScopedEnumerations)) + return DefaultLvalueConversion(From); // FIXME: Check for missing '()' if T is a function type? // If we don't have a class type in C++, there's no way we can get an // expression of integral or enumeration type. const RecordType *RecordTy = T->getAs<RecordType>(); - if (!RecordTy || !getLangOptions().CPlusPlus) { - Diag(Loc, NotIntDiag) - << T << From->getSourceRange(); + if (!RecordTy || !getLangOpts().CPlusPlus) { + if (NotIntDiag.getDiagID()) + Diag(Loc, NotIntDiag) << T << From->getSourceRange(); return Owned(From); } @@ -4072,19 +5078,21 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, I != E; ++I) { if (CXXConversionDecl *Conversion - = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) - if (Conversion->getConversionType().getNonReferenceType() - ->isIntegralOrEnumerationType()) { + = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) { + if (isIntegralOrEnumerationType( + Conversion->getConversionType().getNonReferenceType(), + AllowScopedEnumerations)) { if (Conversion->isExplicit()) ExplicitConversions.addDecl(I.getDecl(), I.getAccess()); else ViableConversions.addDecl(I.getDecl(), I.getAccess()); } + } } switch (ViableConversions.size()) { case 0: - if (ExplicitConversions.size() == 1) { + if (ExplicitConversions.size() == 1 && ExplicitConvDiag.getDiagID()) { DeclAccessPair Found = ExplicitConversions[0]; CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Found->getUnderlyingDecl()); @@ -4115,8 +5123,11 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, HadMultipleCandidates); if (Result.isInvalid()) return ExprError(); - - From = Result.get(); + // Record usage of conversion in an implicit cast. + From = ImplicitCastExpr::Create(Context, Result.get()->getType(), + CK_UserDefinedConversion, + Result.get(), 0, + Result.get()->getValueKind()); } // We'll complain below about a non-integral condition type. @@ -4143,12 +5154,18 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, HadMultipleCandidates); if (Result.isInvalid()) return ExprError(); - - From = Result.get(); + // Record usage of conversion in an implicit cast. + From = ImplicitCastExpr::Create(Context, Result.get()->getType(), + CK_UserDefinedConversion, + Result.get(), 0, + Result.get()->getValueKind()); break; } default: + if (!AmbigDiag.getDiagID()) + return Owned(From); + Diag(Loc, AmbigDiag) << T << From->getSourceRange(); for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) { @@ -4161,11 +5178,11 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, return Owned(From); } - if (!From->getType()->isIntegralOrEnumerationType()) - Diag(Loc, NotIntDiag) - << From->getType() << From->getSourceRange(); + if (!isIntegralOrEnumerationType(From->getType(), AllowScopedEnumerations) && + NotIntDiag.getDiagID()) + Diag(Loc, NotIntDiag) << From->getType() << From->getSourceRange(); - return Owned(From); + return DefaultLvalueConversion(From); } /// AddOverloadCandidate - Adds the given function to the set of @@ -4179,10 +5196,11 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, void Sema::AddOverloadCandidate(FunctionDecl *Function, DeclAccessPair FoundDecl, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions, - bool PartialOverloading) { + bool PartialOverloading, + bool AllowExplicit) { const FunctionProtoType* Proto = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>()); assert(Proto && "Functions without a prototype cannot be overloaded"); @@ -4200,8 +5218,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // is irrelevant. AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(), Expr::Classification::makeSimpleLValue(), - Args, NumArgs, CandidateSet, - SuppressUserConversions); + Args, CandidateSet, SuppressUserConversions); return; } // We treat a constructor like a non-member function, since its object @@ -4219,7 +5236,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // A member function template is never instantiated to perform the copy // of a class object to an object of its class type. QualType ClassType = Context.getTypeDeclType(Constructor->getParent()); - if (NumArgs == 1 && + if (Args.size() == 1 && Constructor->isSpecializationCopyingObject() && (Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) || IsDerivedFrom(Args[0]->getType(), ClassType))) @@ -4227,21 +5244,20 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, } // Add this candidate - CandidateSet.push_back(OverloadCandidate()); - OverloadCandidate& Candidate = CandidateSet.back(); + OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size()); Candidate.FoundDecl = FoundDecl; Candidate.Function = Function; Candidate.Viable = true; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; - Candidate.ExplicitCallArguments = NumArgs; + Candidate.ExplicitCallArguments = Args.size(); unsigned NumArgsInProto = Proto->getNumArgs(); // (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 ((NumArgs + (PartialOverloading && NumArgs)) > NumArgsInProto && + if ((Args.size() + (PartialOverloading && Args.size())) > NumArgsInProto && !Proto->isVariadic()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_too_many_arguments; @@ -4254,7 +5270,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // parameter list is truncated on the right, so that there are // exactly m parameters. unsigned MinRequiredArgs = Function->getMinRequiredArguments(); - if (NumArgs < MinRequiredArgs && !PartialOverloading) { + if (Args.size() < MinRequiredArgs && !PartialOverloading) { // Not enough arguments. Candidate.Viable = false; Candidate.FailureKind = ovl_fail_too_few_arguments; @@ -4262,7 +5278,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, } // (CUDA B.1): Check for invalid calls between targets. - if (getLangOptions().CUDA) + if (getLangOpts().CUDA) if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext)) if (CheckCUDATarget(Caller, Function)) { Candidate.Viable = false; @@ -4272,8 +5288,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // Determine the implicit conversion sequences for each of the // arguments. - Candidate.Conversions.resize(NumArgs); - for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) { if (ArgIdx < NumArgsInProto) { // (C++ 13.3.2p3): for F to be a viable function, there shall // exist for each argument an implicit conversion sequence @@ -4285,7 +5300,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, SuppressUserConversions, /*InOverloadResolution=*/true, /*AllowObjCWritebackConversion=*/ - getLangOptions().ObjCAutoRefCount); + getLangOpts().ObjCAutoRefCount, + AllowExplicit); if (Candidate.Conversions[ArgIdx].isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; @@ -4303,9 +5319,10 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, /// \brief Add all of the function declarations in the given function set to /// the overload canddiate set. void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, - bool SuppressUserConversions) { + bool SuppressUserConversions, + TemplateArgumentListInfo *ExplicitTemplateArgs) { for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) { NamedDecl *D = F.getDecl()->getUnderlyingDecl(); if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { @@ -4313,10 +5330,10 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(), cast<CXXMethodDecl>(FD)->getParent(), Args[0]->getType(), Args[0]->Classify(Context), - Args + 1, NumArgs - 1, - CandidateSet, SuppressUserConversions); + Args.slice(1), CandidateSet, + SuppressUserConversions); else - AddOverloadCandidate(FD, F.getPair(), Args, NumArgs, CandidateSet, + AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet, SuppressUserConversions); } else { FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D); @@ -4324,17 +5341,14 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic()) AddMethodTemplateCandidate(FunTmpl, F.getPair(), cast<CXXRecordDecl>(FunTmpl->getDeclContext()), - /*FIXME: explicit args */ 0, + ExplicitTemplateArgs, Args[0]->getType(), - Args[0]->Classify(Context), - Args + 1, NumArgs - 1, - CandidateSet, - SuppressUserConversions); + Args[0]->Classify(Context), Args.slice(1), + CandidateSet, SuppressUserConversions); else AddTemplateOverloadCandidate(FunTmpl, F.getPair(), - /*FIXME: explicit args */ 0, - Args, NumArgs, CandidateSet, - SuppressUserConversions); + ExplicitTemplateArgs, Args, + CandidateSet, SuppressUserConversions); } } } @@ -4358,12 +5372,13 @@ void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, "Expected a member function template"); AddMethodTemplateCandidate(TD, FoundDecl, ActingContext, /*ExplicitArgs*/ 0, - ObjectType, ObjectClassification, Args, NumArgs, - CandidateSet, + ObjectType, ObjectClassification, + llvm::makeArrayRef(Args, NumArgs), CandidateSet, SuppressUserConversions); } else { AddMethodCandidate(cast<CXXMethodDecl>(Decl), FoundDecl, ActingContext, - ObjectType, ObjectClassification, Args, NumArgs, + ObjectType, ObjectClassification, + llvm::makeArrayRef(Args, NumArgs), CandidateSet, SuppressUserConversions); } } @@ -4379,7 +5394,7 @@ void Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, QualType ObjectType, Expr::Classification ObjectClassification, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions) { const FunctionProtoType* Proto @@ -4395,20 +5410,19 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); // Add this candidate - CandidateSet.push_back(OverloadCandidate()); - OverloadCandidate& Candidate = CandidateSet.back(); + OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size() + 1); Candidate.FoundDecl = FoundDecl; Candidate.Function = Method; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; - Candidate.ExplicitCallArguments = NumArgs; + Candidate.ExplicitCallArguments = Args.size(); unsigned NumArgsInProto = Proto->getNumArgs(); // (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 (NumArgs > NumArgsInProto && !Proto->isVariadic()) { + if (Args.size() > NumArgsInProto && !Proto->isVariadic()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_too_many_arguments; return; @@ -4420,7 +5434,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // parameter list is truncated on the right, so that there are // exactly m parameters. unsigned MinRequiredArgs = Method->getMinRequiredArguments(); - if (NumArgs < MinRequiredArgs) { + if (Args.size() < MinRequiredArgs) { // Not enough arguments. Candidate.Viable = false; Candidate.FailureKind = ovl_fail_too_few_arguments; @@ -4428,7 +5442,6 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, } Candidate.Viable = true; - Candidate.Conversions.resize(NumArgs + 1); if (Method->isStatic() || ObjectType.isNull()) // The implicit object argument is ignored. @@ -4448,7 +5461,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // Determine the implicit conversion sequences for each of the // arguments. - for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) { if (ArgIdx < NumArgsInProto) { // (C++ 13.3.2p3): for F to be a viable function, there shall // exist for each argument an implicit conversion sequence @@ -4460,7 +5473,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, SuppressUserConversions, /*InOverloadResolution=*/true, /*AllowObjCWritebackConversion=*/ - getLangOptions().ObjCAutoRefCount); + getLangOpts().ObjCAutoRefCount); if (Candidate.Conversions[ArgIdx + 1].isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; @@ -4485,7 +5498,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, Expr::Classification ObjectClassification, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions) { if (!CandidateSet.isNewCandidate(MethodTmpl)) @@ -4503,17 +5516,16 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, TemplateDeductionInfo Info(Context, CandidateSet.getLocation()); FunctionDecl *Specialization = 0; if (TemplateDeductionResult Result - = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, - Args, NumArgs, Specialization, Info)) { - CandidateSet.push_back(OverloadCandidate()); - OverloadCandidate &Candidate = CandidateSet.back(); + = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args, + Specialization, Info)) { + OverloadCandidate &Candidate = CandidateSet.addCandidate(); Candidate.FoundDecl = FoundDecl; Candidate.Function = MethodTmpl->getTemplatedDecl(); Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_deduction; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; - Candidate.ExplicitCallArguments = NumArgs; + Candidate.ExplicitCallArguments = Args.size(); Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, Info); return; @@ -4525,8 +5537,8 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, assert(isa<CXXMethodDecl>(Specialization) && "Specialization is not a member function?"); AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl, - ActingContext, ObjectType, ObjectClassification, - Args, NumArgs, CandidateSet, SuppressUserConversions); + ActingContext, ObjectType, ObjectClassification, Args, + CandidateSet, SuppressUserConversions); } /// \brief Add a C++ function template specialization as a candidate @@ -4536,7 +5548,7 @@ void Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions) { if (!CandidateSet.isNewCandidate(FunctionTemplate)) @@ -4554,17 +5566,16 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, TemplateDeductionInfo Info(Context, CandidateSet.getLocation()); FunctionDecl *Specialization = 0; if (TemplateDeductionResult Result - = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, - Args, NumArgs, Specialization, Info)) { - CandidateSet.push_back(OverloadCandidate()); - OverloadCandidate &Candidate = CandidateSet.back(); + = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args, + Specialization, Info)) { + OverloadCandidate &Candidate = CandidateSet.addCandidate(); Candidate.FoundDecl = FoundDecl; Candidate.Function = FunctionTemplate->getTemplatedDecl(); Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_deduction; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; - Candidate.ExplicitCallArguments = NumArgs; + Candidate.ExplicitCallArguments = Args.size(); Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, Info); return; @@ -4573,7 +5584,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, // Add the function template specialization produced by template argument // deduction as a candidate. assert(Specialization && "Missing function template specialization?"); - AddOverloadCandidate(Specialization, FoundDecl, Args, NumArgs, CandidateSet, + AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions); } @@ -4599,8 +5610,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); // Add this candidate - CandidateSet.push_back(OverloadCandidate()); - OverloadCandidate& Candidate = CandidateSet.back(); + OverloadCandidate &Candidate = CandidateSet.addCandidate(1); Candidate.FoundDecl = FoundDecl; Candidate.Function = Conversion; Candidate.IsSurrogate = false; @@ -4609,7 +5619,6 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, Candidate.FinalConversion.setFromType(ConvType); Candidate.FinalConversion.setAllToTypes(ToType); Candidate.Viable = true; - Candidate.Conversions.resize(1); Candidate.ExplicitCallArguments = 1; // C++ [over.match.funcs]p4: @@ -4656,7 +5665,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, // lvalues/rvalues and the type. Fortunately, we can allocate this // call on the stack and we don't need its arguments to be // well-formed. - DeclRefExpr ConversionRef(Conversion, Conversion->getType(), + DeclRefExpr ConversionRef(Conversion, false, Conversion->getType(), VK_LValue, From->getLocStart()); ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack, Context.getPointerType(Conversion->getType()), @@ -4743,8 +5752,7 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, ToType, Specialization, Info)) { - CandidateSet.push_back(OverloadCandidate()); - OverloadCandidate &Candidate = CandidateSet.back(); + OverloadCandidate &Candidate = CandidateSet.addCandidate(); Candidate.FoundDecl = FoundDecl; Candidate.Function = FunctionTemplate->getTemplatedDecl(); Candidate.Viable = false; @@ -4774,7 +5782,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, CXXRecordDecl *ActingContext, const FunctionProtoType *Proto, Expr *Object, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet) { if (!CandidateSet.isNewCandidate(Conversion)) return; @@ -4782,16 +5790,14 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, // Overload resolution is always an unevaluated context. EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); - CandidateSet.push_back(OverloadCandidate()); - OverloadCandidate& Candidate = CandidateSet.back(); + OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size() + 1); Candidate.FoundDecl = FoundDecl; Candidate.Function = 0; Candidate.Surrogate = Conversion; Candidate.Viable = true; Candidate.IsSurrogate = true; Candidate.IgnoreObjectArgument = false; - Candidate.Conversions.resize(NumArgs + 1); - Candidate.ExplicitCallArguments = NumArgs; + Candidate.ExplicitCallArguments = Args.size(); // Determine the implicit conversion sequence for the implicit // object parameter. @@ -4825,7 +5831,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, // (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 (NumArgs > NumArgsInProto && !Proto->isVariadic()) { + if (Args.size() > NumArgsInProto && !Proto->isVariadic()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_too_many_arguments; return; @@ -4833,7 +5839,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, // Function types don't have any default arguments, so just check if // we have enough arguments. - if (NumArgs < NumArgsInProto) { + if (Args.size() < NumArgsInProto) { // Not enough arguments. Candidate.Viable = false; Candidate.FailureKind = ovl_fail_too_few_arguments; @@ -4842,7 +5848,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, // Determine the implicit conversion sequences for each of the // arguments. - for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) { if (ArgIdx < NumArgsInProto) { // (C++ 13.3.2p3): for F to be a viable function, there shall // exist for each argument an implicit conversion sequence @@ -4854,7 +5860,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, /*SuppressUserConversions=*/false, /*InOverloadResolution=*/false, /*AllowObjCWritebackConversion=*/ - getLangOptions().ObjCAutoRefCount); + getLangOpts().ObjCAutoRefCount); if (Candidate.Conversions[ArgIdx + 1].isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; @@ -4935,8 +5941,7 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); // Add this candidate - CandidateSet.push_back(OverloadCandidate()); - OverloadCandidate& Candidate = CandidateSet.back(); + OverloadCandidate &Candidate = CandidateSet.addCandidate(NumArgs); Candidate.FoundDecl = DeclAccessPair::make(0, AS_none); Candidate.Function = 0; Candidate.IsSurrogate = false; @@ -4948,7 +5953,6 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, // Determine the implicit conversion sequences for each of the // arguments. Candidate.Viable = true; - Candidate.Conversions.resize(NumArgs); Candidate.ExplicitCallArguments = NumArgs; for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { // C++ [over.match.oper]p4: @@ -4974,7 +5978,7 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, ArgIdx == 0 && IsAssignmentOperator, /*InOverloadResolution=*/false, /*AllowObjCWritebackConversion=*/ - getLangOptions().ObjCAutoRefCount); + getLangOpts().ObjCAutoRefCount); } if (Candidate.Conversions[ArgIdx].isBad()) { Candidate.Viable = false; @@ -6319,7 +7323,7 @@ public: S.AddBuiltinCandidate(*MemPtr, ParamTypes, Args, 2, CandidateSet); } - if (S.getLangOptions().CPlusPlus0x) { + if (S.getLangOpts().CPlusPlus0x) { for (BuiltinCandidateTypeSet::iterator Enum = CandidateTypes[ArgIdx].enumeration_begin(), EnumEnd = CandidateTypes[ArgIdx].enumeration_end(); @@ -6536,8 +7540,8 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, /// candidate set (C++ [basic.lookup.argdep]). void Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, - bool Operator, - Expr **Args, unsigned NumArgs, + bool Operator, SourceLocation Loc, + llvm::ArrayRef<Expr *> Args, TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, bool PartialOverloading, @@ -6552,7 +7556,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, // we supposed to consider on ADL candidates, anyway? // FIXME: Pass in the explicit template arguments? - ArgumentDependentLookup(Name, Operator, Args, NumArgs, Fns, + ArgumentDependentLookup(Name, Operator, Loc, Args, Fns, StdNamespaceIsAssociated); // Erase all of the candidates we already knew about. @@ -6573,12 +7577,12 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, if (ExplicitTemplateArgs) continue; - AddOverloadCandidate(FD, FoundDecl, Args, NumArgs, CandidateSet, - false, PartialOverloading); + AddOverloadCandidate(FD, FoundDecl, Args, CandidateSet, false, + PartialOverloading); } else AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I), FoundDecl, ExplicitTemplateArgs, - Args, NumArgs, CandidateSet); + Args, CandidateSet); } } @@ -6611,8 +7615,8 @@ isBetterOverloadCandidate(Sema &S, // A viable function F1 is defined to be a better function than another // viable function F2 if for all arguments i, ICSi(F1) is not a worse // conversion sequence than ICSi(F2), and then... - unsigned NumArgs = Cand1.Conversions.size(); - assert(Cand2.Conversions.size() == NumArgs && "Overload candidate mismatch"); + unsigned NumArgs = Cand1.NumConversions; + assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch"); bool HasBetterConversion = false; for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) { switch (CompareImplicitConversionSequences(S, @@ -6669,6 +7673,15 @@ isBetterOverloadCandidate(Sema &S, 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)) { @@ -6794,9 +7807,11 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S, if (Meth->isMoveAssignmentOperator()) return oc_implicit_move_assignment; - assert(Meth->isCopyAssignmentOperator() - && "implicit method is not copy assignment operator?"); - return oc_implicit_copy_assignment; + if (Meth->isCopyAssignmentOperator()) + return oc_implicit_copy_assignment; + + assert(isa<CXXConversionDecl>(Meth) && "expected conversion"); + return oc_method; } return isTemplate ? oc_function_template : oc_function; @@ -6815,17 +7830,19 @@ void MaybeEmitInheritedConstructorNote(Sema &S, FunctionDecl *Fn) { } // end anonymous namespace // Notes the location of an overload candidate. -void Sema::NoteOverloadCandidate(FunctionDecl *Fn) { +void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType) { std::string FnDesc; OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Fn, FnDesc); - Diag(Fn->getLocation(), diag::note_ovl_candidate) - << (unsigned) K << FnDesc; + PartialDiagnostic PD = PDiag(diag::note_ovl_candidate) + << (unsigned) K << FnDesc; + HandleFunctionTypeMismatch(PD, Fn->getType(), DestType); + Diag(Fn->getLocation(), PD); MaybeEmitInheritedConstructorNote(*this, Fn); } //Notes the location of all overload candidates designated through // OverloadedExpr -void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr) { +void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr, QualType DestType) { assert(OverloadedExpr->getType() == Context.OverloadTy); OverloadExpr::FindResult Ovl = OverloadExpr::find(OverloadedExpr); @@ -6836,10 +7853,10 @@ void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr) { I != IEnd; ++I) { if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()) ) { - NoteOverloadCandidate(FunTmpl->getTemplatedDecl()); + NoteOverloadCandidate(FunTmpl->getTemplatedDecl(), DestType); } else if (FunctionDecl *Fun = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()) ) { - NoteOverloadCandidate(Fun); + NoteOverloadCandidate(Fun, DestType); } } } @@ -6915,12 +7932,6 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { if (CToTy.getUnqualifiedType() == CFromTy.getUnqualifiedType() && !CToTy.isAtLeastAsQualifiedAs(CFromTy)) { - // It is dumb that we have to do this here. - while (isa<ArrayType>(CFromTy)) - CFromTy = CFromTy->getAs<ArrayType>()->getElementType(); - while (isa<ArrayType>(CToTy)) - CToTy = CFromTy->getAs<ArrayType>()->getElementType(); - Qualifiers FromQs = CFromTy.getQualifiers(); Qualifiers ToQs = CToTy.getQualifiers(); @@ -7064,9 +8075,8 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { << (unsigned) (Cand->Fix.Kind); // If we can fix the conversion, suggest the FixIts. - for (SmallVector<FixItHint, 1>::iterator - HI = Cand->Fix.Hints.begin(), HE = Cand->Fix.Hints.end(); - HI != HE; ++HI) + for (std::vector<FixItHint>::iterator HI = Cand->Fix.Hints.begin(), + HE = Cand->Fix.Hints.end(); HI != HE; ++HI) FDiag << *HI; S.Diag(Fn->getLocation(), FDiag); @@ -7125,7 +8135,7 @@ void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand, /// Diagnose a failed template-argument deduction. void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, - Expr **Args, unsigned NumArgs) { + unsigned NumArgs) { FunctionDecl *Fn = Cand->Function; // pattern TemplateParameter Param = Cand->DeductionFailure.getTemplateParameter(); @@ -7273,7 +8283,7 @@ void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) { /// more richly for those diagnostic clients that cared, but we'd /// still have to be just as careful with the default diagnostics. void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, - Expr **Args, unsigned NumArgs) { + unsigned NumArgs) { FunctionDecl *Fn = Cand->Function; // Note deleted candidates, but only if they're viable. @@ -7283,7 +8293,8 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc); S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted) - << FnKind << FnDesc << Fn->isDeleted(); + << FnKind << FnDesc + << (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0); MaybeEmitInheritedConstructorNote(S, Fn); return; } @@ -7300,7 +8311,7 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, return DiagnoseArityMismatch(S, Cand, NumArgs); case ovl_fail_bad_deduction: - return DiagnoseBadDeduction(S, Cand, Args, NumArgs); + return DiagnoseBadDeduction(S, Cand, NumArgs); case ovl_fail_trivial_conversion: case ovl_fail_bad_final_conversion: @@ -7309,7 +8320,7 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, case ovl_fail_bad_conversion: { unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0); - for (unsigned N = Cand->Conversions.size(); I != N; ++I) + for (unsigned N = Cand->NumConversions; I != N; ++I) if (Cand->Conversions[I].isBad()) return DiagnoseBadConversion(S, Cand, I); @@ -7361,12 +8372,12 @@ void NoteBuiltinOperatorCandidate(Sema &S, const char *Opc, SourceLocation OpLoc, OverloadCandidate *Cand) { - assert(Cand->Conversions.size() <= 2 && "builtin operator is not binary"); + assert(Cand->NumConversions <= 2 && "builtin operator is not binary"); std::string TypeStr("operator"); TypeStr += Opc; TypeStr += "("; TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString(); - if (Cand->Conversions.size() == 1) { + if (Cand->NumConversions == 1) { TypeStr += ")"; S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr; } else { @@ -7379,7 +8390,7 @@ void NoteBuiltinOperatorCandidate(Sema &S, void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc, OverloadCandidate *Cand) { - unsigned NoOperands = Cand->Conversions.size(); + unsigned NoOperands = Cand->NumConversions; for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) { const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx]; if (ICS.isBad()) break; // all meaningless after first invalid @@ -7483,11 +8494,11 @@ struct CompareOverloadCandidatesForDisplay { // If there's any ordering between the defined conversions... // FIXME: this might not be transitive. - assert(L->Conversions.size() == R->Conversions.size()); + assert(L->NumConversions == R->NumConversions); int leftBetter = 0; unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument); - for (unsigned E = L->Conversions.size(); I != E; ++I) { + for (unsigned E = L->NumConversions; I != E; ++I) { switch (CompareImplicitConversionSequences(S, L->Conversions[I], R->Conversions[I])) { @@ -7537,7 +8548,7 @@ struct CompareOverloadCandidatesForDisplay { /// CompleteNonViableCandidate - Normally, overload resolution only /// computes up to the first. Produces the FixIt set if possible. void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, - Expr **Args, unsigned NumArgs) { + llvm::ArrayRef<Expr *> Args) { assert(!Cand->Viable); // Don't do anything on failures other than bad conversion. @@ -7550,7 +8561,7 @@ void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, // Skip forward to the first bad conversion. unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); - unsigned ConvCount = Cand->Conversions.size(); + unsigned ConvCount = Cand->NumConversions; while (true) { assert(ConvIdx != ConvCount && "no bad conversion in candidate"); ConvIdx++; @@ -7595,7 +8606,7 @@ void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, SuppressUserConversions, /*InOverloadResolution*/ true, /*AllowObjCWritebackConversion=*/ - S.getLangOptions().ObjCAutoRefCount); + S.getLangOpts().ObjCAutoRefCount); return; } @@ -7608,7 +8619,7 @@ void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, SuppressUserConversions, /*InOverloadResolution=*/true, /*AllowObjCWritebackConversion=*/ - S.getLangOptions().ObjCAutoRefCount); + S.getLangOpts().ObjCAutoRefCount); // Store the FixIt in the candidate if it exists. if (!Unfixable && Cand->Conversions[ConvIdx].isBad()) Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S); @@ -7625,7 +8636,7 @@ void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, /// set. void OverloadCandidateSet::NoteCandidates(Sema &S, OverloadCandidateDisplayKind OCD, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, const char *Opc, SourceLocation OpLoc) { // Sort the candidates by viability and position. Sorting directly would @@ -7636,7 +8647,7 @@ void OverloadCandidateSet::NoteCandidates(Sema &S, if (Cand->Viable) Cands.push_back(Cand); else if (OCD == OCD_AllCandidates) { - CompleteNonViableCandidate(S, Cand, Args, NumArgs); + CompleteNonViableCandidate(S, Cand, Args); if (Cand->Function || Cand->IsSurrogate) Cands.push_back(Cand); // Otherwise, this a non-viable builtin candidate. We do not, in general, @@ -7665,7 +8676,7 @@ void OverloadCandidateSet::NoteCandidates(Sema &S, ++CandsShown; if (Cand->Function) - NoteFunctionCandidate(S, Cand, Args, NumArgs); + NoteFunctionCandidate(S, Cand, Args.size()); else if (Cand->IsSurrogate) NoteSurrogateCandidate(S, Cand); else { @@ -7854,7 +8865,7 @@ private: return false; if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(Fn)) { - if (S.getLangOptions().CUDA) + if (S.getLangOpts().CUDA) if (FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext)) if (S.CheckCUDATarget(Caller, FunDecl)) return false; @@ -7932,7 +8943,7 @@ private: << Matches[0].second->getDeclName(), S.PDiag(diag::note_ovl_candidate) << (unsigned) oc_function_template, - Complain); + Complain, TargetFunctionType); if (Result != MatchesCopy.end()) { // Make it the first and only element @@ -7961,7 +8972,7 @@ public: S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_no_viable) << OvlExpr->getName() << TargetFunctionType << OvlExpr->getSourceRange(); - S.NoteAllOverloadCandidates(OvlExpr); + S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType); } bool IsInvalidFormOfPointerToMemberFunction() const { @@ -7987,9 +8998,11 @@ public: S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_ambiguous) << OvlExpr->getName() << OvlExpr->getSourceRange(); - S.NoteAllOverloadCandidates(OvlExpr); + S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType); } - + + bool hadMultipleCandidates() const { return (OvlExpr->getNumDecls() > 1); } + int getNumMatches() const { return Matches.size(); } FunctionDecl* getMatchingFunctionDecl() const { @@ -8019,16 +9032,18 @@ public: /// resolved, and NULL otherwise. When @p Complain is true, this /// routine will emit diagnostics if there is an error. FunctionDecl * -Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType, - bool Complain, - DeclAccessPair &FoundResult) { - +Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, + QualType TargetType, + bool Complain, + DeclAccessPair &FoundResult, + bool *pHadMultipleCandidates) { assert(AddressOfExpr->getType() == Context.OverloadTy); - - AddressOfFunctionResolver Resolver(*this, AddressOfExpr, TargetType, Complain); + + AddressOfFunctionResolver Resolver(*this, AddressOfExpr, TargetType, + Complain); int NumMatches = Resolver.getNumMatches(); FunctionDecl* Fn = 0; - if ( NumMatches == 0 && Complain) { + if (NumMatches == 0 && Complain) { if (Resolver.IsInvalidFormOfPointerToMemberFunction()) Resolver.ComplainIsInvalidFormOfPointerToMemberFunction(); else @@ -8040,11 +9055,13 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetTyp Fn = Resolver.getMatchingFunctionDecl(); assert(Fn); FoundResult = *Resolver.getMatchingFunctionAccessPair(); - MarkDeclarationReferenced(AddressOfExpr->getLocStart(), Fn); + MarkFunctionReferenced(AddressOfExpr->getLocStart(), Fn); if (Complain) CheckAddressOfMemberAccess(AddressOfExpr, FoundResult); } - + + if (pHadMultipleCandidates) + *pHadMultipleCandidates = Resolver.hadMultipleCandidates(); return Fn; } @@ -8146,7 +9163,7 @@ bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization( ExprResult SingleFunctionExpression; if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization( ovl.Expression, /*complain*/ false, &found)) { - if (DiagnoseUseOfDecl(fn, SrcExpr.get()->getSourceRange().getBegin())) { + if (DiagnoseUseOfDecl(fn, SrcExpr.get()->getLocStart())) { SrcExpr = ExprError(); return true; } @@ -8212,7 +9229,7 @@ bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization( static void AddOverloadedCallCandidate(Sema &S, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool PartialOverloading, bool KnownValid) { @@ -8225,16 +9242,15 @@ static void AddOverloadedCallCandidate(Sema &S, assert(!KnownValid && "Explicit template arguments?"); return; } - S.AddOverloadCandidate(Func, FoundDecl, Args, NumArgs, CandidateSet, - false, PartialOverloading); + S.AddOverloadCandidate(Func, FoundDecl, Args, CandidateSet, false, + PartialOverloading); return; } if (FunctionTemplateDecl *FuncTemplate = dyn_cast<FunctionTemplateDecl>(Callee)) { S.AddTemplateOverloadCandidate(FuncTemplate, FoundDecl, - ExplicitTemplateArgs, - Args, NumArgs, CandidateSet); + ExplicitTemplateArgs, Args, CandidateSet); return; } @@ -8244,7 +9260,7 @@ static void AddOverloadedCallCandidate(Sema &S, /// \brief Add the overload candidates named by callee and/or found by argument /// dependent lookup to the given overload set. void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool PartialOverloading) { @@ -8287,16 +9303,15 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(), E = ULE->decls_end(); I != E; ++I) - AddOverloadedCallCandidate(*this, I.getPair(), ExplicitTemplateArgs, - Args, NumArgs, CandidateSet, - PartialOverloading, /*KnownValid*/ true); + AddOverloadedCallCandidate(*this, I.getPair(), ExplicitTemplateArgs, Args, + CandidateSet, PartialOverloading, + /*KnownValid*/ true); if (ULE->requiresADL()) AddArgumentDependentLookupCandidates(ULE->getName(), /*Operator*/ false, - Args, NumArgs, - ExplicitTemplateArgs, - CandidateSet, - PartialOverloading, + ULE->getExprLoc(), + Args, ExplicitTemplateArgs, + CandidateSet, PartialOverloading, ULE->isStdAssociatedNamespace()); } @@ -8310,11 +9325,14 @@ static bool DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, const CXXScopeSpec &SS, LookupResult &R, TemplateArgumentListInfo *ExplicitTemplateArgs, - Expr **Args, unsigned NumArgs) { + llvm::ArrayRef<Expr *> Args) { if (SemaRef.ActiveTemplateInstantiations.empty() || !SS.isEmpty()) return false; for (DeclContext *DC = SemaRef.CurContext; DC; DC = DC->getParent()) { + if (DC->isTransparentContext()) + continue; + SemaRef.LookupQualifiedName(R, DC); if (!R.empty()) { @@ -8330,7 +9348,7 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, OverloadCandidateSet Candidates(FnLoc); for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) AddOverloadedCallCandidate(SemaRef, I.getPair(), - ExplicitTemplateArgs, Args, NumArgs, + ExplicitTemplateArgs, Args, Candidates, false, /*KnownValid*/ false); OverloadCandidateSet::iterator Best; @@ -8345,7 +9363,7 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, // declaring the function there instead. Sema::AssociatedNamespaceSet AssociatedNamespaces; Sema::AssociatedClassSet AssociatedClasses; - SemaRef.FindAssociatedClassesAndNamespaces(Args, NumArgs, + SemaRef.FindAssociatedClassesAndNamespaces(Args, AssociatedNamespaces, AssociatedClasses); // Never suggest declaring a function within namespace 'std'. @@ -8399,12 +9417,75 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, static bool DiagnoseTwoPhaseOperatorLookup(Sema &SemaRef, OverloadedOperatorKind Op, SourceLocation OpLoc, - Expr **Args, unsigned NumArgs) { + llvm::ArrayRef<Expr *> Args) { DeclarationName OpName = SemaRef.Context.DeclarationNames.getCXXOperatorName(Op); LookupResult R(SemaRef, OpName, OpLoc, Sema::LookupOperatorName); return DiagnoseTwoPhaseLookup(SemaRef, OpLoc, CXXScopeSpec(), R, - /*ExplicitTemplateArgs=*/0, Args, NumArgs); + /*ExplicitTemplateArgs=*/0, Args); +} + +namespace { +// Callback to limit the allowed keywords and to only accept typo corrections +// that are keywords or whose decls refer to functions (or template functions) +// that accept the given number of arguments. +class RecoveryCallCCC : public CorrectionCandidateCallback { + public: + RecoveryCallCCC(Sema &SemaRef, unsigned NumArgs, bool HasExplicitTemplateArgs) + : NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs) { + WantTypeSpecifiers = SemaRef.getLangOpts().CPlusPlus; + WantRemainingKeywords = false; + } + + virtual bool 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(); + if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND)) + FD = FTD->getTemplatedDecl(); + if (!HasExplicitTemplateArgs && !FD) { + if (!(FD = dyn_cast<FunctionDecl>(ND)) && isa<ValueDecl>(ND)) { + // If the Decl is neither a function nor a template function, + // determine if it is a pointer or reference to a function. If so, + // check against the number of arguments expected for the pointee. + QualType ValType = cast<ValueDecl>(ND)->getType(); + if (ValType->isAnyPointerType() || ValType->isReferenceType()) + ValType = ValType->getPointeeType(); + if (const FunctionProtoType *FPT = ValType->getAs<FunctionProtoType>()) + if (FPT->getNumArgs() == NumArgs) + return true; + } + } + if (FD && FD->getNumParams() >= NumArgs && + FD->getMinRequiredArguments() <= NumArgs) + return true; + } + return false; + } + + private: + unsigned NumArgs; + bool HasExplicitTemplateArgs; +}; + +// Callback that effectively disabled typo correction +class NoTypoCorrectionCCC : public CorrectionCandidateCallback { + public: + NoTypoCorrectionCCC() { + WantTypeSpecifiers = false; + WantExpressionKeywords = false; + WantCXXNamedCasts = false; + WantRemainingKeywords = false; + } + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + return false; + } +}; } /// Attempts to recover from a call where no functions were found. @@ -8414,12 +9495,13 @@ static ExprResult BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc, - Expr **Args, unsigned NumArgs, + llvm::MutableArrayRef<Expr *> Args, SourceLocation RParenLoc, - bool EmptyLookup) { + bool EmptyLookup, bool AllowTypoCorrection) { CXXScopeSpec SS; SS.Adopt(ULE->getQualifierLoc()); + SourceLocation TemplateKWLoc = ULE->getTemplateKeywordLoc(); TemplateArgumentListInfo TABuffer; TemplateArgumentListInfo *ExplicitTemplateArgs = 0; @@ -8430,11 +9512,16 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(), Sema::LookupOrdinaryName); + RecoveryCallCCC Validator(SemaRef, Args.size(), ExplicitTemplateArgs != 0); + NoTypoCorrectionCCC RejectAll; + CorrectionCandidateCallback *CCC = AllowTypoCorrection ? + (CorrectionCandidateCallback*)&Validator : + (CorrectionCandidateCallback*)&RejectAll; if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R, - ExplicitTemplateArgs, Args, NumArgs) && + ExplicitTemplateArgs, Args) && (!EmptyLookup || - SemaRef.DiagnoseEmptyLookup(S, SS, R, Sema::CTC_Expression, - ExplicitTemplateArgs, Args, NumArgs))) + SemaRef.DiagnoseEmptyLookup(S, SS, R, *CCC, + ExplicitTemplateArgs, Args))) return ExprError(); assert(!R.empty() && "lookup results empty despite recovery"); @@ -8443,10 +9530,11 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, // casts and such from the call, we don't really care. ExprResult NewFn = ExprError(); if ((*R.begin())->isCXXClassMember()) - NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, R, - ExplicitTemplateArgs); - else if (ExplicitTemplateArgs) - NewFn = SemaRef.BuildTemplateIdExpr(SS, R, false, *ExplicitTemplateArgs); + NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, + R, ExplicitTemplateArgs); + else if (ExplicitTemplateArgs || TemplateKWLoc.isValid()) + NewFn = SemaRef.BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, + ExplicitTemplateArgs); else NewFn = SemaRef.BuildDeclarationNameExpr(SS, R, false); @@ -8457,7 +9545,8 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, // an expression with viable lookup results, which should never // end up here. return SemaRef.ActOnCallExpr(/*Scope*/ 0, NewFn.take(), LParenLoc, - MultiExprArg(Args, NumArgs), RParenLoc); + MultiExprArg(Args.data(), Args.size()), + RParenLoc); } /// ResolveOverloadedCallFn - Given the call expression that calls Fn @@ -8472,7 +9561,8 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc, - Expr *ExecConfig) { + Expr *ExecConfig, + bool AllowTypoCorrection) { #ifndef NDEBUG if (ULE->requiresADL()) { // To do ADL, we must have found an unqualified name. @@ -8487,17 +9577,22 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, llvm_unreachable("performing ADL for builtin"); // We don't perform ADL in C. - assert(getLangOptions().CPlusPlus && "ADL enabled in C"); + assert(getLangOpts().CPlusPlus && "ADL enabled in C"); } else assert(!ULE->isStdAssociatedNamespace() && "std is associated namespace but not doing ADL"); #endif + UnbridgedCastsSet UnbridgedCasts; + if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts)) + return ExprError(); + OverloadCandidateSet CandidateSet(Fn->getExprLoc()); // Add the functions denoted by the callee to the set of candidate // functions, including those from argument-dependent lookup. - AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet); + AddOverloadedCallCandidates(ULE, llvm::makeArrayRef(Args, NumArgs), + CandidateSet); // If we found nothing, try to recover. // BuildRecoveryCallExpr diagnoses the error itself, so we just bail @@ -8507,26 +9602,29 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, // 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 (getLangOptions().MicrosoftExt && CurContext->isDependentContext() && - isa<CXXMethodDecl>(CurContext)) { + if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() && + (isa<FunctionDecl>(CurContext) || isa<CXXRecordDecl>(CurContext))) { CallExpr *CE = new (Context) CallExpr(Context, Fn, Args, NumArgs, Context.DependentTy, VK_RValue, RParenLoc); CE->setTypeDependent(true); return Owned(CE); } - return BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, Args, NumArgs, - RParenLoc, /*EmptyLookup=*/true); + return BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, + llvm::MutableArrayRef<Expr *>(Args, NumArgs), + RParenLoc, /*EmptyLookup=*/true, + AllowTypoCorrection); } + UnbridgedCasts.restore(); + OverloadCandidateSet::iterator Best; switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) { case OR_Success: { FunctionDecl *FDecl = Best->Function; - MarkDeclarationReferenced(Fn->getExprLoc(), FDecl); + MarkFunctionReferenced(Fn->getExprLoc(), FDecl); CheckUnresolvedLookupAccess(ULE, Best->FoundDecl); - DiagnoseUseOfDecl(FDecl? FDecl : Best->FoundDecl.getDecl(), - ULE->getNameLoc()); + DiagnoseUseOfDecl(FDecl, ULE->getNameLoc()); Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl); return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc, ExecConfig); @@ -8536,34 +9634,45 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, // Try to recover by looking for viable functions which the user might // have meant to call. ExprResult Recovery = BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, - Args, NumArgs, RParenLoc, - /*EmptyLookup=*/false); + llvm::MutableArrayRef<Expr *>(Args, NumArgs), + RParenLoc, + /*EmptyLookup=*/false, + AllowTypoCorrection); if (!Recovery.isInvalid()) return Recovery; - Diag(Fn->getSourceRange().getBegin(), + Diag(Fn->getLocStart(), diag::err_ovl_no_viable_function_in_call) << ULE->getName() << Fn->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); break; } case OR_Ambiguous: - Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_ambiguous_call) + Diag(Fn->getLocStart(), diag::err_ovl_ambiguous_call) << ULE->getName() << Fn->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, + llvm::makeArrayRef(Args, NumArgs)); break; case OR_Deleted: { - Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call) + Diag(Fn->getLocStart(), diag::err_ovl_deleted_call) << Best->Function->isDeleted() << ULE->getName() << getDeletedOrUnavailableSuffix(Best->Function) << Fn->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); + + // We emitted an error for the unvailable/deleted function call but keep + // the call in the AST. + FunctionDecl *FDecl = Best->Function; + Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl); + return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, + RParenLoc, ExecConfig); } - break; } // Overload resolution failed. @@ -8603,12 +9712,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // TODO: provide better source location info. DeclarationNameInfo OpNameInfo(OpName, OpLoc); - if (Input->getObjectKind() == OK_ObjCProperty) { - ExprResult Result = ConvertPropertyForRValue(Input); - if (Result.isInvalid()) - return ExprError(); - Input = Result.take(); - } + if (checkPlaceholderForOverload(*this, Input)) + return ExprError(); Expr *Args[2] = { Input, 0 }; unsigned NumArgs = 1; @@ -8648,14 +9753,15 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, OverloadCandidateSet CandidateSet(OpLoc); // Add the candidates from the given function set. - AddFunctionCandidates(Fns, &Args[0], NumArgs, CandidateSet, false); + AddFunctionCandidates(Fns, llvm::makeArrayRef(Args, NumArgs), CandidateSet, + false); // Add operator candidates that are member functions. AddMemberOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet); // Add candidates from ADL. AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true, - Args, NumArgs, + OpLoc, llvm::makeArrayRef(Args, NumArgs), /*ExplicitTemplateArgs*/ 0, CandidateSet); @@ -8675,7 +9781,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // We matched an overloaded operator. Build a call to that // operator. - MarkDeclarationReferenced(OpLoc, FnDecl); + MarkFunctionReferenced(OpLoc, FnDecl); // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { @@ -8709,7 +9815,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // Build the actual expression node. ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, - HadMultipleCandidates); + HadMultipleCandidates, OpLoc); if (FnExpr.isInvalid()) return ExprError(); @@ -8741,7 +9847,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // This is an erroneous use of an operator which can be overloaded by // a non-member function. Check for non-member operators which were // defined too late to be candidates. - if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, Args, NumArgs)) + if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, + llvm::makeArrayRef(Args, NumArgs))) // FIXME: Recover by calling the found function. return ExprError(); @@ -8754,7 +9861,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, << UnaryOperator::getOpcodeStr(Opc) << Input->getType() << Input->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs, + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, + llvm::makeArrayRef(Args, NumArgs), UnaryOperator::getOpcodeStr(Opc), OpLoc); return ExprError(); @@ -8764,7 +9872,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, << UnaryOperator::getOpcodeStr(Opc) << getDeletedOrUnavailableSuffix(Best->Function) << Input->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs, + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs), UnaryOperator::getOpcodeStr(Opc), OpLoc); return ExprError(); } @@ -8841,45 +9950,15 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, OpLoc)); } - // Always do property rvalue conversions on the RHS. - if (Args[1]->getObjectKind() == OK_ObjCProperty) { - ExprResult Result = ConvertPropertyForRValue(Args[1]); - if (Result.isInvalid()) - return ExprError(); - Args[1] = Result.take(); - } - - // The LHS is more complicated. - if (Args[0]->getObjectKind() == OK_ObjCProperty) { - - // There's a tension for assignment operators between primitive - // property assignment and the overloaded operators. - if (BinaryOperator::isAssignmentOp(Opc)) { - const ObjCPropertyRefExpr *PRE = LHS->getObjCProperty(); - - // Is the property "logically" settable? - bool Settable = (PRE->isExplicitProperty() || - PRE->getImplicitPropertySetter()); - - // To avoid gratuitously inventing semantics, use the primitive - // unless it isn't. Thoughts in case we ever really care: - // - If the property isn't logically settable, we have to - // load and hope. - // - If the property is settable and this is simple assignment, - // we really should use the primitive. - // - If the property is settable, then we could try overloading - // on a generic lvalue of the appropriate type; if it works - // out to a builtin candidate, we would do that same operation - // on the property, and otherwise just error. - if (Settable) - return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); - } + // Always do placeholder-like conversions on the RHS. + if (checkPlaceholderForOverload(*this, Args[1])) + return ExprError(); - ExprResult Result = ConvertPropertyForRValue(Args[0]); - if (Result.isInvalid()) - return ExprError(); - Args[0] = Result.take(); - } + // Do placeholder-like conversion on the LHS; note that we should + // not get here with a PseudoObject LHS. + assert(Args[0]->getObjectKind() != OK_ObjCProperty); + if (checkPlaceholderForOverload(*this, Args[0])) + return ExprError(); // If this is the assignment operator, we only perform overload resolution // if the left-hand side is a class or enumeration type. This is actually @@ -8899,14 +9978,14 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, OverloadCandidateSet CandidateSet(OpLoc); // Add the candidates from the given function set. - AddFunctionCandidates(Fns, Args, 2, CandidateSet, false); + AddFunctionCandidates(Fns, Args, CandidateSet, false); // Add operator candidates that are member functions. AddMemberOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet); // Add candidates from ADL. AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true, - Args, 2, + OpLoc, Args, /*ExplicitTemplateArgs*/ 0, CandidateSet); @@ -8926,7 +10005,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // We matched an overloaded operator. Build a call to that // operator. - MarkDeclarationReferenced(OpLoc, FnDecl); + MarkFunctionReferenced(OpLoc, FnDecl); // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { @@ -9032,7 +10111,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // This is an erroneous use of an operator which can be overloaded by // a non-member function. Check for non-member operators which were // defined too late to be candidates. - if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, Args, 2)) + if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, Args)) // FIXME: Recover by calling the found function. return ExprError(); @@ -9043,7 +10122,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, assert(Result.isInvalid() && "C++ binary operator overloading is missing candidates!"); if (Result.isInvalid()) - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2, + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, BinaryOperator::getOpcodeStr(Opc), OpLoc); return move(Result); } @@ -9053,17 +10132,32 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, << BinaryOperator::getOpcodeStr(Opc) << Args[0]->getType() << Args[1]->getType() << Args[0]->getSourceRange() << Args[1]->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, 2, + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, BinaryOperator::getOpcodeStr(Opc), OpLoc); return ExprError(); case OR_Deleted: - Diag(OpLoc, diag::err_ovl_deleted_oper) - << Best->Function->isDeleted() - << BinaryOperator::getOpcodeStr(Opc) - << getDeletedOrUnavailableSuffix(Best->Function) - << Args[0]->getSourceRange() << Args[1]->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2, + if (isImplicitlyDeleted(Best->Function)) { + CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function); + Diag(OpLoc, diag::err_ovl_deleted_special_oper) + << getSpecialMember(Method) + << BinaryOperator::getOpcodeStr(Opc) + << getDeletedOrUnavailableSuffix(Best->Function); + + if (getSpecialMember(Method) != CXXInvalid) { + // The user probably meant to call this special member. Just + // explain why it's deleted. + NoteDeletedFunction(Method); + return ExprError(); + } + } else { + Diag(OpLoc, diag::err_ovl_deleted_oper) + << Best->Function->isDeleted() + << BinaryOperator::getOpcodeStr(Opc) + << getDeletedOrUnavailableSuffix(Best->Function) + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + } + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, BinaryOperator::getOpcodeStr(Opc), OpLoc); return ExprError(); } @@ -9103,18 +10197,11 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, RLoc)); } - if (Args[0]->getObjectKind() == OK_ObjCProperty) { - ExprResult Result = ConvertPropertyForRValue(Args[0]); - if (Result.isInvalid()) - return ExprError(); - Args[0] = Result.take(); - } - if (Args[1]->getObjectKind() == OK_ObjCProperty) { - ExprResult Result = ConvertPropertyForRValue(Args[1]); - if (Result.isInvalid()) - return ExprError(); - Args[1] = Result.take(); - } + // Handle placeholders on both operands. + if (checkPlaceholderForOverload(*this, Args[0])) + return ExprError(); + if (checkPlaceholderForOverload(*this, Args[1])) + return ExprError(); // Build an empty overload set. OverloadCandidateSet CandidateSet(LLoc); @@ -9140,7 +10227,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // We matched an overloaded operator. Build a call to that // operator. - MarkDeclarationReferenced(LLoc, FnDecl); + MarkFunctionReferenced(LLoc, FnDecl); CheckMemberOperatorAccess(LLoc, Args[0], Args[1], Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, LLoc); @@ -9172,12 +10259,12 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, ResultTy = ResultTy.getNonLValueExprType(Context); // Build the actual expression node. - DeclarationNameLoc LocInfo; - LocInfo.CXXOperatorName.BeginOpNameLoc = LLoc.getRawEncoding(); - LocInfo.CXXOperatorName.EndOpNameLoc = RLoc.getRawEncoding(); + DeclarationNameInfo OpLocInfo(OpName, LLoc); + OpLocInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc)); ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, HadMultipleCandidates, - LLoc, LocInfo); + OpLocInfo.getLoc(), + OpLocInfo.getInfo()); if (FnExpr.isInvalid()) return ExprError(); @@ -9222,7 +10309,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, Diag(LLoc, diag::err_ovl_no_viable_subscript) << Args[0]->getType() << Args[0]->getSourceRange() << Args[1]->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2, + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, "[]", LLoc); return ExprError(); } @@ -9232,7 +10319,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, << "[]" << Args[0]->getType() << Args[1]->getType() << Args[0]->getSourceRange() << Args[1]->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, 2, + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, "[]", LLoc); return ExprError(); @@ -9241,7 +10328,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, << Best->Function->isDeleted() << "[]" << getDeletedOrUnavailableSuffix(Best->Function) << Args[0]->getSourceRange() << Args[1]->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2, + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, "[]", LLoc); return ExprError(); } @@ -9305,7 +10392,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, resultType, valueKind, RParenLoc); if (CheckCallReturnType(proto->getResultType(), - op->getRHS()->getSourceRange().getBegin(), + op->getRHS()->getLocStart(), call, 0)) return ExprError(); @@ -9315,6 +10402,10 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, return MaybeBindToTemporary(call); } + UnbridgedCastsSet UnbridgedCasts; + if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts)) + return ExprError(); + MemberExpr *MemExpr; CXXMethodDecl *Method = 0; DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public); @@ -9324,6 +10415,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl()); FoundDecl = MemExpr->getFoundDecl(); Qualifier = MemExpr->getQualifier(); + UnbridgedCasts.restore(); } else { UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr); Qualifier = UnresExpr->getQualifier(); @@ -9353,9 +10445,9 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // Microsoft supports direct constructor calls. - if (getLangOptions().MicrosoftExt && isa<CXXConstructorDecl>(Func)) { - AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), Args, NumArgs, - CandidateSet); + if (getLangOpts().MicrosoftExt && isa<CXXConstructorDecl>(Func)) { + AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), + llvm::makeArrayRef(Args, NumArgs), CandidateSet); } else if ((Method = dyn_cast<CXXMethodDecl>(Func))) { // If explicit template arguments were provided, we can't call a // non-template member function. @@ -9364,25 +10456,28 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, AddMethodCandidate(Method, I.getPair(), ActingDC, ObjectType, ObjectClassification, - Args, NumArgs, CandidateSet, + llvm::makeArrayRef(Args, NumArgs), CandidateSet, /*SuppressUserConversions=*/false); } else { AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func), I.getPair(), ActingDC, TemplateArgs, ObjectType, ObjectClassification, - Args, NumArgs, CandidateSet, + llvm::makeArrayRef(Args, NumArgs), + CandidateSet, /*SuppressUsedConversions=*/false); } } DeclarationName DeclName = UnresExpr->getMemberName(); + UnbridgedCasts.restore(); + OverloadCandidateSet::iterator Best; switch (CandidateSet.BestViableFunction(*this, UnresExpr->getLocStart(), Best)) { case OR_Success: Method = cast<CXXMethodDecl>(Best->Function); - MarkDeclarationReferenced(UnresExpr->getMemberLoc(), Method); + MarkFunctionReferenced(UnresExpr->getMemberLoc(), Method); FoundDecl = Best->FoundDecl; CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()); @@ -9392,14 +10487,16 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, Diag(UnresExpr->getMemberLoc(), diag::err_ovl_no_viable_member_function_in_call) << DeclName << MemExprE->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); // FIXME: Leaking incoming expressions! return ExprError(); case OR_Ambiguous: Diag(UnresExpr->getMemberLoc(), diag::err_ovl_ambiguous_member_call) << DeclName << MemExprE->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); // FIXME: Leaking incoming expressions! return ExprError(); @@ -9409,7 +10506,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, << DeclName << getDeletedOrUnavailableSuffix(Best->Function) << MemExprE->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); // FIXME: Leaking incoming expressions! return ExprError(); } @@ -9459,6 +10557,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, RParenLoc)) return ExprError(); + DiagnoseSentinelCalls(Method, LParenLoc, Args, NumArgs); + if (CheckFunctionCall(Method, TheCall)) return ExprError(); @@ -9488,12 +10588,13 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc) { + if (checkPlaceholderForOverload(*this, Obj)) + return ExprError(); ExprResult Object = Owned(Obj); - if (Object.get()->getObjectKind() == OK_ObjCProperty) { - Object = ConvertPropertyForRValue(Object.take()); - if (Object.isInvalid()) - return ExprError(); - } + + UnbridgedCastsSet UnbridgedCasts; + if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts)) + return ExprError(); assert(Object.get()->getType()->isRecordType() && "Requires object type argument"); const RecordType *Record = Object.get()->getType()->getAs<RecordType>(); @@ -9566,7 +10667,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>()) { AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto, - Object.get(), Args, NumArgs, CandidateSet); + Object.get(), llvm::makeArrayRef(Args, NumArgs), + CandidateSet); } } } @@ -9584,37 +10686,42 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, case OR_No_Viable_Function: if (CandidateSet.empty()) - Diag(Object.get()->getSourceRange().getBegin(), diag::err_ovl_no_oper) + Diag(Object.get()->getLocStart(), diag::err_ovl_no_oper) << Object.get()->getType() << /*call*/ 1 << Object.get()->getSourceRange(); else - Diag(Object.get()->getSourceRange().getBegin(), + Diag(Object.get()->getLocStart(), diag::err_ovl_no_viable_object_call) << Object.get()->getType() << Object.get()->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); break; case OR_Ambiguous: - Diag(Object.get()->getSourceRange().getBegin(), + Diag(Object.get()->getLocStart(), diag::err_ovl_ambiguous_object_call) << Object.get()->getType() << Object.get()->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, + llvm::makeArrayRef(Args, NumArgs)); break; case OR_Deleted: - Diag(Object.get()->getSourceRange().getBegin(), + Diag(Object.get()->getLocStart(), diag::err_ovl_deleted_object_call) << Best->Function->isDeleted() << Object.get()->getType() << getDeletedOrUnavailableSuffix(Best->Function) << Object.get()->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); break; } if (Best == CandidateSet.end()) return true; + UnbridgedCasts.restore(); + if (Best->Function == 0) { // Since there is no function declaration, this is one of the // surrogate candidates. Dig out the conversion function. @@ -9635,12 +10742,16 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, Conv, HadMultipleCandidates); 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)); return ActOnCallExpr(S, Call.get(), LParenLoc, MultiExprArg(Args, NumArgs), RParenLoc); } - MarkDeclarationReferenced(LParenLoc, Best->Function); + MarkFunctionReferenced(LParenLoc, Best->Function); CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc); @@ -9668,8 +10779,13 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) MethodArgs[ArgIdx + 1] = Args[ArgIdx]; + DeclarationNameInfo OpLocInfo( + Context.DeclarationNames.getCXXOperatorName(OO_Call), LParenLoc); + OpLocInfo.setCXXOperatorNameRange(SourceRange(LParenLoc, RParenLoc)); ExprResult NewFn = CreateFunctionRefExpr(*this, Method, - HadMultipleCandidates); + HadMultipleCandidates, + OpLocInfo.getLoc(), + OpLocInfo.getInfo()); if (NewFn.isInvalid()) return true; @@ -9750,6 +10866,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, if (IsError) return true; + DiagnoseSentinelCalls(Method, LParenLoc, Args, NumArgs); + if (CheckFunctionCall(Method, TheCall)) return true; @@ -9764,12 +10882,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { assert(Base->getType()->isRecordType() && "left-hand side must have class type"); - if (Base->getObjectKind() == OK_ObjCProperty) { - ExprResult Result = ConvertPropertyForRValue(Base); - if (Result.isInvalid()) - return ExprError(); - Base = Result.take(); - } + if (checkPlaceholderForOverload(*this, Base)) + return ExprError(); SourceLocation Loc = Base->getExprLoc(); @@ -9815,13 +10929,13 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { else Diag(OpLoc, diag::err_ovl_no_viable_oper) << "operator->" << Base->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Base); return ExprError(); case OR_Ambiguous: Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary) << "->" << Base->getType() << Base->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, &Base, 1); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Base); return ExprError(); case OR_Deleted: @@ -9830,11 +10944,11 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { << "->" << getDeletedOrUnavailableSuffix(Best->Function) << Base->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Base); return ExprError(); } - MarkDeclarationReferenced(OpLoc, Best->Function); + MarkFunctionReferenced(OpLoc, Best->Function); CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); @@ -9849,7 +10963,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { // Build the operator call. ExprResult FnExpr = CreateFunctionRefExpr(*this, Method, - HadMultipleCandidates); + HadMultipleCandidates, OpLoc); if (FnExpr.isInvalid()) return ExprError(); @@ -9867,6 +10981,80 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { return MaybeBindToTemporary(TheCall); } +/// BuildLiteralOperatorCall - Build a UserDefinedLiteral by creating a call to +/// a literal operator described by the provided lookup results. +ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, + DeclarationNameInfo &SuffixInfo, + ArrayRef<Expr*> Args, + SourceLocation LitEndLoc, + TemplateArgumentListInfo *TemplateArgs) { + SourceLocation UDSuffixLoc = SuffixInfo.getCXXLiteralOperatorNameLoc(); + + OverloadCandidateSet CandidateSet(UDSuffixLoc); + AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, true, + TemplateArgs); + + bool HadMultipleCandidates = (CandidateSet.size() > 1); + + // Perform overload resolution. This will usually be trivial, but might need + // to perform substitutions for a literal operator template. + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, UDSuffixLoc, Best)) { + case OR_Success: + case OR_Deleted: + break; + + case OR_No_Viable_Function: + Diag(UDSuffixLoc, diag::err_ovl_no_viable_function_in_call) + << R.getLookupName(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); + return ExprError(); + + case OR_Ambiguous: + Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName(); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args); + return ExprError(); + } + + FunctionDecl *FD = Best->Function; + MarkFunctionReferenced(UDSuffixLoc, FD); + DiagnoseUseOfDecl(Best->FoundDecl, UDSuffixLoc); + + ExprResult Fn = CreateFunctionRefExpr(*this, FD, HadMultipleCandidates, + SuffixInfo.getLoc(), + SuffixInfo.getInfo()); + if (Fn.isInvalid()) + return true; + + // Check the argument types. This should almost always be a no-op, except + // that array-to-pointer decay is applied to string literals. + Expr *ConvArgs[2]; + for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) { + ExprResult InputInit = PerformCopyInitialization( + InitializedEntity::InitializeParameter(Context, FD->getParamDecl(ArgIdx)), + SourceLocation(), Args[ArgIdx]); + if (InputInit.isInvalid()) + return true; + ConvArgs[ArgIdx] = InputInit.take(); + } + + QualType ResultTy = FD->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + + UserDefinedLiteral *UDL = + new (Context) UserDefinedLiteral(Context, Fn.take(), ConvArgs, Args.size(), + ResultTy, VK, LitEndLoc, UDSuffixLoc); + + if (CheckCallReturnType(FD->getResultType(), UDSuffixLoc, UDL, FD)) + return ExprError(); + + if (CheckFunctionCall(FD, UDL)) + return ExprError(); + + return MaybeBindToTemporary(UDL); +} + /// FixOverloadedFunctionReference - E is an expression that refers to /// a C++ overloaded function (possibly with some parentheses and /// perhaps a '&' around it). We have resolved the overloaded function @@ -9954,7 +11142,9 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, DeclRefExpr *DRE = DeclRefExpr::Create(Context, ULE->getQualifierLoc(), + ULE->getTemplateKeywordLoc(), Fn, + /*enclosing*/ false, // FIXME? ULE->getNameLoc(), Fn->getType(), VK_LValue, @@ -9980,7 +11170,9 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, if (cast<CXXMethodDecl>(Fn)->isStatic()) { DeclRefExpr *DRE = DeclRefExpr::Create(Context, MemExpr->getQualifierLoc(), + MemExpr->getTemplateKeywordLoc(), Fn, + /*enclosing*/ false, MemExpr->getMemberLoc(), Fn->getType(), VK_LValue, @@ -9992,6 +11184,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, SourceLocation Loc = MemExpr->getMemberLoc(); if (MemExpr->getQualifier()) Loc = MemExpr->getQualifierLoc().getBeginLoc(); + CheckCXXThisCapture(Loc); Base = new (Context) CXXThisExpr(Loc, MemExpr->getBaseType(), /*isImplicit=*/true); @@ -10012,6 +11205,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, MemberExpr *ME = MemberExpr::Create(Context, Base, MemExpr->isArrow(), MemExpr->getQualifierLoc(), + MemExpr->getTemplateKeywordLoc(), Fn, Found, MemExpr->getMemberNameInfo(), @@ -10022,7 +11216,6 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, } llvm_unreachable("Invalid reference to overloaded function"); - return E; } ExprResult Sema::FixOverloadedFunctionReference(ExprResult E, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp new file mode 100644 index 0000000..d52c912 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp @@ -0,0 +1,1351 @@ +//===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for expressions involving +// pseudo-object references. Pseudo-objects are conceptual objects +// whose storage is entirely abstract and all accesses to which are +// translated through some sort of abstraction barrier. +// +// For example, Objective-C objects can have "properties", either +// declared or undeclared. A property may be accessed by writing +// expr.prop +// where 'expr' is an r-value of Objective-C pointer type and 'prop' +// is the name of the property. If this expression is used in a context +// needing an r-value, it is treated as if it were a message-send +// of the associated 'getter' selector, typically: +// [expr prop] +// If it is used as the LHS of a simple assignment, it is treated +// as a message-send of the associated 'setter' selector, typically: +// [expr setProp: RHS] +// If it is used as the LHS of a compound assignment, or the operand +// of a unary increment or decrement, both are required; for example, +// 'expr.prop *= 100' would be translated to: +// [expr setProp: [expr prop] * 100] +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Initialization.h" +#include "clang/AST/ExprObjC.h" +#include "clang/Lex/Preprocessor.h" + +using namespace clang; +using namespace sema; + +namespace { + // Basically just a very focused copy of TreeTransform. + template <class T> struct Rebuilder { + Sema &S; + Rebuilder(Sema &S) : S(S) {} + + T &getDerived() { return static_cast<T&>(*this); } + + Expr *rebuild(Expr *e) { + // Fast path: nothing to look through. + if (typename T::specific_type *specific + = dyn_cast<typename T::specific_type>(e)) + return getDerived().rebuildSpecific(specific); + + // Otherwise, we should look through and rebuild anything that + // IgnoreParens would. + + if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) { + e = rebuild(parens->getSubExpr()); + return new (S.Context) ParenExpr(parens->getLParen(), + parens->getRParen(), + e); + } + + if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) { + assert(uop->getOpcode() == UO_Extension); + e = rebuild(uop->getSubExpr()); + return new (S.Context) UnaryOperator(e, uop->getOpcode(), + uop->getType(), + uop->getValueKind(), + uop->getObjectKind(), + uop->getOperatorLoc()); + } + + if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) { + assert(!gse->isResultDependent()); + unsigned resultIndex = gse->getResultIndex(); + unsigned numAssocs = gse->getNumAssocs(); + + SmallVector<Expr*, 8> assocs(numAssocs); + SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs); + + for (unsigned i = 0; i != numAssocs; ++i) { + Expr *assoc = gse->getAssocExpr(i); + if (i == resultIndex) assoc = rebuild(assoc); + assocs[i] = assoc; + assocTypes[i] = gse->getAssocTypeSourceInfo(i); + } + + return new (S.Context) GenericSelectionExpr(S.Context, + gse->getGenericLoc(), + gse->getControllingExpr(), + assocTypes.data(), + assocs.data(), + numAssocs, + gse->getDefaultLoc(), + gse->getRParenLoc(), + gse->containsUnexpandedParameterPack(), + resultIndex); + } + + llvm_unreachable("bad expression to rebuild!"); + } + }; + + struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> { + Expr *NewBase; + ObjCPropertyRefRebuilder(Sema &S, Expr *newBase) + : Rebuilder<ObjCPropertyRefRebuilder>(S), NewBase(newBase) {} + + typedef ObjCPropertyRefExpr specific_type; + Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) { + // Fortunately, the constraint that we're rebuilding something + // with a base limits the number of cases here. + assert(refExpr->getBase()); + + if (refExpr->isExplicitProperty()) { + return new (S.Context) + ObjCPropertyRefExpr(refExpr->getExplicitProperty(), + refExpr->getType(), refExpr->getValueKind(), + refExpr->getObjectKind(), refExpr->getLocation(), + NewBase); + } + return new (S.Context) + ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(), + refExpr->getImplicitPropertySetter(), + refExpr->getType(), refExpr->getValueKind(), + refExpr->getObjectKind(),refExpr->getLocation(), + NewBase); + } + }; + + struct ObjCSubscriptRefRebuilder : Rebuilder<ObjCSubscriptRefRebuilder> { + Expr *NewBase; + Expr *NewKeyExpr; + ObjCSubscriptRefRebuilder(Sema &S, Expr *newBase, Expr *newKeyExpr) + : Rebuilder<ObjCSubscriptRefRebuilder>(S), + NewBase(newBase), NewKeyExpr(newKeyExpr) {} + + typedef ObjCSubscriptRefExpr specific_type; + Expr *rebuildSpecific(ObjCSubscriptRefExpr *refExpr) { + assert(refExpr->getBaseExpr()); + assert(refExpr->getKeyExpr()); + + return new (S.Context) + ObjCSubscriptRefExpr(NewBase, + NewKeyExpr, + refExpr->getType(), refExpr->getValueKind(), + refExpr->getObjectKind(),refExpr->getAtIndexMethodDecl(), + refExpr->setAtIndexMethodDecl(), + refExpr->getRBracket()); + } + }; + + class PseudoOpBuilder { + public: + Sema &S; + unsigned ResultIndex; + SourceLocation GenericLoc; + SmallVector<Expr *, 4> Semantics; + + PseudoOpBuilder(Sema &S, SourceLocation genericLoc) + : S(S), ResultIndex(PseudoObjectExpr::NoResult), + GenericLoc(genericLoc) {} + + virtual ~PseudoOpBuilder() {} + + /// Add a normal semantic expression. + void addSemanticExpr(Expr *semantic) { + Semantics.push_back(semantic); + } + + /// Add the 'result' semantic expression. + void addResultSemanticExpr(Expr *resultExpr) { + assert(ResultIndex == PseudoObjectExpr::NoResult); + ResultIndex = Semantics.size(); + Semantics.push_back(resultExpr); + } + + ExprResult buildRValueOperation(Expr *op); + ExprResult buildAssignmentOperation(Scope *Sc, + SourceLocation opLoc, + BinaryOperatorKind opcode, + Expr *LHS, Expr *RHS); + ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc, + UnaryOperatorKind opcode, + Expr *op); + + ExprResult complete(Expr *syntacticForm); + + OpaqueValueExpr *capture(Expr *op); + OpaqueValueExpr *captureValueAsResult(Expr *op); + + void setResultToLastSemantic() { + assert(ResultIndex == PseudoObjectExpr::NoResult); + ResultIndex = Semantics.size() - 1; + } + + /// Return true if assignments have a non-void result. + virtual bool assignmentsHaveResult() { return true; } + + virtual Expr *rebuildAndCaptureObject(Expr *) = 0; + virtual ExprResult buildGet() = 0; + virtual ExprResult buildSet(Expr *, SourceLocation, + bool captureSetValueAsResult) = 0; + }; + + /// A PseudoOpBuilder for Objective-C @properties. + class ObjCPropertyOpBuilder : public PseudoOpBuilder { + ObjCPropertyRefExpr *RefExpr; + ObjCPropertyRefExpr *SyntacticRefExpr; + OpaqueValueExpr *InstanceReceiver; + ObjCMethodDecl *Getter; + + ObjCMethodDecl *Setter; + Selector SetterSelector; + + public: + ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) : + PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr), + SyntacticRefExpr(0), InstanceReceiver(0), Getter(0), Setter(0) { + } + + ExprResult buildRValueOperation(Expr *op); + ExprResult buildAssignmentOperation(Scope *Sc, + SourceLocation opLoc, + BinaryOperatorKind opcode, + Expr *LHS, Expr *RHS); + ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc, + UnaryOperatorKind opcode, + Expr *op); + + bool tryBuildGetOfReference(Expr *op, ExprResult &result); + bool findSetter(); + bool findGetter(); + + Expr *rebuildAndCaptureObject(Expr *syntacticBase); + ExprResult buildGet(); + ExprResult buildSet(Expr *op, SourceLocation, bool); + }; + + /// A PseudoOpBuilder for Objective-C array/dictionary indexing. + class ObjCSubscriptOpBuilder : public PseudoOpBuilder { + ObjCSubscriptRefExpr *RefExpr; + OpaqueValueExpr *InstanceBase; + OpaqueValueExpr *InstanceKey; + ObjCMethodDecl *AtIndexGetter; + Selector AtIndexGetterSelector; + + ObjCMethodDecl *AtIndexSetter; + Selector AtIndexSetterSelector; + + public: + ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) : + PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()), + RefExpr(refExpr), + InstanceBase(0), InstanceKey(0), + AtIndexGetter(0), AtIndexSetter(0) { } + + ExprResult buildRValueOperation(Expr *op); + ExprResult buildAssignmentOperation(Scope *Sc, + SourceLocation opLoc, + BinaryOperatorKind opcode, + Expr *LHS, Expr *RHS); + Expr *rebuildAndCaptureObject(Expr *syntacticBase); + + bool findAtIndexGetter(); + bool findAtIndexSetter(); + + ExprResult buildGet(); + ExprResult buildSet(Expr *op, SourceLocation, bool); + }; + +} + +/// Capture the given expression in an OpaqueValueExpr. +OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) { + // Make a new OVE whose source is the given expression. + OpaqueValueExpr *captured = + new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(), + e->getValueKind(), e->getObjectKind(), + e); + + // Make sure we bind that in the semantics. + addSemanticExpr(captured); + return captured; +} + +/// Capture the given expression as the result of this pseudo-object +/// operation. This routine is safe against expressions which may +/// already be captured. +/// +/// \param Returns the captured expression, which will be the +/// same as the input if the input was already captured +OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) { + assert(ResultIndex == PseudoObjectExpr::NoResult); + + // If the expression hasn't already been captured, just capture it + // and set the new semantic + if (!isa<OpaqueValueExpr>(e)) { + OpaqueValueExpr *cap = capture(e); + setResultToLastSemantic(); + return cap; + } + + // Otherwise, it must already be one of our semantic expressions; + // set ResultIndex to its index. + unsigned index = 0; + for (;; ++index) { + assert(index < Semantics.size() && + "captured expression not found in semantics!"); + if (e == Semantics[index]) break; + } + ResultIndex = index; + return cast<OpaqueValueExpr>(e); +} + +/// The routine which creates the final PseudoObjectExpr. +ExprResult PseudoOpBuilder::complete(Expr *syntactic) { + return PseudoObjectExpr::Create(S.Context, syntactic, + Semantics, ResultIndex); +} + +/// The main skeleton for building an r-value operation. +ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) { + Expr *syntacticBase = rebuildAndCaptureObject(op); + + ExprResult getExpr = buildGet(); + if (getExpr.isInvalid()) return ExprError(); + addResultSemanticExpr(getExpr.take()); + + return complete(syntacticBase); +} + +/// The basic skeleton for building a simple or compound +/// assignment operation. +ExprResult +PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, + BinaryOperatorKind opcode, + Expr *LHS, Expr *RHS) { + assert(BinaryOperator::isAssignmentOp(opcode)); + + Expr *syntacticLHS = rebuildAndCaptureObject(LHS); + OpaqueValueExpr *capturedRHS = capture(RHS); + + Expr *syntactic; + + ExprResult result; + if (opcode == BO_Assign) { + result = capturedRHS; + syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS, + opcode, capturedRHS->getType(), + capturedRHS->getValueKind(), + OK_Ordinary, opcLoc); + } else { + ExprResult opLHS = buildGet(); + if (opLHS.isInvalid()) return ExprError(); + + // Build an ordinary, non-compound operation. + BinaryOperatorKind nonCompound = + BinaryOperator::getOpForCompoundAssignment(opcode); + result = S.BuildBinOp(Sc, opcLoc, nonCompound, + opLHS.take(), capturedRHS); + if (result.isInvalid()) return ExprError(); + + syntactic = + new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode, + result.get()->getType(), + result.get()->getValueKind(), + OK_Ordinary, + opLHS.get()->getType(), + result.get()->getType(), + opcLoc); + } + + // The result of the assignment, if not void, is the value set into + // the l-value. + result = buildSet(result.take(), opcLoc, assignmentsHaveResult()); + if (result.isInvalid()) return ExprError(); + addSemanticExpr(result.take()); + + return complete(syntactic); +} + +/// The basic skeleton for building an increment or decrement +/// operation. +ExprResult +PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, + UnaryOperatorKind opcode, + Expr *op) { + assert(UnaryOperator::isIncrementDecrementOp(opcode)); + + Expr *syntacticOp = rebuildAndCaptureObject(op); + + // Load the value. + ExprResult result = buildGet(); + if (result.isInvalid()) return ExprError(); + + QualType resultType = result.get()->getType(); + + // That's the postfix result. + if (UnaryOperator::isPostfix(opcode) && assignmentsHaveResult()) { + result = capture(result.take()); + setResultToLastSemantic(); + } + + // Add or subtract a literal 1. + llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1); + Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy, + GenericLoc); + + if (UnaryOperator::isIncrementOp(opcode)) { + result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.take(), one); + } else { + result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.take(), 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) && assignmentsHaveResult()); + if (result.isInvalid()) return ExprError(); + addSemanticExpr(result.take()); + + UnaryOperator *syntactic = + new (S.Context) UnaryOperator(syntacticOp, opcode, resultType, + VK_LValue, OK_Ordinary, opcLoc); + return complete(syntactic); +} + + +//===----------------------------------------------------------------------===// +// Objective-C @property and implicit property references +//===----------------------------------------------------------------------===// + +/// Look up a method in the receiver type of an Objective-C property +/// reference. +static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel, + const ObjCPropertyRefExpr *PRE) { + if (PRE->isObjectReceiver()) { + const ObjCObjectPointerType *PT = + PRE->getBase()->getType()->castAs<ObjCObjectPointerType>(); + + // Special case for 'self' in class method implementations. + if (PT->isObjCClassType() && + S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) { + // This cast is safe because isSelfExpr is only true within + // methods. + ObjCMethodDecl *method = + cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor()); + return S.LookupMethodInObjectType(sel, + S.Context.getObjCInterfaceType(method->getClassInterface()), + /*instance*/ false); + } + + return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); + } + + if (PRE->isSuperReceiver()) { + if (const ObjCObjectPointerType *PT = + PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>()) + return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); + + return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false); + } + + assert(PRE->isClassReceiver() && "Invalid expression"); + QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver()); + return S.LookupMethodInObjectType(sel, IT, false); +} + +bool ObjCPropertyOpBuilder::findGetter() { + if (Getter) return true; + + // For implicit properties, just trust the lookup we already did. + if (RefExpr->isImplicitProperty()) { + Getter = RefExpr->getImplicitPropertyGetter(); + return (Getter != 0); + } + + ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); + Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr); + return (Getter != 0); +} + +/// Try to find the most accurate setter declaration for the property +/// reference. +/// +/// \return true if a setter was found, in which case Setter +bool ObjCPropertyOpBuilder::findSetter() { + // For implicit properties, just trust the lookup we already did. + if (RefExpr->isImplicitProperty()) { + if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) { + Setter = setter; + SetterSelector = setter->getSelector(); + return true; + } else { + IdentifierInfo *getterName = + RefExpr->getImplicitPropertyGetter()->getSelector() + .getIdentifierInfoForSlot(0); + SetterSelector = + SelectorTable::constructSetterName(S.PP.getIdentifierTable(), + S.PP.getSelectorTable(), + getterName); + return false; + } + } + + // For explicit properties, this is more involved. + ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); + SetterSelector = prop->getSetterName(); + + // Do a normal method lookup first. + if (ObjCMethodDecl *setter = + LookupMethodInReceiverType(S, SetterSelector, RefExpr)) { + Setter = setter; + return true; + } + + // That can fail in the somewhat crazy situation that we're + // type-checking a message send within the @interface declaration + // that declared the @property. But it's not clear that that's + // valuable to support. + + return false; +} + +/// Capture the base object of an Objective-C property expression. +Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { + assert(InstanceReceiver == 0); + + // If we have a base, capture it in an OVE and rebuild the syntactic + // form to use the OVE as its base. + if (RefExpr->isObjectReceiver()) { + InstanceReceiver = capture(RefExpr->getBase()); + + syntacticBase = + ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase); + } + + if (ObjCPropertyRefExpr * + refE = dyn_cast<ObjCPropertyRefExpr>(syntacticBase->IgnoreParens())) + SyntacticRefExpr = refE; + + return syntacticBase; +} + +/// Load from an Objective-C property reference. +ExprResult ObjCPropertyOpBuilder::buildGet() { + findGetter(); + assert(Getter); + + if (SyntacticRefExpr) + SyntacticRefExpr->setIsMessagingGetter(); + + QualType receiverType; + if (RefExpr->isClassReceiver()) { + receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); + } else if (RefExpr->isSuperReceiver()) { + receiverType = RefExpr->getSuperReceiverType(); + } else { + assert(InstanceReceiver); + receiverType = InstanceReceiver->getType(); + } + + // Build a message-send. + ExprResult msg; + if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) { + assert(InstanceReceiver || RefExpr->isSuperReceiver()); + msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType, + GenericLoc, Getter->getSelector(), + Getter, MultiExprArg()); + } else { + msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(), + GenericLoc, + Getter->getSelector(), Getter, + MultiExprArg()); + } + return msg; +} + +/// Store to an Objective-C property reference. +/// +/// \param bindSetValueAsResult - If true, capture the actual +/// value being set as the value of the property operation. +ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, + bool captureSetValueAsResult) { + bool hasSetter = findSetter(); + assert(hasSetter); (void) hasSetter; + + if (SyntacticRefExpr) + SyntacticRefExpr->setIsMessagingSetter(); + + QualType receiverType; + if (RefExpr->isClassReceiver()) { + receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); + } else if (RefExpr->isSuperReceiver()) { + receiverType = RefExpr->getSuperReceiverType(); + } else { + assert(InstanceReceiver); + receiverType = InstanceReceiver->getType(); + } + + // Use assignment constraints when possible; they give us better + // diagnostics. "When possible" basically means anything except a + // C++ class type. + if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) { + QualType paramType = (*Setter->param_begin())->getType(); + if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) { + ExprResult opResult = op; + Sema::AssignConvertType assignResult + = S.CheckSingleAssignmentConstraints(paramType, opResult); + if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType, + op->getType(), opResult.get(), + Sema::AA_Assigning)) + return ExprError(); + + op = opResult.take(); + assert(op && "successful assignment left argument invalid?"); + } + } + + // Arguments. + Expr *args[] = { op }; + + // Build a message-send. + ExprResult msg; + if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) { + msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType, + GenericLoc, SetterSelector, Setter, + MultiExprArg(args, 1)); + } else { + msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(), + GenericLoc, + SetterSelector, Setter, + MultiExprArg(args, 1)); + } + + if (!msg.isInvalid() && captureSetValueAsResult) { + ObjCMessageExpr *msgExpr = + cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); + Expr *arg = msgExpr->getArg(0); + msgExpr->setArg(0, captureValueAsResult(arg)); + } + + return msg; +} + +/// @property-specific behavior for doing lvalue-to-rvalue conversion. +ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) { + // Explicit properties always have getters, but implicit ones don't. + // Check that before proceeding. + if (RefExpr->isImplicitProperty() && + !RefExpr->getImplicitPropertyGetter()) { + S.Diag(RefExpr->getLocation(), diag::err_getter_not_found) + << RefExpr->getBase()->getType(); + return ExprError(); + } + + ExprResult result = PseudoOpBuilder::buildRValueOperation(op); + if (result.isInvalid()) return ExprError(); + + if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType()) + S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(), + Getter, RefExpr->getLocation()); + + // 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()) { + QualType propType = RefExpr->getExplicitProperty()->getType(); + if (const ObjCObjectPointerType *ptr + = propType->getAs<ObjCObjectPointerType>()) { + if (!ptr->isObjCIdType()) + result = S.ImpCastExprToType(result.get(), propType, CK_BitCast); + } + } + + return result; +} + +/// Try to build this as a call to a getter that returns a reference. +/// +/// \return true if it was possible, whether or not it actually +/// succeeded +bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op, + ExprResult &result) { + if (!S.getLangOpts().CPlusPlus) return false; + + findGetter(); + assert(Getter && "property has no setter and no getter!"); + + // Only do this if the getter returns an l-value reference type. + QualType resultType = Getter->getResultType(); + if (!resultType->isLValueReferenceType()) return false; + + result = buildRValueOperation(op); + return true; +} + +/// @property-specific behavior for doing assignments. +ExprResult +ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc, + SourceLocation opcLoc, + BinaryOperatorKind opcode, + Expr *LHS, Expr *RHS) { + assert(BinaryOperator::isAssignmentOp(opcode)); + + // If there's no setter, we have no choice but to try to assign to + // the result of the getter. + if (!findSetter()) { + ExprResult result; + if (tryBuildGetOfReference(LHS, result)) { + if (result.isInvalid()) return ExprError(); + return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS); + } + + // Otherwise, it's an error. + S.Diag(opcLoc, diag::err_nosetter_property_assignment) + << unsigned(RefExpr->isImplicitProperty()) + << SetterSelector + << LHS->getSourceRange() << RHS->getSourceRange(); + return ExprError(); + } + + // If there is a setter, we definitely want to use it. + + // Verify that we can do a compound assignment. + if (opcode != BO_Assign && !findGetter()) { + S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment) + << LHS->getSourceRange() << RHS->getSourceRange(); + return ExprError(); + } + + ExprResult result = + PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS); + if (result.isInvalid()) return ExprError(); + + // Various warnings about property assignments in ARC. + if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) { + S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS); + S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); + } + + return result; +} + +/// @property-specific behavior for doing increments and decrements. +ExprResult +ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, + UnaryOperatorKind opcode, + Expr *op) { + // If there's no setter, we have no choice but to try to assign to + // the result of the getter. + if (!findSetter()) { + ExprResult result; + if (tryBuildGetOfReference(op, result)) { + if (result.isInvalid()) return ExprError(); + return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take()); + } + + // Otherwise, it's an error. + S.Diag(opcLoc, diag::err_nosetter_property_incdec) + << unsigned(RefExpr->isImplicitProperty()) + << unsigned(UnaryOperator::isDecrementOp(opcode)) + << SetterSelector + << op->getSourceRange(); + return ExprError(); + } + + // If there is a setter, we definitely want to use it. + + // We also need a getter. + if (!findGetter()) { + assert(RefExpr->isImplicitProperty()); + S.Diag(opcLoc, diag::err_nogetter_property_incdec) + << unsigned(UnaryOperator::isDecrementOp(opcode)) + << RefExpr->getImplicitPropertyGetter()->getSelector() // FIXME! + << op->getSourceRange(); + return ExprError(); + } + + return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op); +} + +// ObjCSubscript build stuff. +// + +/// objective-c subscripting-specific behavior for doing lvalue-to-rvalue +/// conversion. +/// FIXME. Remove this routine if it is proven that no additional +/// specifity is needed. +ExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) { + ExprResult result = PseudoOpBuilder::buildRValueOperation(op); + if (result.isInvalid()) return ExprError(); + return result; +} + +/// objective-c subscripting-specific behavior for doing assignments. +ExprResult +ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc, + SourceLocation opcLoc, + BinaryOperatorKind opcode, + Expr *LHS, Expr *RHS) { + assert(BinaryOperator::isAssignmentOp(opcode)); + // There must be a method to do the Index'ed assignment. + if (!findAtIndexSetter()) + return ExprError(); + + // Verify that we can do a compound assignment. + if (opcode != BO_Assign && !findAtIndexGetter()) + return ExprError(); + + ExprResult result = + PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS); + if (result.isInvalid()) return ExprError(); + + // Various warnings about objc Index'ed assignments in ARC. + if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) { + S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS); + S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); + } + + return result; +} + +/// Capture the base object of an Objective-C Index'ed expression. +Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { + assert(InstanceBase == 0); + + // Capture base expression in an OVE and rebuild the syntactic + // form to use the OVE as its base expression. + InstanceBase = capture(RefExpr->getBaseExpr()); + InstanceKey = capture(RefExpr->getKeyExpr()); + + syntacticBase = + ObjCSubscriptRefRebuilder(S, InstanceBase, + InstanceKey).rebuild(syntacticBase); + + return syntacticBase; +} + +/// CheckSubscriptingKind - This routine decide what type +/// of indexing represented by "FromE" is being done. +Sema::ObjCSubscriptKind + Sema::CheckSubscriptingKind(Expr *FromE) { + // If the expression already has integral or enumeration type, we're golden. + QualType T = FromE->getType(); + if (T->isIntegralOrEnumerationType()) + return OS_Array; + + // If we don't have a class type in C++, there's no way we can get an + // expression of integral or enumeration type. + const RecordType *RecordTy = T->getAs<RecordType>(); + if (!RecordTy && T->isObjCObjectPointerType()) + // All other scalar cases are assumed to be dictionary indexing which + // caller handles, with diagnostics if needed. + return OS_Dictionary; + if (!getLangOpts().CPlusPlus || + !RecordTy || RecordTy->isIncompleteType()) { + // No indexing can be done. Issue diagnostics and quit. + const Expr *IndexExpr = FromE->IgnoreParenImpCasts(); + if (isa<StringLiteral>(IndexExpr)) + Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer) + << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@"); + else + Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) + << T; + return OS_Error; + } + + // We must have a complete class type. + if (RequireCompleteType(FromE->getExprLoc(), T, + PDiag(diag::err_objc_index_incomplete_class_type) + << FromE->getSourceRange())) + return OS_Error; + + // Look for a conversion to an integral, enumeration type, or + // objective-C pointer type. + UnresolvedSet<4> ViableConversions; + UnresolvedSet<4> ExplicitConversions; + const UnresolvedSetImpl *Conversions + = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions(); + + int NoIntegrals=0, NoObjCIdPointers=0; + SmallVector<CXXConversionDecl *, 4> ConversionDecls; + + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); + I != E; + ++I) { + if (CXXConversionDecl *Conversion + = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) { + QualType CT = Conversion->getConversionType().getNonReferenceType(); + if (CT->isIntegralOrEnumerationType()) { + ++NoIntegrals; + ConversionDecls.push_back(Conversion); + } + else if (CT->isObjCIdType() ||CT->isBlockPointerType()) { + ++NoObjCIdPointers; + ConversionDecls.push_back(Conversion); + } + } + } + if (NoIntegrals ==1 && NoObjCIdPointers == 0) + return OS_Array; + if (NoIntegrals == 0 && NoObjCIdPointers == 1) + return OS_Dictionary; + if (NoIntegrals == 0 && NoObjCIdPointers == 0) { + // No conversion function was found. Issue diagnostic and return. + Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) + << FromE->getType(); + return OS_Error; + } + Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion) + << FromE->getType(); + for (unsigned int i = 0; i < ConversionDecls.size(); i++) + Diag(ConversionDecls[i]->getLocation(), diag::not_conv_function_declared_at); + + return OS_Error; +} + +bool ObjCSubscriptOpBuilder::findAtIndexGetter() { + if (AtIndexGetter) + return true; + + Expr *BaseExpr = RefExpr->getBaseExpr(); + QualType BaseT = BaseExpr->getType(); + + QualType ResultType; + if (const ObjCObjectPointerType *PTy = + BaseT->getAs<ObjCObjectPointerType>()) { + ResultType = PTy->getPointeeType(); + if (const ObjCObjectType *iQFaceTy = + ResultType->getAsObjCQualifiedInterfaceType()) + ResultType = iQFaceTy->getBaseType(); + } + Sema::ObjCSubscriptKind Res = + S.CheckSubscriptingKind(RefExpr->getKeyExpr()); + if (Res == Sema::OS_Error) + return false; + bool arrayRef = (Res == Sema::OS_Array); + + if (ResultType.isNull()) { + S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type) + << BaseExpr->getType() << arrayRef; + return false; + } + if (!arrayRef) { + // dictionary subscripting. + // - (id)objectForKeyedSubscript:(id)key; + IdentifierInfo *KeyIdents[] = { + &S.Context.Idents.get("objectForKeyedSubscript") + }; + AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); + } + else { + // - (id)objectAtIndexedSubscript:(size_t)index; + IdentifierInfo *KeyIdents[] = { + &S.Context.Idents.get("objectAtIndexedSubscript") + }; + + AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); + } + + AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType, + true /*instance*/); + bool receiverIdType = (BaseT->isObjCIdType() || + BaseT->isObjCQualifiedIdType()); + + if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) { + AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(), + SourceLocation(), AtIndexGetterSelector, + S.Context.getObjCIdType() /*ReturnType*/, + 0 /*TypeSourceInfo */, + S.Context.getTranslationUnitDecl(), + true /*Instance*/, false/*isVariadic*/, + /*isSynthesized=*/false, + /*isImplicitlyDeclared=*/true, /*isDefined=*/false, + ObjCMethodDecl::Required, + false); + ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter, + SourceLocation(), SourceLocation(), + arrayRef ? &S.Context.Idents.get("index") + : &S.Context.Idents.get("key"), + arrayRef ? S.Context.UnsignedLongTy + : S.Context.getObjCIdType(), + /*TInfo=*/0, + SC_None, + SC_None, + 0); + AtIndexGetter->setMethodParams(S.Context, Argument, + ArrayRef<SourceLocation>()); + } + + if (!AtIndexGetter) { + if (!receiverIdType) { + S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found) + << BaseExpr->getType() << 0 << arrayRef; + return false; + } + AtIndexGetter = + S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector, + RefExpr->getSourceRange(), + true, false); + } + + if (AtIndexGetter) { + QualType T = AtIndexGetter->param_begin()[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(), + diag::note_parameter_type) << T; + return false; + } + QualType R = AtIndexGetter->getResultType(); + if (!R->isObjCObjectPointerType()) { + S.Diag(RefExpr->getKeyExpr()->getExprLoc(), + diag::err_objc_indexing_method_result_type) << R << arrayRef; + S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) << + AtIndexGetter->getDeclName(); + } + } + return true; +} + +bool ObjCSubscriptOpBuilder::findAtIndexSetter() { + if (AtIndexSetter) + return true; + + Expr *BaseExpr = RefExpr->getBaseExpr(); + QualType BaseT = BaseExpr->getType(); + + QualType ResultType; + if (const ObjCObjectPointerType *PTy = + BaseT->getAs<ObjCObjectPointerType>()) { + ResultType = PTy->getPointeeType(); + if (const ObjCObjectType *iQFaceTy = + ResultType->getAsObjCQualifiedInterfaceType()) + ResultType = iQFaceTy->getBaseType(); + } + + Sema::ObjCSubscriptKind Res = + S.CheckSubscriptingKind(RefExpr->getKeyExpr()); + if (Res == Sema::OS_Error) + return false; + bool arrayRef = (Res == Sema::OS_Array); + + if (ResultType.isNull()) { + S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type) + << BaseExpr->getType() << arrayRef; + return false; + } + + if (!arrayRef) { + // dictionary subscripting. + // - (void)setObject:(id)object forKeyedSubscript:(id)key; + IdentifierInfo *KeyIdents[] = { + &S.Context.Idents.get("setObject"), + &S.Context.Idents.get("forKeyedSubscript") + }; + AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents); + } + else { + // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index; + IdentifierInfo *KeyIdents[] = { + &S.Context.Idents.get("setObject"), + &S.Context.Idents.get("atIndexedSubscript") + }; + AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents); + } + AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType, + true /*instance*/); + + bool receiverIdType = (BaseT->isObjCIdType() || + BaseT->isObjCQualifiedIdType()); + + if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) { + TypeSourceInfo *ResultTInfo = 0; + QualType ReturnType = S.Context.VoidTy; + AtIndexSetter = ObjCMethodDecl::Create(S.Context, SourceLocation(), + SourceLocation(), AtIndexSetterSelector, + ReturnType, + ResultTInfo, + S.Context.getTranslationUnitDecl(), + true /*Instance*/, false/*isVariadic*/, + /*isSynthesized=*/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, + SC_None, + SC_None, + 0); + Params.push_back(object); + ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter, + SourceLocation(), SourceLocation(), + arrayRef ? &S.Context.Idents.get("index") + : &S.Context.Idents.get("key"), + arrayRef ? S.Context.UnsignedLongTy + : S.Context.getObjCIdType(), + /*TInfo=*/0, + SC_None, + SC_None, + 0); + Params.push_back(key); + AtIndexSetter->setMethodParams(S.Context, Params, ArrayRef<SourceLocation>()); + } + + if (!AtIndexSetter) { + if (!receiverIdType) { + S.Diag(BaseExpr->getExprLoc(), + diag::err_objc_subscript_method_not_found) + << BaseExpr->getType() << 1 << arrayRef; + return false; + } + AtIndexSetter = + S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector, + RefExpr->getSourceRange(), + true, false); + } + + bool err = false; + if (AtIndexSetter && arrayRef) { + QualType T = AtIndexSetter->param_begin()[1]->getType(); + if (!T->isIntegralOrEnumerationType()) { + S.Diag(RefExpr->getKeyExpr()->getExprLoc(), + diag::err_objc_subscript_index_type) << T; + S.Diag(AtIndexSetter->param_begin()[1]->getLocation(), + diag::note_parameter_type) << T; + err = true; + } + T = AtIndexSetter->param_begin()[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(), + 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(); + if (!T->isObjCObjectPointerType()) { + if (i == 1) + S.Diag(RefExpr->getKeyExpr()->getExprLoc(), + diag::err_objc_subscript_key_type) << T; + else + S.Diag(RefExpr->getBaseExpr()->getExprLoc(), + diag::err_objc_subscript_dic_object_type) << T; + S.Diag(AtIndexSetter->param_begin()[i]->getLocation(), + diag::note_parameter_type) << T; + err = true; + } + } + + return !err; +} + +// Get the object at "Index" position in the container. +// [BaseExpr objectAtIndexedSubscript : IndexExpr]; +ExprResult ObjCSubscriptOpBuilder::buildGet() { + if (!findAtIndexGetter()) + return ExprError(); + + QualType receiverType = InstanceBase->getType(); + + // Build a message-send. + ExprResult msg; + Expr *Index = InstanceKey; + + // Arguments. + Expr *args[] = { Index }; + assert(InstanceBase); + msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType, + GenericLoc, + AtIndexGetterSelector, AtIndexGetter, + MultiExprArg(args, 1)); + return msg; +} + +/// Store into the container the "op" object at "Index"'ed location +/// by building this messaging expression: +/// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index; +/// \param bindSetValueAsResult - If true, capture the actual +/// value being set as the value of the property operation. +ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, + bool captureSetValueAsResult) { + if (!findAtIndexSetter()) + return ExprError(); + + QualType receiverType = InstanceBase->getType(); + Expr *Index = InstanceKey; + + // Arguments. + Expr *args[] = { op, Index }; + + // Build a message-send. + ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType, + GenericLoc, + AtIndexSetterSelector, + AtIndexSetter, + MultiExprArg(args, 2)); + + if (!msg.isInvalid() && captureSetValueAsResult) { + ObjCMessageExpr *msgExpr = + cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); + Expr *arg = msgExpr->getArg(0); + msgExpr->setArg(0, captureValueAsResult(arg)); + } + + return msg; +} + +//===----------------------------------------------------------------------===// +// General Sema routines. +//===----------------------------------------------------------------------===// + +ExprResult Sema::checkPseudoObjectRValue(Expr *E) { + Expr *opaqueRef = E->IgnoreParens(); + if (ObjCPropertyRefExpr *refExpr + = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { + ObjCPropertyOpBuilder builder(*this, refExpr); + return builder.buildRValueOperation(E); + } + else if (ObjCSubscriptRefExpr *refExpr + = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { + ObjCSubscriptOpBuilder builder(*this, refExpr); + return builder.buildRValueOperation(E); + } else { + llvm_unreachable("unknown pseudo-object kind!"); + } +} + +/// Check an increment or decrement of a pseudo-object expression. +ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc, + UnaryOperatorKind opcode, Expr *op) { + // Do nothing if the operand is dependent. + if (op->isTypeDependent()) + return new (Context) UnaryOperator(op, opcode, Context.DependentTy, + VK_RValue, OK_Ordinary, opcLoc); + + assert(UnaryOperator::isIncrementDecrementOp(opcode)); + Expr *opaqueRef = op->IgnoreParens(); + if (ObjCPropertyRefExpr *refExpr + = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { + ObjCPropertyOpBuilder builder(*this, refExpr); + return builder.buildIncDecOperation(Sc, opcLoc, opcode, op); + } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) { + Diag(opcLoc, diag::err_illegal_container_subscripting_op); + return ExprError(); + } else { + llvm_unreachable("unknown pseudo-object kind!"); + } +} + +ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, + BinaryOperatorKind opcode, + Expr *LHS, Expr *RHS) { + // Do nothing if either argument is dependent. + if (LHS->isTypeDependent() || RHS->isTypeDependent()) + return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy, + VK_RValue, OK_Ordinary, opcLoc); + + // Filter out non-overload placeholder types in the RHS. + if (RHS->getType()->isNonOverloadPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(RHS); + if (result.isInvalid()) return ExprError(); + RHS = result.take(); + } + + Expr *opaqueRef = LHS->IgnoreParens(); + if (ObjCPropertyRefExpr *refExpr + = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { + ObjCPropertyOpBuilder builder(*this, refExpr); + return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); + } else if (ObjCSubscriptRefExpr *refExpr + = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { + ObjCSubscriptOpBuilder builder(*this, refExpr); + return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); + } else { + llvm_unreachable("unknown pseudo-object kind!"); + } +} + +/// Given a pseudo-object reference, rebuild it without the opaque +/// values. Basically, undo the behavior of rebuildAndCaptureObject. +/// This should never operate in-place. +static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) { + Expr *opaqueRef = E->IgnoreParens(); + if (ObjCPropertyRefExpr *refExpr + = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { + OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase()); + return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E); + } else if (ObjCSubscriptRefExpr *refExpr + = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { + OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr()); + OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr()); + return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(), + keyOVE->getSourceExpr()).rebuild(E); + } else { + llvm_unreachable("unknown pseudo-object kind!"); + } +} + +/// Given a pseudo-object expression, recreate what it looks like +/// syntactically without the attendant OpaqueValueExprs. +/// +/// This is a hack which should be removed when TreeTransform is +/// capable of rebuilding a tree without stripping implicit +/// operations. +Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) { + Expr *syntax = E->getSyntacticForm(); + if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) { + Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr()); + return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(), + uop->getValueKind(), uop->getObjectKind(), + uop->getOperatorLoc()); + } else if (CompoundAssignOperator *cop + = dyn_cast<CompoundAssignOperator>(syntax)) { + Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS()); + Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr(); + return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(), + cop->getType(), + cop->getValueKind(), + cop->getObjectKind(), + cop->getComputationLHSType(), + cop->getComputationResultType(), + cop->getOperatorLoc()); + } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) { + Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS()); + Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr(); + return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(), + bop->getType(), bop->getValueKind(), + bop->getObjectKind(), + bop->getOperatorLoc()); + } else { + assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject)); + return stripOpaqueValuesFromPseudoObjectRef(*this, syntax); + } +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp index 5351896..97c8eb0 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp @@ -16,8 +16,8 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" -#include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/CharUnits.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" @@ -78,7 +78,7 @@ void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) { // In ARC, we don't need to retain the iteration variable of a fast // enumeration loop. Rather than actually trying to catch that // during declaration processing, we remove the consequences here. - if (getLangOptions().ObjCAutoRefCount) { + if (getLangOpts().ObjCAutoRefCount) { QualType type = var->getType(); // Only do this if we inferred the lifetime. Inferred lifetime @@ -152,7 +152,8 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { SourceLocation Loc; SourceRange R1, R2; - if (!E->isUnusedResultAWarning(Loc, R1, R2, Context)) + if (SourceMgr.isInSystemMacro(E->getExprLoc()) || + !E->isUnusedResultAWarning(Loc, R1, R2, Context)) return; // Okay, we have an unused result. Depending on what the base expression is, @@ -189,7 +190,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { } } } else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) { - if (getLangOptions().ObjCAutoRefCount && ME->isDelegateInitCall()) { + if (getLangOpts().ObjCAutoRefCount && ME->isDelegateInitCall()) { Diag(Loc, diag::err_arc_unused_init_message) << R1; return; } @@ -198,8 +199,12 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { Diag(Loc, diag::warn_unused_result) << R1 << R2; return; } - } else if (isa<ObjCPropertyRefExpr>(E)) { - DiagID = diag::warn_unused_property_expr; + } else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) { + const Expr *Source = POE->getSyntacticForm(); + if (isa<ObjCSubscriptRefExpr>(Source)) + DiagID = diag::warn_unused_container_subscript_expr; + else + DiagID = diag::warn_unused_property_expr; } else if (const CXXFunctionalCastExpr *FC = dyn_cast<CXXFunctionalCastExpr>(E)) { if (isa<CXXConstructExpr>(FC->getSubExpr()) || @@ -224,6 +229,18 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { DiagRuntimeBehavior(Loc, 0, PDiag(DiagID) << R1 << R2); } +void Sema::ActOnStartOfCompoundStmt() { + PushCompoundScope(); +} + +void Sema::ActOnFinishOfCompoundStmt() { + PopCompoundScope(); +} + +sema::CompoundScopeInfo &Sema::getCurCompoundScope() const { + return getCurFunction()->CompoundScopes.back(); +} + StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, MultiStmtArg elts, bool isStmtExpr) { @@ -231,7 +248,7 @@ Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, Stmt **Elts = reinterpret_cast<Stmt**>(elts.release()); // If we're in C89 mode, check that we don't have any decls after stmts. If // so, emit an extension diagnostic. - if (!getLangOptions().C99 && !getLangOptions().CPlusPlus) { + if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) { // Note that __extension__ can be around a decl. unsigned i = 0; // Skip over all declarations. @@ -256,6 +273,15 @@ Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, DiagnoseUnusedExprResult(Elts[i]); } + // Check for suspicious empty body (null statement) in `for' and `while' + // statements. Don't do anything for template instantiations, this just adds + // noise. + if (NumElts != 0 && !CurrentInstantiationScope && + getCurCompoundScope().HasEmptyLoopBodies) { + for (unsigned i = 0; i != NumElts - 1; ++i) + DiagnoseEmptyLoopBody(Elts[i], Elts[i + 1]); + } + return Owned(new (Context) CompoundStmt(Context, Elts, NumElts, L, R)); } @@ -265,22 +291,26 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal, SourceLocation ColonLoc) { assert((LHSVal != 0) && "missing expression in case statement"); - // C99 6.8.4.2p3: The expression shall be an integer constant. - // However, GCC allows any evaluatable integer expression. - if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent() && - VerifyIntegerConstantExpression(LHSVal)) + if (getCurFunction()->SwitchStack.empty()) { + Diag(CaseLoc, diag::err_case_not_in_switch); return StmtError(); + } - // GCC extension: The expression shall be an integer constant. + if (!getLangOpts().CPlusPlus0x) { + // 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(); + if (!LHSVal) + return StmtError(); + } - if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent() && - VerifyIntegerConstantExpression(RHSVal)) { - RHSVal = 0; // Recover by just forgetting about it. - } + // GCC extension: The expression shall be an integer constant. - if (getCurFunction()->SwitchStack.empty()) { - Diag(CaseLoc, diag::err_case_not_in_switch); - return StmtError(); + if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent()) { + RHSVal = VerifyIntegerConstantExpression(RHSVal).take(); + // Recover from an error by just forgetting about it. + } } CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc, @@ -350,21 +380,9 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, DiagnoseUnusedExprResult(thenStmt); - // Warn if the if block has a null body without an else value. - // this helps prevent bugs due to typos, such as - // if (condition); - // do_stuff(); - // if (!elseStmt) { - if (NullStmt* stmt = dyn_cast<NullStmt>(thenStmt)) - // But do not warn if the body is a macro that expands to nothing, e.g: - // - // #define CALL(x) - // if (condition) - // CALL(0); - // - if (!stmt->hasLeadingEmptyMacro()) - Diag(stmt->getSemiLoc(), diag::warn_empty_if_body); + DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt, + diag::warn_empty_if_body); } DiagnoseUnusedExprResult(elseStmt); @@ -501,7 +519,8 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond, PDiag(diag::note_switch_conversion), PDiag(diag::err_switch_multiple_conversions), PDiag(diag::note_switch_conversion), - PDiag(0)); + PDiag(0), + /*AllowScopedEnumerations*/ true); if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.take(); @@ -617,8 +636,6 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, } else { CaseStmt *CS = cast<CaseStmt>(SC); - // We already verified that the expression has a i-c-e value (C99 - // 6.8.4.2p3) - get that value now. Expr *Lo = CS->getLHS(); if (Lo->isTypeDependent() || Lo->isValueDependent()) { @@ -626,16 +643,39 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, break; } - llvm::APSInt LoVal = Lo->EvaluateKnownConstInt(Context); + llvm::APSInt LoVal; + + if (getLangOpts().CPlusPlus0x) { + // C++11 [stmt.switch]p2: the constant-expression shall be a converted + // constant expression of the promoted type of the switch condition. + ExprResult ConvLo = + CheckConvertedConstantExpression(Lo, CondType, LoVal, CCEK_CaseValue); + if (ConvLo.isInvalid()) { + CaseListIsErroneous = true; + continue; + } + Lo = ConvLo.take(); + } else { + // We already verified that the expression has a i-c-e value (C99 + // 6.8.4.2p3) - get that value now. + LoVal = Lo->EvaluateKnownConstInt(Context); + + // If the LHS is not the same type as the condition, insert an implicit + // cast. + Lo = DefaultLvalueConversion(Lo).take(); + Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).take(); + } - // Convert the value to the same width/sign as the condition. + // Convert the value to the same width/sign as the condition had prior to + // integral promotions. + // + // FIXME: This causes us to reject valid code: + // switch ((char)c) { case 256: case 0: return 0; } + // Here we claim there is a duplicated condition value, but there is not. ConvertIntegerToTypeWarnOnOverflow(LoVal, CondWidth, CondIsSigned, Lo->getLocStart(), diag::warn_case_value_overflow); - // If the LHS is not the same type as the condition, insert an implicit - // cast. - Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).take(); CS->setLHS(Lo); // If this is a case range, remember it in CaseRanges, otherwise CaseVals. @@ -656,19 +696,15 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // condition is constant. llvm::APSInt ConstantCondValue; bool HasConstantCond = false; - bool ShouldCheckConstantCond = false; if (!HasDependentValue && !TheDefaultStmt) { - Expr::EvalResult Result; - HasConstantCond = CondExprBeforePromotion->Evaluate(Result, Context); - if (HasConstantCond) { - assert(Result.Val.isInt() && "switch condition evaluated to non-int"); - ConstantCondValue = Result.Val.getInt(); - ShouldCheckConstantCond = true; - - assert(ConstantCondValue.getBitWidth() == CondWidth && - ConstantCondValue.isSigned() == CondIsSigned); - } + HasConstantCond + = CondExprBeforePromotion->EvaluateAsInt(ConstantCondValue, Context, + Expr::SE_AllowSideEffects); + assert(!HasConstantCond || + (ConstantCondValue.getBitWidth() == CondWidth && + ConstantCondValue.isSigned() == CondIsSigned)); } + bool ShouldCheckConstantCond = HasConstantCond; // Sort all the scalar case values so we can easily detect duplicates. std::stable_sort(CaseVals.begin(), CaseVals.end(), CmpCaseVals); @@ -705,16 +741,33 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, llvm::APSInt &LoVal = CaseRanges[i].first; CaseStmt *CR = CaseRanges[i].second; Expr *Hi = CR->getRHS(); - llvm::APSInt HiVal = Hi->EvaluateKnownConstInt(Context); + llvm::APSInt HiVal; + + if (getLangOpts().CPlusPlus0x) { + // C++11 [stmt.switch]p2: the constant-expression shall be a converted + // constant expression of the promoted type of the switch condition. + ExprResult ConvHi = + CheckConvertedConstantExpression(Hi, CondType, HiVal, + CCEK_CaseValue); + if (ConvHi.isInvalid()) { + CaseListIsErroneous = true; + continue; + } + Hi = ConvHi.take(); + } 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(); + } // Convert the value to the same width/sign as the condition. ConvertIntegerToTypeWarnOnOverflow(HiVal, CondWidth, CondIsSigned, Hi->getLocStart(), diag::warn_case_value_overflow); - // If the LHS is not the same type as the condition, insert an implicit - // cast. - Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).take(); CR->setRHS(Hi); // If the low value is bigger than the high value, the case is empty. @@ -821,39 +874,35 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); // See which case values aren't in enum. - // TODO: we might want to check whether case values are out of the - // enum even if we don't want to check whether all cases are handled. - if (!TheDefaultStmt) { - EnumValsTy::const_iterator EI = EnumVals.begin(); - for (CaseValsTy::const_iterator CI = CaseVals.begin(); - 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) - << ED->getDeclName(); + EnumValsTy::const_iterator EI = EnumVals.begin(); + for (CaseValsTy::const_iterator CI = CaseVals.begin(); + 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; + } + // See which of case ranges aren't in enum + EI = EnumVals.begin(); + for (CaseRangesTy::const_iterator RI = CaseRanges.begin(); + RI != CaseRanges.end() && EI != EIend; RI++) { + while (EI != EIend && EI->first < RI->first) + EI++; + + if (EI == EIend || EI->first != RI->first) { + Diag(RI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum) + << CondTypeBeforePromotion; } - // See which of case ranges aren't in enum - EI = EnumVals.begin(); - for (CaseRangesTy::const_iterator RI = CaseRanges.begin(); - RI != CaseRanges.end() && EI != EIend; RI++) { - while (EI != EIend && EI->first < RI->first) - EI++; - - if (EI == EIend || EI->first != RI->first) { - Diag(RI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum) - << ED->getDeclName(); - } - llvm::APSInt Hi = - RI->second->getRHS()->EvaluateKnownConstInt(Context); - 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) - << ED->getDeclName(); - } + llvm::APSInt Hi = + RI->second->getRHS()->EvaluateKnownConstInt(Context); + 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; } // Check which enum vals aren't in switch @@ -863,7 +912,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, SmallVector<DeclarationName,8> UnhandledNames; - for (EnumValsTy::const_iterator EI = EnumVals.begin(); EI != EIend; EI++){ + for (EI = EnumVals.begin(); EI != EIend; EI++){ // Drop unneeded case values llvm::APSInt CIVal; while (CI != CaseVals.end() && CI->first < EI->first) @@ -883,28 +932,34 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, if (RI == CaseRanges.end() || EI->first < RI->first) { hasCasesNotInSwitch = true; - if (!TheDefaultStmt) - UnhandledNames.push_back(EI->second->getDeclName()); + UnhandledNames.push_back(EI->second->getDeclName()); } } + if (TheDefaultStmt && UnhandledNames.empty()) + Diag(TheDefaultStmt->getDefaultLoc(), diag::warn_unreachable_default); + // Produce a nice diagnostic if multiple values aren't handled. switch (UnhandledNames.size()) { case 0: break; case 1: - Diag(CondExpr->getExprLoc(), diag::warn_missing_case1) + Diag(CondExpr->getExprLoc(), TheDefaultStmt + ? diag::warn_def_missing_case1 : diag::warn_missing_case1) << UnhandledNames[0]; break; case 2: - Diag(CondExpr->getExprLoc(), diag::warn_missing_case2) + Diag(CondExpr->getExprLoc(), TheDefaultStmt + ? diag::warn_def_missing_case2 : diag::warn_missing_case2) << UnhandledNames[0] << UnhandledNames[1]; break; case 3: - Diag(CondExpr->getExprLoc(), diag::warn_missing_case3) + Diag(CondExpr->getExprLoc(), TheDefaultStmt + ? diag::warn_def_missing_case3 : diag::warn_missing_case3) << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2]; break; default: - Diag(CondExpr->getExprLoc(), diag::warn_missing_cases) + Diag(CondExpr->getExprLoc(), TheDefaultStmt + ? diag::warn_def_missing_cases : diag::warn_missing_cases) << (unsigned)UnhandledNames.size() << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2]; break; @@ -915,6 +970,9 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, } } + 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) @@ -941,6 +999,9 @@ Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond, DiagnoseUnusedExprResult(Body); + if (isa<NullStmt>(Body)) + getCurCompoundScope().setHasEmptyLoopBodies(); + return Owned(new (Context) WhileStmt(Context, ConditionVar, ConditionExpr, Body, WhileLoc)); } @@ -972,7 +1033,7 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, Stmt *First, FullExprArg second, Decl *secondVar, FullExprArg third, SourceLocation RParenLoc, Stmt *Body) { - if (!getLangOptions().CPlusPlus) { + if (!getLangOpts().CPlusPlus) { if (DeclStmt *DS = dyn_cast_or_null<DeclStmt>(First)) { // C99 6.8.5p3: The declaration part of a 'for' statement shall only // declare identifiers for objects having storage class 'auto' or @@ -1004,6 +1065,9 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, DiagnoseUnusedExprResult(Third); DiagnoseUnusedExprResult(Body); + if (isa<NullStmt>(Body)) + getCurCompoundScope().setHasEmptyLoopBodies(); + return Owned(new (Context) ForStmt(Context, First, SecondResult.take(), ConditionVar, Third, Body, ForLoc, LParenLoc, @@ -1015,10 +1079,18 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, /// x can be an arbitrary l-value expression. Bind it up as a /// full-expression. StmtResult Sema::ActOnForEachLValueExpr(Expr *E) { + // Reduce placeholder expressions here. Note that this rejects the + // use of pseudo-object l-values in this position. + ExprResult result = CheckPlaceholderExpr(E); + if (result.isInvalid()) return StmtError(); + E = result.take(); + CheckImplicitConversions(E); - ExprResult Result = MaybeCreateExprWithCleanups(E); - if (Result.isInvalid()) return StmtError(); - return Owned(static_cast<Stmt*>(Result.get())); + + result = MaybeCreateExprWithCleanups(E); + if (result.isInvalid()) return StmtError(); + + return Owned(static_cast<Stmt*>(result.take())); } ExprResult @@ -1048,13 +1120,13 @@ Sema::ActOnObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) { ObjCInterfaceDecl *iface = objectType->getInterface(); // If we have a forward-declared type, we can't do this check. - if (iface && iface->isForwardDecl()) { - // This is ill-formed under ARC. - if (getLangOptions().ObjCAutoRefCount) { - Diag(forLoc, diag::err_arc_collection_forward) - << pointerType->getPointeeType() << collection->getSourceRange(); - } - + // Under ARC, it is an error not to have a forward-declared class. + if (iface && + RequireCompleteType(forLoc, QualType(objectType, 0), + getLangOpts().ObjCAutoRefCount + ? PDiag(diag::err_arc_collection_forward) + << collection->getSourceRange() + : PDiag(0))) { // Otherwise, if we have any useful type information, check that // the type declares the appropriate method. } else if (iface || !objectType->qual_empty()) { @@ -1157,8 +1229,9 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, // Deduce the type for the iterator variable now rather than leaving it to // AddInitializerToDecl, so we can produce a more suitable diagnostic. TypeSourceInfo *InitTSI = 0; - if (Init->getType()->isVoidType() || - !SemaRef.DeduceAutoType(Decl->getTypeSourceInfo(), Init, InitTSI)) + if ((!isa<InitListExpr>(Init) && Init->getType()->isVoidType()) || + SemaRef.DeduceAutoType(Decl->getTypeSourceInfo(), Init, InitTSI) == + Sema::DAR_Failed) SemaRef.Diag(Loc, diag) << Init->getType(); if (!InitTSI) { Decl->setInvalidDecl(); @@ -1170,7 +1243,7 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, // In ARC, infer lifetime. // FIXME: ARC may want to turn this into 'const __unsafe_unretained' if // we're doing the equivalent of fast iteration. - if (SemaRef.getLangOptions().ObjCAutoRefCount && + if (SemaRef.getLangOpts().ObjCAutoRefCount && SemaRef.inferObjCARCLifetime(Decl)) Decl->setInvalidDecl(); @@ -1223,7 +1296,9 @@ static ExprResult BuildForRangeBeginEndCall(Sema &SemaRef, Scope *S, ExprResult MemberRef = SemaRef.BuildMemberReferenceExpr(Range, Range->getType(), Loc, /*IsPtr=*/false, CXXScopeSpec(), - /*Qualifier=*/0, MemberLookup, + /*TemplateKWLoc=*/SourceLocation(), + /*FirstQualifierInScope=*/0, + MemberLookup, /*TemplateArgs=*/0); if (MemberRef.isInvalid()) return ExprError(); @@ -1242,7 +1317,7 @@ static ExprResult BuildForRangeBeginEndCall(Sema &SemaRef, Scope *S, FoundNames.begin(), FoundNames.end(), /*LookInStdNamespace=*/true); CallExpr = SemaRef.BuildOverloadedCallExpr(S, Fn, Fn, Loc, &Range, 1, Loc, - 0); + 0, /*AllowTypoCorrection=*/false); if (CallExpr.isInvalid()) { SemaRef.Diag(Range->getLocStart(), diag::note_for_range_type) << Range->getType(); @@ -1542,7 +1617,12 @@ StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) { if (!S || !B) return StmtError(); - cast<CXXForRangeStmt>(S)->setBody(B); + CXXForRangeStmt *ForStmt = cast<CXXForRangeStmt>(S); + ForStmt->setBody(B); + + DiagnoseEmptyStmtBody(ForStmt->getRParenLoc(), B, + diag::warn_empty_range_based_for_body); + return S; } @@ -1569,6 +1649,7 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, E = ExprRes.take(); if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing)) return StmtError(); + E = MaybeCreateExprWithCleanups(E); } getCurFunction()->setHasIndirectGoto(); @@ -1639,14 +1720,29 @@ const VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType, if (!VD) return 0; - if (VD->hasLocalStorage() && !VD->isExceptionVariable() && - !VD->getType()->isReferenceType() && !VD->hasAttr<BlocksAttr>() && - !VD->getType().isVolatileQualified() && - ((VD->getKind() == Decl::Var) || - (AllowFunctionParameter && VD->getKind() == Decl::ParmVar))) - return VD; + // ...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; + + // ...automatic... + if (!VD->hasLocalStorage()) return 0; - return 0; + // ...non-volatile... + if (VD->getType().isVolatileQualified()) return 0; + if (VD->getType()->isReferenceType()) return 0; + + // __block variables can't be allocated in a way that permits NRVO. + if (VD->hasAttr<BlocksAttr>()) return 0; + + // Variables with higher required alignment than their type's ABI + // alignment cannot use NRVO. + if (VD->hasAttr<AlignedAttr>() && + Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VD->getType())) + return 0; + + return VD; } /// \brief Perform the initialization of a potentially-movable value, which @@ -1726,42 +1822,64 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, return Res; } -/// ActOnBlockReturnStmt - Utility routine to figure out block's return type. +/// ActOnCapScopeReturnStmt - Utility routine to type-check return statements +/// for capturing scopes. /// StmtResult -Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { - // If this is the first return we've seen in the block, infer the type of - // the block from it. - BlockScopeInfo *CurBlock = getCurBlock(); - if (CurBlock->ReturnType.isNull()) { - if (RetValExp) { - // Don't call UsualUnaryConversions(), since we don't want to do - // integer promotions here. +Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { + // If this is the first return we've seen, infer the return type. + // [expr.prim.lambda]p4 in C++11; block literals follow a superset of those + // rules which allows multiple return statements. + CapturingScopeInfo *CurCap = cast<CapturingScopeInfo>(getCurFunction()); + if (CurCap->HasImplicitReturnType) { + QualType ReturnT; + if (RetValExp && !isa<InitListExpr>(RetValExp)) { ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp); if (Result.isInvalid()) return StmtError(); RetValExp = Result.take(); - if (!RetValExp->isTypeDependent()) { - CurBlock->ReturnType = RetValExp->getType(); - if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) { - // We have to remove a 'const' added to copied-in variable which was - // part of the implementation spec. and not the actual qualifier for - // the variable. - if (CDRE->isConstQualAdded()) - CurBlock->ReturnType.removeLocalConst(); // FIXME: local??? - } - } else - CurBlock->ReturnType = Context.DependentTy; - } else - CurBlock->ReturnType = Context.VoidTy; + if (!RetValExp->isTypeDependent()) + ReturnT = RetValExp->getType(); + else + ReturnT = Context.DependentTy; + } else { + if (RetValExp) { + // C++11 [expr.lambda.prim]p4 bans inferring the result from an + // initializer list, because it is not an expression (even + // though we represent it as one). We still deduce 'void'. + Diag(ReturnLoc, diag::err_lambda_return_init_list) + << RetValExp->getSourceRange(); + } + + ReturnT = Context.VoidTy; + } + // We require the return types to strictly match here. + if (!CurCap->ReturnType.isNull() && + !CurCap->ReturnType->isDependentType() && + !ReturnT->isDependentType() && + !Context.hasSameType(ReturnT, CurCap->ReturnType)) { + Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible) + << ReturnT << CurCap->ReturnType + << (getCurLambda() != 0); + return StmtError(); + } + CurCap->ReturnType = ReturnT; } - QualType FnRetType = CurBlock->ReturnType; + QualType FnRetType = CurCap->ReturnType; + assert(!FnRetType.isNull()); - if (CurBlock->FunctionType->getAs<FunctionType>()->getNoReturnAttr()) { - Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr) - << getCurFunctionOrMethodDecl()->getDeclName(); - return StmtError(); + if (BlockScopeInfo *CurBlock = dyn_cast<BlockScopeInfo>(CurCap)) { + if (CurBlock->FunctionType->getAs<FunctionType>()->getNoReturnAttr()) { + Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr); + return StmtError(); + } + } else { + LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CurCap); + if (LSI->CallOperator->getType()->getAs<FunctionType>()->getNoReturnAttr()){ + Diag(ReturnLoc, diag::err_noreturn_lambda_has_return_expr); + return StmtError(); + } } // Otherwise, verify that this result type matches the previous one. We are @@ -1772,12 +1890,17 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // Delay processing for now. TODO: there are lots of dependent // types we can conclusively prove aren't void. } else if (FnRetType->isVoidType()) { - if (RetValExp && - !(getLangOptions().CPlusPlus && + if (RetValExp && !isa<InitListExpr>(RetValExp) && + !(getLangOpts().CPlusPlus && (RetValExp->isTypeDependent() || RetValExp->getType()->isVoidType()))) { - Diag(ReturnLoc, diag::err_return_block_has_expr); - RetValExp = 0; + if (!getLangOpts().CPlusPlus && + RetValExp->getType()->isVoidType()) + Diag(ReturnLoc, diag::ext_return_has_void_expr) << "literal" << 2; + else { + Diag(ReturnLoc, diag::err_return_block_has_expr); + RetValExp = 0; + } } } else if (!RetValExp) { return StmtError(Diag(ReturnLoc, diag::err_block_return_missing_expr)); @@ -1793,7 +1916,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false); InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc, FnRetType, - NRVOCandidate != 0); + NRVOCandidate != 0); ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate, FnRetType, RetValExp); if (Res.isInvalid()) { @@ -1813,7 +1936,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // If we need to check for the named return value optimization, save the // return statement in our scope for later processing. - if (getLangOptions().CPlusPlus && FnRetType->isRecordType() && + if (getLangOpts().CPlusPlus && FnRetType->isRecordType() && !CurContext->isDependentContext()) FunctionScopes.back()->Returns.push_back(Result); @@ -1826,28 +1949,25 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp)) return StmtError(); - if (getCurBlock()) - return ActOnBlockReturnStmt(ReturnLoc, RetValExp); + if (isa<CapturingScopeInfo>(getCurFunction())) + return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp); QualType FnRetType; - QualType DeclaredRetType; + QualType RelatedRetType; if (const FunctionDecl *FD = getCurFunctionDecl()) { FnRetType = FD->getResultType(); - DeclaredRetType = FnRetType; if (FD->hasAttr<NoReturnAttr>() || FD->getType()->getAs<FunctionType>()->getNoReturnAttr()) Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) - << getCurFunctionOrMethodDecl()->getDeclName(); + << FD->getDeclName(); } else if (ObjCMethodDecl *MD = getCurMethodDecl()) { - DeclaredRetType = MD->getResultType(); + FnRetType = MD->getResultType(); 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 // method body is a pointer to the type of the class being implemented. - FnRetType = Context.getObjCInterfaceType(MD->getClassInterface()); - FnRetType = Context.getObjCObjectPointerType(FnRetType); - } else { - FnRetType = DeclaredRetType; + RelatedRetType = Context.getObjCInterfaceType(MD->getClassInterface()); + RelatedRetType = Context.getObjCObjectPointerType(RelatedRetType); } } else // If we don't have a function/method context, bail. return StmtError(); @@ -1855,7 +1975,26 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { ReturnStmt *Result = 0; if (FnRetType->isVoidType()) { if (RetValExp) { - if (!RetValExp->isTypeDependent()) { + if (isa<InitListExpr>(RetValExp)) { + // We simply never allow init lists as the return value of void + // functions. This is compatible because this was never allowed before, + // so there's no legacy code to deal with. + NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); + int FunctionKind = 0; + if (isa<ObjCMethodDecl>(CurDecl)) + FunctionKind = 1; + else if (isa<CXXConstructorDecl>(CurDecl)) + FunctionKind = 2; + else if (isa<CXXDestructorDecl>(CurDecl)) + FunctionKind = 3; + + Diag(ReturnLoc, diag::err_return_init_list) + << CurDecl->getDeclName() << FunctionKind + << RetValExp->getSourceRange(); + + // Drop the expression. + RetValExp = 0; + } else if (!RetValExp->isTypeDependent()) { // C99 6.8.6.4p1 (ext_ since GCC warns) unsigned D = diag::ext_return_has_expr; if (RetValExp->getType()->isVoidType()) @@ -1872,7 +2011,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // return (some void expression); is legal in C++. if (D != diag::ext_return_has_void_expr || - !getLangOptions().CPlusPlus) { + !getLangOpts().CPlusPlus) { NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); int FunctionKind = 0; @@ -1889,15 +2028,17 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } } - CheckImplicitConversions(RetValExp, ReturnLoc); - RetValExp = MaybeCreateExprWithCleanups(RetValExp); + if (RetValExp) { + CheckImplicitConversions(RetValExp, ReturnLoc); + RetValExp = MaybeCreateExprWithCleanups(RetValExp); + } } Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, 0); } else if (!RetValExp && !FnRetType->isDependentType()) { unsigned DiagID = diag::warn_return_missing_expr; // C90 6.6.6.4p4 // C99 6.8.6.4p1 (ext_ since GCC warns) - if (getLangOptions().C99) DiagID = diag::ext_return_missing_expr; + if (getLangOpts().C99) DiagID = diag::ext_return_missing_expr; if (FunctionDecl *FD = getCurFunctionDecl()) Diag(ReturnLoc, DiagID) << FD->getIdentifier() << 0/*fn*/; @@ -1909,6 +2050,21 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) { // we have a non-void function with an expression, continue checking + if (!RelatedRetType.isNull()) { + // If we have a related result type, perform an extra conversion here. + // FIXME: The diagnostics here don't really describe what is happening. + InitializedEntity Entity = + InitializedEntity::InitializeTemporary(RelatedRetType); + + ExprResult Res = PerformCopyInitialization(Entity, SourceLocation(), + RetValExp); + if (Res.isInvalid()) { + // FIXME: Cleanup temporaries here, anyway? + return StmtError(); + } + RetValExp = Res.takeAs<Expr>(); + } + // 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. @@ -1932,17 +2088,6 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (RetValExp) { - // If we type-checked an Objective-C method's return type based - // on a related return type, we may need to adjust the return - // type again. Do so now. - if (DeclaredRetType != FnRetType) { - ExprResult result = PerformImplicitConversion(RetValExp, - DeclaredRetType, - AA_Returning); - if (result.isInvalid()) return StmtError(); - RetValExp = result.take(); - } - CheckImplicitConversions(RetValExp, ReturnLoc); RetValExp = MaybeCreateExprWithCleanups(RetValExp); } @@ -1951,7 +2096,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // If we need to check for the named return value optimization, save the // return statement in our scope for later processing. - if (getLangOptions().CPlusPlus && FnRetType->isRecordType() && + if (getLangOpts().CPlusPlus && FnRetType->isRecordType() && !CurContext->isDependentContext()) FunctionScopes.back()->Returns.push_back(Result); @@ -1977,7 +2122,7 @@ static bool CheckAsmLValue(const Expr *E, Sema &S) { // are supposed to allow. const Expr *E2 = E->IgnoreParenNoopCasts(S.Context); if (E != E2 && E2->isLValue()) { - if (!S.getLangOptions().HeinousExtensions) + if (!S.getLangOpts().HeinousExtensions) S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue) << E->getSourceRange(); else @@ -2255,7 +2400,7 @@ Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) { StmtResult Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, MultiStmtArg CatchStmts, Stmt *Finally) { - if (!getLangOptions().ObjCExceptions) + if (!getLangOpts().ObjCExceptions) Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try"; getCurFunction()->setHasBranchProtectedScope(); @@ -2292,7 +2437,7 @@ StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, StmtResult Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, Scope *CurScope) { - if (!getLangOptions().ObjCExceptions) + if (!getLangOpts().ObjCExceptions) Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw"; if (!Throw) { @@ -2392,7 +2537,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, MultiStmtArg RawHandlers) { // Don't report an error if 'try' is used in system headers. - if (!getLangOptions().CXXExceptions && + if (!getLangOpts().CXXExceptions && !getSourceManager().isInSystemHeader(TryLoc)) Diag(TryLoc, diag::err_exceptions_disabled) << "try"; @@ -2484,3 +2629,26 @@ Sema::ActOnSEHFinallyBlock(SourceLocation Loc, assert(Block); return Owned(SEHFinallyStmt::Create(Context,Loc,Block)); } + +StmtResult Sema::BuildMSDependentExistsStmt(SourceLocation KeywordLoc, + bool IsIfExists, + NestedNameSpecifierLoc QualifierLoc, + DeclarationNameInfo NameInfo, + Stmt *Nested) +{ + return new (Context) MSDependentExistsStmt(KeywordLoc, IsIfExists, + QualifierLoc, NameInfo, + cast<CompoundStmt>(Nested)); +} + + +StmtResult Sema::ActOnMSDependentExistsStmt(SourceLocation KeywordLoc, + bool IsIfExists, + CXXScopeSpec &SS, + UnqualifiedId &Name, + Stmt *Nested) { + return BuildMSDependentExistsStmt(KeywordLoc, IsIfExists, + SS.getWithLocInContext(Context), + GetNameFromUnqualifiedId(Name), + Nested); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp index 8dda34c..ff8c4da 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp @@ -26,6 +26,8 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/PartialDiagnostic.h" +#include "llvm/ADT/SmallBitVector.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" using namespace clang; using namespace sema; @@ -42,11 +44,16 @@ clang::getTemplateParamsRange(TemplateParameterList const * const *Ps, /// of a template and, if so, return that template declaration. Otherwise, /// returns NULL. static NamedDecl *isAcceptableTemplateName(ASTContext &Context, - NamedDecl *Orig) { + NamedDecl *Orig, + bool AllowFunctionTemplates) { NamedDecl *D = Orig->getUnderlyingDecl(); - if (isa<TemplateDecl>(D)) + if (isa<TemplateDecl>(D)) { + if (!AllowFunctionTemplates && isa<FunctionTemplateDecl>(D)) + return 0; + return Orig; + } if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) { // C++ [temp.local]p1: @@ -76,13 +83,15 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context, return 0; } -void Sema::FilterAcceptableTemplateNames(LookupResult &R) { +void Sema::FilterAcceptableTemplateNames(LookupResult &R, + bool AllowFunctionTemplates) { // The set of class templates we've already seen. llvm::SmallPtrSet<ClassTemplateDecl *, 8> ClassTemplates; LookupResult::Filter filter = R.makeFilter(); while (filter.hasNext()) { NamedDecl *Orig = filter.next(); - NamedDecl *Repl = isAcceptableTemplateName(Context, Orig); + NamedDecl *Repl = isAcceptableTemplateName(Context, Orig, + AllowFunctionTemplates); if (!Repl) filter.erase(); else if (Repl != Orig) { @@ -112,9 +121,10 @@ void Sema::FilterAcceptableTemplateNames(LookupResult &R) { filter.done(); } -bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R) { +bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R, + bool AllowFunctionTemplates) { for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) - if (isAcceptableTemplateName(Context, *I)) + if (isAcceptableTemplateName(Context, *I, AllowFunctionTemplates)) return true; return false; @@ -128,7 +138,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S, bool EnteringContext, TemplateTy &TemplateResult, bool &MemberOfUnknownSpecialization) { - assert(getLangOptions().CPlusPlus && "No template names in C!"); + assert(getLangOpts().CPlusPlus && "No template names in C!"); DeclarationName TName; MemberOfUnknownSpecialization = false; @@ -153,8 +163,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S, QualType ObjectType = ObjectTypePtr.get(); - LookupResult R(*this, TName, Name.getSourceRange().getBegin(), - LookupOrdinaryName); + LookupResult R(*this, TName, Name.getLocStart(), LookupOrdinaryName); LookupTemplateName(R, S, SS, ObjectType, EnteringContext, MemberOfUnknownSpecialization); if (R.empty()) return TNK_Non_template; @@ -249,6 +258,12 @@ void Sema::LookupTemplateName(LookupResult &Found, isDependent = ObjectType->isDependentType(); assert((isDependent || !ObjectType->isIncompleteType()) && "Caller should have completed object type"); + + // Template names cannot appear inside an Objective-C class or object type. + if (ObjectType->isObjCObjectOrInterfaceType()) { + Found.clear(); + return; + } } else if (SS.isSet()) { // This nested-name-specifier occurs after another nested-name-specifier, // so long into the context associated with the prior nested-name-specifier. @@ -261,13 +276,13 @@ void Sema::LookupTemplateName(LookupResult &Found, } bool ObjectTypeSearchedInScope = false; + bool AllowFunctionTemplatesInLookup = true; if (LookupCtx) { // Perform "qualified" name lookup into the declaration context we // computed, which is either the type of the base of a member access // expression or the declaration context associated with a prior // nested-name-specifier. LookupQualifiedName(Found, LookupCtx); - if (!ObjectType.isNull() && Found.empty()) { // C++ [basic.lookup.classref]p1: // In a class member access expression (5.2.5), if the . or -> token is @@ -280,6 +295,7 @@ void Sema::LookupTemplateName(LookupResult &Found, // or function template. if (S) LookupName(Found, S); ObjectTypeSearchedInScope = true; + AllowFunctionTemplatesInLookup = false; } } else if (isDependent && (!S || ObjectType.isNull())) { // We cannot look into a dependent object type or nested nme @@ -289,23 +305,31 @@ void Sema::LookupTemplateName(LookupResult &Found, } else { // Perform unqualified name lookup in the current scope. LookupName(Found, S); + + if (!ObjectType.isNull()) + AllowFunctionTemplatesInLookup = false; } if (Found.empty() && !isDependent) { // If we did not find any names, attempt to correct any typos. DeclarationName Name = Found.getLookupName(); Found.clear(); + // Simple filter callback that, for keywords, only accepts the C++ *_cast + CorrectionCandidateCallback FilterCCC; + FilterCCC.WantTypeSpecifiers = false; + FilterCCC.WantExpressionKeywords = false; + FilterCCC.WantRemainingKeywords = false; + FilterCCC.WantCXXNamedCasts = true; if (TypoCorrection Corrected = CorrectTypo(Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS, - LookupCtx, false, - CTC_CXXCasts)) { + FilterCCC, LookupCtx)) { Found.setLookupName(Corrected.getCorrection()); if (Corrected.getCorrectionDecl()) Found.addDecl(Corrected.getCorrectionDecl()); FilterAcceptableTemplateNames(Found); if (!Found.empty()) { - std::string CorrectedStr(Corrected.getAsString(getLangOptions())); - std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions())); + std::string CorrectedStr(Corrected.getAsString(getLangOpts())); + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); if (LookupCtx) Diag(Found.getNameLoc(), diag::err_no_member_template_suggest) << Name << LookupCtx << CorrectedQuotedStr << SS.getRange() @@ -323,7 +347,7 @@ void Sema::LookupTemplateName(LookupResult &Found, } } - FilterAcceptableTemplateNames(Found); + FilterAcceptableTemplateNames(Found, AllowFunctionTemplatesInLookup); if (Found.empty()) { if (isDependent) MemberOfUnknownSpecialization = true; @@ -339,7 +363,7 @@ void Sema::LookupTemplateName(LookupResult &Found, LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(), LookupOrdinaryName); LookupName(FoundOuter, S); - FilterAcceptableTemplateNames(FoundOuter); + FilterAcceptableTemplateNames(FoundOuter, /*AllowFunctionTemplates=*/false); if (FoundOuter.empty()) { // - if the name is not found, the name found in the class of the @@ -379,6 +403,7 @@ void Sema::LookupTemplateName(LookupResult &Found, /// specifier naming a dependent type. ExprResult Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool isAddressOfOperand, const TemplateArgumentListInfo *TemplateArgs) { @@ -398,20 +423,23 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, /*IsArrow*/ true, /*Op*/ SourceLocation(), SS.getWithLocInContext(Context), + TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs)); } - return BuildDependentDeclRefExpr(SS, NameInfo, TemplateArgs); + return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); } ExprResult Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs) { return Owned(DependentScopeDeclRefExpr::Create(Context, SS.getWithLocInContext(Context), + TemplateKWLoc, NameInfo, TemplateArgs)); } @@ -420,12 +448,12 @@ Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS, /// that the template parameter 'PrevDecl' is being shadowed by a new /// declaration at location Loc. Returns true to indicate that this is /// an error, and false otherwise. -bool Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) { +void Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) { assert(PrevDecl->isTemplateParameter() && "Not a template parameter"); // Microsoft Visual C++ permits template parameters to be shadowed. - if (getLangOptions().MicrosoftExt) - return false; + if (getLangOpts().MicrosoftExt) + return; // C++ [temp.local]p4: // A template-parameter shall not be redeclared within its @@ -433,7 +461,7 @@ bool Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) { Diag(Loc, diag::err_template_param_shadow) << cast<NamedDecl>(PrevDecl)->getDeclName(); Diag(PrevDecl->getLocation(), diag::note_template_param_here); - return true; + return; } /// AdjustDeclIfTemplate - If the given decl happens to be a template, reset @@ -491,7 +519,6 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, } llvm_unreachable("Unhandled parsed template argument"); - return TemplateArgumentLoc(); } /// \brief Translates template arguments as provided by the parser @@ -528,9 +555,10 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, NamedDecl *PrevDecl = LookupSingleName(S, ParamName, ParamNameLoc, LookupOrdinaryName, ForRedeclaration); - if (PrevDecl && PrevDecl->isTemplateParameter()) - Invalid = Invalid || DiagnoseTemplateParameterShadow(ParamNameLoc, - PrevDecl); + if (PrevDecl && PrevDecl->isTemplateParameter()) { + DiagnoseTemplateParameterShadow(ParamNameLoc, PrevDecl); + PrevDecl = 0; + } } SourceLocation Loc = ParamNameLoc; @@ -615,8 +643,12 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) { T->isNullPtrType() || // If T is a dependent type, we can't do the check now, so we // assume that it is well-formed. - T->isDependentType()) - return T; + T->isDependentType()) { + // C++ [temp.param]p5: The top-level cv-qualifiers on the template-parameter + // are ignored when determining its type. + return T.getUnqualifiedType(); + } + // C++ [temp.param]p8: // // A non-type template-parameter of type "array of T" or @@ -652,9 +684,10 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, NamedDecl *PrevDecl = LookupSingleName(S, ParamName, D.getIdentifierLoc(), LookupOrdinaryName, ForRedeclaration); - if (PrevDecl && PrevDecl->isTemplateParameter()) - Invalid = Invalid || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), - PrevDecl); + if (PrevDecl && PrevDecl->isTemplateParameter()) { + DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); + PrevDecl = 0; + } } T = CheckNonTypeTemplateParameterType(T, D.getIdentifierLoc()); @@ -666,7 +699,7 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, bool IsParameterPack = D.hasEllipsis(); NonTypeTemplateParmDecl *Param = NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(), - D.getSourceRange().getBegin(), + D.getLocStart(), D.getIdentifierLoc(), Depth, Position, ParamName, T, IsParameterPack, TInfo); @@ -839,7 +872,12 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, if (SS.isNotEmpty() && !SS.isInvalid()) { SemanticContext = computeDeclContext(SS, true); if (!SemanticContext) { - // FIXME: Produce a reasonable diagnostic here + // FIXME: Horrible, horrible hack! We can't currently represent this + // in the AST, and historically we have just ignored such friend + // class templates, so don't complain here. + if (TUK != TUK_Friend) + Diag(NameLoc, diag::err_template_qualified_declarator_no_match) + << SS.getScopeRep() << SS.getRange(); return true; } @@ -853,7 +891,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, ContextRAII SavedContext(*this, SemanticContext); if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams)) Invalid = true; - } + } else if (TUK != TUK_Friend && TUK != TUK_Reference) + diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc); LookupQualifiedName(Previous, SemanticContext); } else { @@ -987,9 +1026,11 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // If the name of the template was qualified, we must be defining the // template out-of-line. if (!SS.isInvalid() && !Invalid && !PrevClassTemplate && - !(TUK == TUK_Friend && CurContext->isDependentContext())) + !(TUK == TUK_Friend && CurContext->isDependentContext())) { Diag(NameLoc, diag::err_member_def_does_not_match) << Name << SemanticContext << SS.getRange(); + Invalid = true; + } } CXXRecordDecl *NewClass = @@ -1003,21 +1044,19 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, NumOuterTemplateParamLists, OuterTemplateParamLists); + // Add alignment attributes if necessary; these attributes are checked when + // the ASTContext lays out the structure. + AddAlignmentAttributesForRecord(NewClass); + AddMsStructLayoutForRecord(NewClass); + ClassTemplateDecl *NewTemplate = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc, DeclarationName(Name), TemplateParams, NewClass, PrevClassTemplate); NewClass->setDescribedClassTemplate(NewTemplate); - if (PrevClassTemplate && PrevClassTemplate->isModulePrivate()) { + if (ModulePrivateLoc.isValid()) NewTemplate->setModulePrivate(); - } else if (ModulePrivateLoc.isValid()) { - if (PrevClassTemplate && !PrevClassTemplate->isModulePrivate()) - diagnoseModulePrivateRedeclaration(NewTemplate, PrevClassTemplate, - ModulePrivateLoc); - else - NewTemplate->setModulePrivate(); - } // Build the type for the class template declaration now. QualType T = NewTemplate->getInjectedClassNameSpecialization(); @@ -1032,7 +1071,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, PrevClassTemplate->setMemberSpecialization(); // Set the access specifier. - if (!Invalid && TUK != TUK_Friend) + if (!Invalid && TUK != TUK_Friend && NewTemplate->getDeclContext()->isRecord()) SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS); // Set the lexical context of these templates @@ -1059,7 +1098,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // Friend templates are visible in fairly strange ways. if (!CurContext->isDependentContext()) { DeclContext *DC = SemanticContext->getRedeclContext(); - DC->makeDeclVisibleInContext(NewTemplate, /* Recoverable = */ false); + DC->makeDeclVisibleInContext(NewTemplate); if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) PushOnScopeChains(NewTemplate, EnclosingScope, /* AddToContext = */ false); @@ -1103,10 +1142,10 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S, // template-argument, that declaration shall be a definition and shall be // the only declaration of the function template in the translation unit. // (C++98/03 doesn't have this wording; see DR226). - if (!S.getLangOptions().CPlusPlus0x) - S.Diag(ParamLoc, - diag::ext_template_parameter_default_in_function_template) - << DefArgRange; + S.Diag(ParamLoc, S.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_template_parameter_default_in_function_template + : diag::ext_template_parameter_default_in_function_template) + << DefArgRange; return false; case Sema::TPC_ClassTemplateMember: @@ -1131,7 +1170,7 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S, // declaration (and it is a definition). Strange! } - return false; + llvm_unreachable("Invalid TemplateParamListContext!"); } /// \brief Check for unexpanded parameter packs within the template parameters @@ -1195,9 +1234,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, bool SawDefaultArgument = false; SourceLocation PreviousDefaultArgLoc; - bool SawParameterPack = false; - SourceLocation ParameterPackLoc; - // Dummy initialization to avoid warnings. TemplateParameterList::iterator OldParam = NewParams->end(); if (OldParams) @@ -1212,18 +1248,11 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, SourceLocation OldDefaultLoc; SourceLocation NewDefaultLoc; - // Variables used to diagnose missing default arguments + // Variable used to diagnose missing default arguments bool MissingDefaultArg = false; - // C++0x [temp.param]p11: - // If a template parameter of a primary class template or alias template - // is a template parameter pack, it shall be the last template parameter. - if (SawParameterPack && - (TPC == TPC_ClassTemplate || TPC == TPC_TypeAliasTemplate)) { - Diag(ParameterPackLoc, - diag::err_template_param_pack_must_be_last_template_parameter); - Invalid = true; - } + // Variable used to diagnose non-final parameter packs + bool SawParameterPack = false; if (TemplateTypeParmDecl *NewTypeParm = dyn_cast<TemplateTypeParmDecl>(*NewParam)) { @@ -1243,7 +1272,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, assert(!NewTypeParm->hasDefaultArgument() && "Parameter packs can't have a default argument!"); SawParameterPack = true; - ParameterPackLoc = NewTypeParm->getLocation(); } else if (OldTypeParm && OldTypeParm->hasDefaultArgument() && NewTypeParm->hasDefaultArgument()) { OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc(); @@ -1288,7 +1316,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, assert(!NewNonTypeParm->hasDefaultArgument() && "Parameter packs can't have a default argument!"); SawParameterPack = true; - ParameterPackLoc = NewNonTypeParm->getLocation(); } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() && NewNonTypeParm->hasDefaultArgument()) { OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc(); @@ -1313,16 +1340,16 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, } else if (SawDefaultArgument) MissingDefaultArg = true; } else { - // Check the presence of a default argument here. TemplateTemplateParmDecl *NewTemplateParm = cast<TemplateTemplateParmDecl>(*NewParam); // Check for unexpanded parameter packs, recursively. - if (DiagnoseUnexpandedParameterPacks(*this, NewTemplateParm)) { + if (::DiagnoseUnexpandedParameterPacks(*this, NewTemplateParm)) { Invalid = true; continue; } + // Check the presence of a default argument here. if (NewTemplateParm->hasDefaultArgument() && DiagnoseDefaultTemplateArgument(*this, TPC, NewTemplateParm->getLocation(), @@ -1336,7 +1363,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, assert(!NewTemplateParm->hasDefaultArgument() && "Parameter packs can't have a default argument!"); SawParameterPack = true; - ParameterPackLoc = NewTemplateParm->getLocation(); } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() && NewTemplateParm->hasDefaultArgument()) { OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation(); @@ -1363,6 +1389,16 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, MissingDefaultArg = true; } + // C++0x [temp.param]p11: + // If a template parameter of a primary class template or alias template + // is a template parameter pack, it shall be the last template parameter. + if (SawParameterPack && (NewParam + 1) != NewParamEnd && + (TPC == TPC_ClassTemplate || TPC == TPC_TypeAliasTemplate)) { + Diag((*NewParam)->getLocation(), + diag::err_template_param_pack_must_be_last_template_parameter); + Invalid = true; + } + if (RedundantDefaultArg) { // C++ [temp.param]p12: // A template-parameter shall not be given default arguments @@ -1878,7 +1914,6 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) { } } - QualType Sema::CheckTemplateIdType(TemplateName Name, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs) { @@ -1910,18 +1945,17 @@ 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)) + false, Converted, &ExpansionIntoFixedList)) return QualType(); - assert((Converted.size() == Template->getTemplateParameters()->size()) && - "Converted template argument list is too short!"); - QualType CanonType; bool InstantiationDependent = false; - if (TypeAliasTemplateDecl *AliasTemplate - = dyn_cast<TypeAliasTemplateDecl>(Template)) { + TypeAliasTemplateDecl *AliasTemplate = 0; + if (!ExpansionIntoFixedList && + (AliasTemplate = dyn_cast<TypeAliasTemplateDecl>(Template))) { // Find the canonical type for this type alias template specialization. TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl(); if (Pattern->isInvalidDecl()) @@ -2037,11 +2071,12 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, } TypeResult -Sema::ActOnTemplateIdType(CXXScopeSpec &SS, +Sema::ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, TemplateTy TemplateD, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation RAngleLoc) { + SourceLocation RAngleLoc, + bool IsCtorOrDtorName) { if (SS.isInvalid()) return true; @@ -2052,20 +2087,21 @@ Sema::ActOnTemplateIdType(CXXScopeSpec &SS, translateTemplateArguments(TemplateArgsIn, TemplateArgs); if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { - QualType T = Context.getDependentTemplateSpecializationType(ETK_None, - DTN->getQualifier(), - DTN->getIdentifier(), - TemplateArgs); - - // Build type-source information. + QualType T + = Context.getDependentTemplateSpecializationType(ETK_None, + DTN->getQualifier(), + DTN->getIdentifier(), + TemplateArgs); + // Build type-source information. TypeLocBuilder TLB; DependentTemplateSpecializationTypeLoc SpecTL = TLB.push<DependentTemplateSpecializationTypeLoc>(T); - SpecTL.setKeywordLoc(SourceLocation()); - SpecTL.setNameLoc(TemplateLoc); + SpecTL.setElaboratedKeywordLoc(SourceLocation()); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + SpecTL.setTemplateKeywordLoc(TemplateKWLoc); + SpecTL.setTemplateNameLoc(TemplateLoc); SpecTL.setLAngleLoc(LAngleLoc); SpecTL.setRAngleLoc(RAngleLoc); - SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I) SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); @@ -2078,20 +2114,24 @@ Sema::ActOnTemplateIdType(CXXScopeSpec &SS, return true; // Build type-source information. - TypeLocBuilder TLB; + TypeLocBuilder TLB; TemplateSpecializationTypeLoc SpecTL = TLB.push<TemplateSpecializationTypeLoc>(Result); + SpecTL.setTemplateKeywordLoc(TemplateKWLoc); SpecTL.setTemplateNameLoc(TemplateLoc); SpecTL.setLAngleLoc(LAngleLoc); SpecTL.setRAngleLoc(RAngleLoc); for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i) SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo()); - if (SS.isNotEmpty()) { + // NOTE: avoid constructing an ElaboratedTypeLoc if this is a + // constructor or destructor name (in such a case, the scope specifier + // will be attached to the enclosing Decl or Expr node). + if (SS.isNotEmpty() && !IsCtorOrDtorName) { // Create an elaborated-type-specifier containing the nested-name-specifier. Result = Context.getElaboratedType(ETK_None, SS.getScopeRep(), Result); ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result); - ElabTL.setKeywordLoc(SourceLocation()); + ElabTL.setElaboratedKeywordLoc(SourceLocation()); ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); } @@ -2102,7 +2142,8 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, TypeSpecifierType TagSpec, SourceLocation TagLoc, CXXScopeSpec &SS, - TemplateTy TemplateD, + SourceLocation TemplateKWLoc, + TemplateTy TemplateD, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, @@ -2127,12 +2168,13 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, // Build type-source information. TypeLocBuilder TLB; DependentTemplateSpecializationTypeLoc SpecTL - = TLB.push<DependentTemplateSpecializationTypeLoc>(T); - SpecTL.setKeywordLoc(TagLoc); - SpecTL.setNameLoc(TemplateLoc); + = TLB.push<DependentTemplateSpecializationTypeLoc>(T); + SpecTL.setElaboratedKeywordLoc(TagLoc); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + SpecTL.setTemplateKeywordLoc(TemplateKWLoc); + SpecTL.setTemplateNameLoc(TemplateLoc); SpecTL.setLAngleLoc(LAngleLoc); SpecTL.setRAngleLoc(RAngleLoc); - SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I) SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); @@ -2167,11 +2209,12 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, Diag(D->getLocation(), diag::note_previous_use); } } - + // Provide source-location information for the template specialization. TypeLocBuilder TLB; TemplateSpecializationTypeLoc SpecTL = TLB.push<TemplateSpecializationTypeLoc>(Result); + SpecTL.setTemplateKeywordLoc(TemplateKWLoc); SpecTL.setTemplateNameLoc(TemplateLoc); SpecTL.setLAngleLoc(LAngleLoc); SpecTL.setRAngleLoc(RAngleLoc); @@ -2179,18 +2222,19 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo()); // Construct an elaborated type containing the nested-name-specifier (if any) - // and keyword. + // and tag keyword. Result = Context.getElaboratedType(Keyword, SS.getScopeRep(), Result); ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result); - ElabTL.setKeywordLoc(TagLoc); + ElabTL.setElaboratedKeywordLoc(TagLoc); ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); } ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, LookupResult &R, bool RequiresADL, - const TemplateArgumentListInfo &TemplateArgs) { + const TemplateArgumentListInfo *TemplateArgs) { // FIXME: Can we do any checking at this point? I guess we could check the // template arguments that we have against the template name, if the template // name refers to a single template. That's not a terribly common case, @@ -2211,6 +2255,7 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create(Context, R.getNamingClass(), SS.getWithLocInContext(Context), + TemplateKWLoc, R.getLookupNameInfo(), RequiresADL, TemplateArgs, R.begin(), R.end()); @@ -2221,13 +2266,15 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, // We actually only call this from template instantiation. ExprResult Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo &TemplateArgs) { + const TemplateArgumentListInfo *TemplateArgs) { + assert(TemplateArgs || TemplateKWLoc.isValid()); DeclContext *DC; if (!(DC = computeDeclContext(SS, false)) || DC->isDependentContext() || RequireCompleteDeclContext(SS, DC)) - return BuildDependentDeclRefExpr(SS, NameInfo, &TemplateArgs); + return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); bool MemberOfUnknownSpecialization; LookupResult R(*this, NameInfo, LookupOrdinaryName); @@ -2251,7 +2298,7 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, return ExprError(); } - return BuildTemplateIdExpr(SS, R, /* ADL */ false, TemplateArgs); + return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/ false, TemplateArgs); } /// \brief Form a dependent template name. @@ -2262,15 +2309,17 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, /// SS will be "MetaFun::", \p TemplateKWLoc contains the location /// of the "template" keyword, and "apply" is the \p Name. TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, - SourceLocation TemplateKWLoc, CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext, TemplateTy &Result) { - if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent() && - !getLangOptions().CPlusPlus0x) - Diag(TemplateKWLoc, diag::ext_template_outside_of_template) + if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent()) + Diag(TemplateKWLoc, + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_template_outside_of_template : + diag::ext_template_outside_of_template) << FixItHint::CreateRemoval(TemplateKWLoc); DeclContext *LookupCtx = 0; @@ -2305,7 +2354,7 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases())) { // This is a dependent template. Handle it below. } else if (TNK == TNK_Non_template) { - Diag(Name.getSourceRange().getBegin(), + Diag(Name.getLocStart(), diag::err_template_kw_refers_to_non_template) << GetNameFromUnqualifiedId(Name).getName() << Name.getSourceRange() @@ -2339,7 +2388,7 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, break; } - Diag(Name.getSourceRange().getBegin(), + Diag(Name.getLocStart(), diag::err_template_kw_refers_to_non_template) << GetNameFromUnqualifiedId(Name).getName() << Name.getSourceRange() @@ -2391,7 +2440,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, // Objective-C ARC: // If an explicitly-specified template argument type is a lifetime type // with no lifetime qualifier, the __strong lifetime qualifier is inferred. - if (getLangOptions().ObjCAutoRefCount && + if (getLangOpts().ObjCAutoRefCount && ArgType->isObjCLifetimeType() && !ArgType.getObjCLifetime()) { Qualifiers Qs; @@ -2729,9 +2778,14 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, CXXScopeSpec SS; SS.Adopt(Arg.getTemplateQualifierLoc()); + // FIXME: the template-template arg was a DependentTemplateName, + // 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), - NameInfo)); + TemplateKWLoc, + NameInfo, 0)); // If we parsed the template argument as a pack expansion, create a // pack expansion expression. @@ -2782,7 +2836,6 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, case TemplateArgument::Pack: llvm_unreachable("Caller must expand template argument packs"); - break; } return false; @@ -2828,33 +2881,55 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, // We have a template template parameter but the template // argument does not refer to a template. Diag(Arg.getLocation(), diag::err_template_arg_must_be_template) - << getLangOptions().CPlusPlus0x; + << getLangOpts().CPlusPlus0x; return true; case TemplateArgument::Declaration: - llvm_unreachable( - "Declaration argument with template template parameter"); - break; + llvm_unreachable("Declaration argument with template template parameter"); case TemplateArgument::Integral: - llvm_unreachable( - "Integral argument with template template parameter"); - break; + llvm_unreachable("Integral argument with template template parameter"); case TemplateArgument::Pack: llvm_unreachable("Caller must expand template argument packs"); - break; } return false; } +/// \brief Diagnose an arity mismatch in the +static bool diagnoseArityMismatch(Sema &S, TemplateDecl *Template, + SourceLocation TemplateLoc, + TemplateArgumentListInfo &TemplateArgs) { + TemplateParameterList *Params = Template->getTemplateParameters(); + unsigned NumParams = Params->size(); + unsigned NumArgs = TemplateArgs.size(); + + SourceRange Range; + if (NumArgs > NumParams) + Range = SourceRange(TemplateArgs[NumParams].getLocation(), + TemplateArgs.getRAngleLoc()); + S.Diag(TemplateLoc, diag::err_template_arg_list_different_arity) + << (NumArgs > NumParams) + << (isa<ClassTemplateDecl>(Template)? 0 : + isa<FunctionTemplateDecl>(Template)? 1 : + isa<TemplateTemplateParmDecl>(Template)? 2 : 3) + << Template << Range; + S.Diag(Template->getLocation(), diag::note_template_decl_here) + << Params->getSourceRange(); + return true; +} + /// \brief Check that the given template argument list is well-formed /// for specializing the given template. bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, - SmallVectorImpl<TemplateArgument> &Converted) { + SmallVectorImpl<TemplateArgument> &Converted, + bool *ExpansionIntoFixedList) { + if (ExpansionIntoFixedList) + *ExpansionIntoFixedList = false; + TemplateParameterList *Params = Template->getTemplateParameters(); unsigned NumParams = Params->size(); unsigned NumArgs = TemplateArgs.size(); @@ -2864,27 +2939,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, bool HasParameterPack = NumParams > 0 && Params->getParam(NumParams - 1)->isTemplateParameterPack(); - - if ((NumArgs > NumParams && !HasParameterPack) || - (NumArgs < Params->getMinRequiredArguments() && - !PartialTemplateArgs)) { - // FIXME: point at either the first arg beyond what we can handle, - // or the '>', depending on whether we have too many or too few - // arguments. - SourceRange Range; - if (NumArgs > NumParams) - Range = SourceRange(TemplateArgs[NumParams].getLocation(), RAngleLoc); - Diag(TemplateLoc, diag::err_template_arg_list_different_arity) - << (NumArgs > NumParams) - << (isa<ClassTemplateDecl>(Template)? 0 : - isa<FunctionTemplateDecl>(Template)? 1 : - isa<TemplateTemplateParmDecl>(Template)? 2 : 3) - << Template << Range; - Diag(Template->getLocation(), diag::note_template_decl_here) - << Params->getSourceRange(); - Invalid = true; - } - + // C++ [temp.arg]p1: // [...] The type and form of each template-argument specified in // a template-id shall match the type and form specified for the @@ -2896,10 +2951,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, ParamEnd = Params->end(); unsigned ArgIdx = 0; LocalInstantiationScope InstScope(*this, true); + bool SawPackExpansion = false; while (Param != ParamEnd) { if (ArgIdx < NumArgs) { // If we have an expanded parameter pack, make sure we don't have too // many arguments. + // FIXME: This really should fall out from the normal arity checking. if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { if (NTTP->isExpandedParameterPack() && @@ -2933,6 +2990,15 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // Move to the next template parameter. ++Param; } + + // If this template argument is a pack expansion, record that fact + // and break out; we can't actually check any more. + if (TemplateArgs[ArgIdx].getArgument().isPackExpansion()) { + SawPackExpansion = true; + ++ArgIdx; + break; + } + ++ArgIdx; continue; } @@ -2952,7 +3018,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if ((*Param)->isTemplateParameterPack()) break; - // We have a default template argument that we will use. + // Check whether we have a default argument. TemplateArgumentLoc Arg; // Retrieve the default template argument from the template @@ -2961,10 +3027,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // (when the template parameter was part of a nested template) into // the default argument. if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) { - if (!TTP->hasDefaultArgument()) { - assert(Invalid && "Missing default argument"); - break; - } + if (!TTP->hasDefaultArgument()) + return diagnoseArityMismatch(*this, Template, TemplateLoc, + TemplateArgs); TypeSourceInfo *ArgType = SubstDefaultTemplateArgument(*this, Template, @@ -2979,10 +3044,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, ArgType); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { - if (!NTTP->hasDefaultArgument()) { - assert(Invalid && "Missing default argument"); - break; - } + if (!NTTP->hasDefaultArgument()) + return diagnoseArityMismatch(*this, Template, TemplateLoc, + TemplateArgs); ExprResult E = SubstDefaultTemplateArgument(*this, Template, TemplateLoc, @@ -2998,10 +3062,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(*Param); - if (!TempParm->hasDefaultArgument()) { - assert(Invalid && "Missing default argument"); - break; - } + if (!TempParm->hasDefaultArgument()) + return diagnoseArityMismatch(*this, Template, TemplateLoc, + TemplateArgs); NestedNameSpecifierLoc QualifierLoc; TemplateName Name = SubstDefaultTemplateArgument(*this, Template, @@ -3039,12 +3102,71 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, ++ArgIdx; } + // If we saw a pack expansion, then directly convert the remaining arguments, + // because we don't know what parameters they'll match up with. + if (SawPackExpansion) { + bool AddToArgumentPack + = Param != ParamEnd && (*Param)->isTemplateParameterPack(); + while (ArgIdx < NumArgs) { + if (AddToArgumentPack) + ArgumentPack.push_back(TemplateArgs[ArgIdx].getArgument()); + else + Converted.push_back(TemplateArgs[ArgIdx].getArgument()); + ++ArgIdx; + } + + // Push the argument pack onto the list of converted arguments. + if (AddToArgumentPack) { + if (ArgumentPack.empty()) + Converted.push_back(TemplateArgument(0, 0)); + else { + Converted.push_back( + TemplateArgument::CreatePackCopy(Context, + ArgumentPack.data(), + ArgumentPack.size())); + ArgumentPack.clear(); + } + } else if (ExpansionIntoFixedList) { + // We have expanded a pack into a fixed list. + *ExpansionIntoFixedList = true; + } + + return Invalid; + } + + // If we have any leftover arguments, then there were too many arguments. + // Complain and fail. + if (ArgIdx < NumArgs) + return diagnoseArityMismatch(*this, Template, TemplateLoc, TemplateArgs); + + // If we have an expanded parameter pack, make sure we don't have too + // many arguments. + // FIXME: This really should fall out from the normal arity checking. + if (Param != ParamEnd) { + if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { + if (NTTP->isExpandedParameterPack() && + ArgumentPack.size() < NTTP->getNumExpansionTypes()) { + Diag(TemplateLoc, diag::err_template_arg_list_different_arity) + << false + << (isa<ClassTemplateDecl>(Template)? 0 : + isa<FunctionTemplateDecl>(Template)? 1 : + isa<TemplateTemplateParmDecl>(Template)? 2 : 3) + << Template; + Diag(Template->getLocation(), diag::note_template_decl_here) + << Params->getSourceRange(); + return true; + } + } + } + // Form argument packs for each of the parameter packs remaining. while (Param != ParamEnd) { // If we're checking a partial list of template arguments, don't fill // in arguments for non-template parameter packs. - if ((*Param)->isTemplateParameterPack()) { + if (!HasParameterPack) + return true; if (ArgumentPack.empty()) Converted.push_back(TemplateArgument(0, 0)); else { @@ -3053,7 +3175,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, ArgumentPack.size())); ArgumentPack.clear(); } - } + } else if (!PartialTemplateArgs) + return diagnoseArityMismatch(*this, Template, TemplateLoc, TemplateArgs); ++Param; } @@ -3261,13 +3384,19 @@ bool UnnamedLocalNoLinkageFinder::VisitAtomicType(const AtomicType* T) { bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) { if (Tag->getDeclContext()->isFunctionOrMethod()) { - S.Diag(SR.getBegin(), diag::ext_template_arg_local_type) + S.Diag(SR.getBegin(), + S.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_template_arg_local_type : + diag::ext_template_arg_local_type) << S.Context.getTypeDeclType(Tag) << SR; return true; } if (!Tag->getDeclName() && !Tag->getTypedefNameForAnonDecl()) { - S.Diag(SR.getBegin(), diag::ext_template_arg_unnamed_type) << SR; + S.Diag(SR.getBegin(), + S.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_template_arg_unnamed_type : + diag::ext_template_arg_unnamed_type) << SR; S.Diag(Tag->getLocation(), diag::note_template_unnamed_type_here); return true; } @@ -3291,7 +3420,7 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier( case NestedNameSpecifier::TypeSpecWithTemplate: return Visit(QualType(NNS->getAsType(), 0)); } - return false; + llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); } @@ -3317,9 +3446,14 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param, // compounded from any of these types shall not be used as a // template-argument for a template type-parameter. // - // C++0x allows these, and even in C++03 we allow them as an extension with + // C++11 allows these, and even in C++03 we allow them as an extension with // a warning. - if (!LangOpts.CPlusPlus0x && Arg->hasUnnamedOrLocalType()) { + if (LangOpts.CPlusPlus0x ? + 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()) { UnnamedLocalNoLinkageFinder Finder(*this, SR); (void)Finder.Visit(Context.getCanonicalType(Arg)); } @@ -3327,6 +3461,99 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param, return false; } +enum NullPointerValueKind { + NPV_NotNullPointer, + NPV_NullPointer, + NPV_Error +}; + +/// \brief Determine whether the given template argument is a null pointer +/// value of the appropriate type. +static NullPointerValueKind +isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, + QualType ParamType, Expr *Arg) { + if (Arg->isValueDependent() || Arg->isTypeDependent()) + return NPV_NotNullPointer; + + if (!S.getLangOpts().CPlusPlus0x) + return NPV_NotNullPointer; + + // Determine whether we have a constant expression. + ExprResult ArgRV = S.DefaultFunctionArrayConversion(Arg); + if (ArgRV.isInvalid()) + return NPV_Error; + Arg = ArgRV.take(); + + Expr::EvalResult EvalResult; + llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + EvalResult.Diag = &Notes; + if (!Arg->EvaluateAsRValue(EvalResult, S.Context) || + EvalResult.HasSideEffects) { + SourceLocation DiagLoc = Arg->getExprLoc(); + + // If our only note is the usual "invalid subexpression" note, just point + // the caret at its location rather than producing an essentially + // redundant note. + if (Notes.size() == 1 && Notes[0].second.getDiagID() == + diag::note_invalid_subexpr_in_const_expr) { + DiagLoc = Notes[0].first; + Notes.clear(); + } + + S.Diag(DiagLoc, diag::err_template_arg_not_address_constant) + << Arg->getType() << Arg->getSourceRange(); + for (unsigned I = 0, N = Notes.size(); I != N; ++I) + S.Diag(Notes[I].first, Notes[I].second); + + S.Diag(Param->getLocation(), diag::note_template_param_here); + return NPV_Error; + } + + // C++11 [temp.arg.nontype]p1: + // - an address constant expression of type std::nullptr_t + if (Arg->getType()->isNullPtrType()) + return NPV_NullPointer; + + // - a constant expression that evaluates to a null pointer value (4.10); or + // - a constant expression that evaluates to a null member pointer value + // (4.11); or + if ((EvalResult.Val.isLValue() && !EvalResult.Val.getLValueBase()) || + (EvalResult.Val.isMemberPointer() && + !EvalResult.Val.getMemberPointerDecl())) { + // If our expression has an appropriate type, we've succeeded. + bool ObjCLifetimeConversion; + if (S.Context.hasSameUnqualifiedType(Arg->getType(), ParamType) || + S.IsQualificationConversion(Arg->getType(), ParamType, false, + ObjCLifetimeConversion)) + return NPV_NullPointer; + + // The types didn't match, but we know we got a null pointer; complain, + // then recover as if the types were correct. + S.Diag(Arg->getExprLoc(), diag::err_template_arg_wrongtype_null_constant) + << Arg->getType() << ParamType << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return NPV_NullPointer; + } + + // If we don't have a null pointer value, but we do have a NULL pointer + // constant, suggest a cast to the appropriate type. + 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()), + ")"); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return NPV_NullPointer; + } + + // FIXME: If we ever want to support general, address-constant expressions + // as non-type template arguments, we should return the ExprResult here to + // be interpreted by the caller. + return NPV_NotNullPointer; +} + /// \brief Checks whether the given template argument is the address /// of an object or function according to C++ [temp.arg.nontype]p1. static bool @@ -3339,6 +3566,21 @@ 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: + Converted = TemplateArgument((Decl *)0); + return false; + + case NPV_Error: + return true; + + case NPV_NotNullPointer: + break; + } + } + // See through any implicit casts we added to fix the type. Arg = Arg->IgnoreImpCasts(); @@ -3358,9 +3600,11 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, // See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773 bool ExtraParens = false; while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { - if (!Invalid && !ExtraParens && !S.getLangOptions().CPlusPlus0x) { - S.Diag(Arg->getSourceRange().getBegin(), - diag::ext_template_arg_extra_parens) + if (!Invalid && !ExtraParens) { + S.Diag(Arg->getLocStart(), + S.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_template_arg_extra_parens : + diag::ext_template_arg_extra_parens) << Arg->getSourceRange(); ExtraParens = true; } @@ -3382,7 +3626,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, } } - if (S.getLangOptions().MicrosoftExt && isa<CXXUuidofExpr>(Arg)) { + if (S.getLangOpts().MicrosoftExt && isa<CXXUuidofExpr>(Arg)) { Converted = TemplateArgument(ArgIn); return false; } @@ -3391,62 +3635,78 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, dyn_cast<SubstNonTypeTemplateParmExpr>(Arg)) Arg = subst->getReplacement()->IgnoreImpCasts(); - DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg); - if (!DRE) { - S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref) - << Arg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); - return true; - } - // Stop checking the precise nature of the argument if it is value dependent, // it should be checked when instantiated. if (Arg->isValueDependent()) { Converted = TemplateArgument(ArgIn); return false; } + + DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg); + if (!DRE) { + S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref) + << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } if (!isa<ValueDecl>(DRE->getDecl())) { - S.Diag(Arg->getSourceRange().getBegin(), + S.Diag(Arg->getLocStart(), diag::err_template_arg_not_object_or_func_form) << Arg->getSourceRange(); S.Diag(Param->getLocation(), diag::note_template_param_here); return true; } - NamedDecl *Entity = 0; + NamedDecl *Entity = DRE->getDecl(); // Cannot refer to non-static data members - if (FieldDecl *Field = dyn_cast<FieldDecl>(DRE->getDecl())) { - S.Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_field) + if (FieldDecl *Field = dyn_cast<FieldDecl>(Entity)) { + S.Diag(Arg->getLocStart(), diag::err_template_arg_field) << Field << Arg->getSourceRange(); S.Diag(Param->getLocation(), diag::note_template_param_here); return true; } // Cannot refer to non-static member functions - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(DRE->getDecl())) + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Entity)) { if (!Method->isStatic()) { - S.Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_method) + S.Diag(Arg->getLocStart(), diag::err_template_arg_method) << Method << Arg->getSourceRange(); S.Diag(Param->getLocation(), diag::note_template_param_here); return true; } + } - // Functions must have external linkage. - if (FunctionDecl *Func = dyn_cast<FunctionDecl>(DRE->getDecl())) { - if (!isExternalLinkage(Func->getLinkage())) { - S.Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_function_not_extern) - << Func << Arg->getSourceRange(); - S.Diag(Func->getLocation(), diag::note_template_arg_internal_object) - << true; - return true; - } + FunctionDecl *Func = dyn_cast<FunctionDecl>(Entity); + VarDecl *Var = dyn_cast<VarDecl>(Entity); + + // A non-type template argument must refer to an object or function. + if (!Func && !Var) { + // We found something, but we don't know specifically what it is. + S.Diag(Arg->getLocStart(), diag::err_template_arg_not_object_or_func) + << Arg->getSourceRange(); + S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here); + return true; + } - // Okay: we've named a function with external linkage. - Entity = Func; + // Address / reference template args must have external linkage in C++98. + if (Entity->getLinkage() == InternalLinkage) { + S.Diag(Arg->getLocStart(), S.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_template_arg_object_internal : + diag::ext_template_arg_object_internal) + << !Func << Entity << Arg->getSourceRange(); + S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object) + << !Func; + } else if (Entity->getLinkage() == NoLinkage) { + S.Diag(Arg->getLocStart(), diag::err_template_arg_object_no_linkage) + << !Func << Entity << Arg->getSourceRange(); + S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object) + << !Func; + return true; + } + if (Func) { // If the template parameter has pointer type, the function decays. if (ParamType->isPointerType() && !AddressTaken) ArgType = S.Context.getPointerType(Func->getType()); @@ -3469,27 +3729,24 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, ArgType = Func->getType(); } - } else if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { - if (!isExternalLinkage(Var->getLinkage())) { - S.Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_object_not_extern) - << Var << Arg->getSourceRange(); - S.Diag(Var->getLocation(), diag::note_template_arg_internal_object) - << true; - return true; - } - + } else { // A value of reference type is not an object. if (Var->getType()->isReferenceType()) { - S.Diag(Arg->getSourceRange().getBegin(), + S.Diag(Arg->getLocStart(), diag::err_template_arg_reference_var) << Var->getType() << Arg->getSourceRange(); S.Diag(Param->getLocation(), diag::note_template_param_here); return true; } - // Okay: we've named an object with external linkage - Entity = Var; + // A template argument must have static storage duration. + // FIXME: Ensure this works for thread_local as well as __thread. + if (Var->isThreadSpecified()) { + S.Diag(Arg->getLocStart(), diag::err_template_arg_thread_local) + << Arg->getSourceRange(); + S.Diag(Var->getLocation(), diag::note_template_arg_refers_here); + return true; + } // If the template parameter has pointer type, we must have taken // the address of this object. @@ -3536,13 +3793,6 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, S.Diag(Param->getLocation(), diag::note_template_param_here); } } - } else { - // We found something else, but we don't know specifically what it is. - S.Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_not_object_or_func) - << Arg->getSourceRange(); - S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here); - return true; } bool ObjCLifetimeConversion; @@ -3568,7 +3818,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, unsigned ArgQuals = ArgType.getCVRQualifiers(); if ((ParamQuals | ArgQuals) != ParamQuals) { - S.Diag(Arg->getSourceRange().getBegin(), + S.Diag(Arg->getLocStart(), diag::err_template_arg_ref_bind_ignores_quals) << ParamType << Arg->getType() << Arg->getSourceRange(); @@ -3597,16 +3847,47 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, // Create the template argument. Converted = TemplateArgument(Entity->getCanonicalDecl()); - S.MarkDeclarationReferenced(Arg->getLocStart(), Entity); + S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity); return false; } /// \brief Checks whether the given template argument is a pointer to /// member constant according to C++ [temp.arg.nontype]p1. -bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, - TemplateArgument &Converted) { +static bool CheckTemplateArgumentPointerToMember(Sema &S, + NonTypeTemplateParmDecl *Param, + QualType ParamType, + Expr *&ResultArg, + TemplateArgument &Converted) { bool Invalid = false; + // Check for a null pointer value. + Expr *Arg = ResultArg; + switch (isNullPointerValueTemplateArgument(S, Param, ParamType, Arg)) { + case NPV_Error: + return true; + case NPV_NullPointer: + Converted = TemplateArgument((Decl *)0); + return false; + case NPV_NotNullPointer: + break; + } + + bool ObjCLifetimeConversion; + if (S.IsQualificationConversion(Arg->getType(), + ParamType.getNonReferenceType(), + false, ObjCLifetimeConversion)) { + Arg = S.ImpCastExprToType(Arg, ParamType, CK_NoOp, + Arg->getValueKind()).take(); + ResultArg = Arg; + } else if (!S.Context.hasSameUnqualifiedType(Arg->getType(), + ParamType.getNonReferenceType())) { + // We can't perform this conversion. + S.Diag(Arg->getLocStart(), diag::err_template_arg_not_convertible) + << Arg->getType() << ParamType << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + // See through any implicit casts we added to fix the type. while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg)) Arg = Cast->getSubExpr(); @@ -3623,9 +3904,11 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, // See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773 bool ExtraParens = false; while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { - if (!Invalid && !ExtraParens && !getLangOptions().CPlusPlus0x) { - Diag(Arg->getSourceRange().getBegin(), - diag::ext_template_arg_extra_parens) + if (!Invalid && !ExtraParens) { + S.Diag(Arg->getLocStart(), + S.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_template_arg_extra_parens : + diag::ext_template_arg_extra_parens) << Arg->getSourceRange(); ExtraParens = true; } @@ -3651,7 +3934,7 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, if (VD->getType()->isMemberPointerType()) { if (isa<NonTypeTemplateParmDecl>(VD) || (isa<VarDecl>(VD) && - Context.getCanonicalType(VD->getType()).isConstQualified())) { + S.Context.getCanonicalType(VD->getType()).isConstQualified())) { if (Arg->isTypeDependent() || Arg->isValueDependent()) Converted = TemplateArgument(Arg); else @@ -3665,8 +3948,8 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, } if (!DRE) - return Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_not_pointer_to_member_form) + return S.Diag(Arg->getLocStart(), + diag::err_template_arg_not_pointer_to_member_form) << Arg->getSourceRange(); if (isa<FieldDecl>(DRE->getDecl()) || isa<CXXMethodDecl>(DRE->getDecl())) { @@ -3684,11 +3967,10 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, } // We found something else, but we don't know specifically what it is. - Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_not_pointer_to_member_form) - << Arg->getSourceRange(); - Diag(DRE->getDecl()->getLocation(), - diag::note_template_arg_refers_here); + S.Diag(Arg->getLocStart(), + diag::err_template_arg_not_pointer_to_member_form) + << Arg->getSourceRange(); + S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here); return true; } @@ -3704,7 +3986,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType InstantiatedParamType, Expr *Arg, TemplateArgument &Converted, CheckTemplateArgumentKind CTAK) { - SourceLocation StartLoc = Arg->getSourceRange().getBegin(); + SourceLocation StartLoc = Arg->getLocStart(); // If either the parameter has a dependent type or the argument is // type-dependent, there's nothing we can check now. @@ -3720,13 +4002,77 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // template-argument cannot be converted to the type of the // corresponding template-parameter then the program is // ill-formed. - // - // -- for a non-type template-parameter of integral or - // enumeration type, integral promotions (4.5) and integral - // conversions (4.7) are applied. QualType ParamType = InstantiatedParamType; - QualType ArgType = Arg->getType(); if (ParamType->isIntegralOrEnumerationType()) { + // C++11: + // -- for a non-type template-parameter of integral or + // enumeration type, conversions permitted in a converted + // constant expression are applied. + // + // C++98: + // -- for a non-type template-parameter of integral or + // enumeration type, integral promotions (4.5) and integral + // conversions (4.7) are applied. + + if (CTAK == CTAK_Deduced && + !Context.hasSameUnqualifiedType(ParamType, Arg->getType())) { + // C++ [temp.deduct.type]p17: + // If, in the declaration of a function template with a non-type + // template-parameter, the non-type template-parameter is used + // in an expression in the function parameter-list and, if the + // corresponding template-argument is deduced, the + // template-argument type shall match the type of the + // template-parameter exactly, except that a template-argument + // deduced from an array bound may be of any integral type. + Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch) + << Arg->getType().getUnqualifiedType() + << ParamType.getUnqualifiedType(); + Diag(Param->getLocation(), diag::note_template_param_here); + return ExprError(); + } + + if (getLangOpts().CPlusPlus0x) { + // We can't check arbitrary value-dependent arguments. + // FIXME: If there's no viable conversion to the template parameter type, + // we should be able to diagnose that prior to instantiation. + if (Arg->isValueDependent()) { + Converted = TemplateArgument(Arg); + return Owned(Arg); + } + + // C++ [temp.arg.nontype]p1: + // A template-argument for a non-type, non-template template-parameter + // shall be one of: + // + // -- for a non-type template-parameter of integral or enumeration + // type, a converted constant expression of the type of the + // template-parameter; or + llvm::APSInt Value; + ExprResult ArgResult = + CheckConvertedConstantExpression(Arg, ParamType, Value, + CCEK_TemplateArg); + if (ArgResult.isInvalid()) + return ExprError(); + + // Widen the argument value to sizeof(parameter type). This is almost + // always a no-op, except when the parameter type is bool. In + // that case, this may extend the argument from 1 bit to 8 bits. + QualType IntegerType = ParamType; + if (const EnumType *Enum = IntegerType->getAs<EnumType>()) + IntegerType = Enum->getDecl()->getIntegerType(); + Value = Value.extOrTrunc(Context.getTypeSize(IntegerType)); + + Converted = TemplateArgument(Value, Context.getCanonicalType(ParamType)); + return ArgResult; + } + + ExprResult ArgResult = DefaultLvalueConversion(Arg); + if (ArgResult.isInvalid()) + return ExprError(); + Arg = ArgResult.take(); + + QualType ArgType = Arg->getType(); + // C++ [temp.arg.nontype]p1: // A template-argument for a non-type, non-template // template-parameter shall be one of: @@ -3737,16 +4083,16 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, SourceLocation NonConstantLoc; llvm::APSInt Value; if (!ArgType->isIntegralOrEnumerationType()) { - Diag(Arg->getSourceRange().getBegin(), + Diag(Arg->getLocStart(), diag::err_template_arg_not_integral_or_enumeral) << ArgType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); return ExprError(); - } else if (!Arg->isValueDependent() && - !Arg->isIntegerConstantExpr(Value, Context, &NonConstantLoc)) { - Diag(NonConstantLoc, diag::err_template_arg_not_ice) - << ArgType << Arg->getSourceRange(); - return ExprError(); + } else if (!Arg->isValueDependent()) { + Arg = VerifyIntegerConstantExpression(Arg, &Value, + PDiag(diag::err_template_arg_not_ice) << ArgType, false).take(); + if (!Arg) + return ExprError(); } // From here on out, all we care about are the unqualified forms @@ -3757,19 +4103,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // Try to convert the argument to the parameter's type. if (Context.hasSameType(ParamType, ArgType)) { // Okay: no conversion necessary - } else if (CTAK == CTAK_Deduced) { - // C++ [temp.deduct.type]p17: - // If, in the declaration of a function template with a non-type - // template-parameter, the non-type template- parameter is used - // in an expression in the function parameter-list and, if the - // corresponding template-argument is deduced, the - // template-argument type shall match the type of the - // template-parameter exactly, except that a template-argument - // deduced from an array bound may be of any integral type. - Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch) - << ArgType << ParamType; - Diag(Param->getLocation(), diag::note_template_param_here); - return ExprError(); } else if (ParamType->isBooleanType()) { // This is an integral-to-boolean conversion. Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean).take(); @@ -3779,7 +4112,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralCast).take(); } else { // We can't perform this conversion. - Diag(Arg->getSourceRange().getBegin(), + Diag(Arg->getLocStart(), diag::err_template_arg_not_convertible) << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); @@ -3820,7 +4153,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // Complain if an unsigned parameter received a negative value. if (IntegerType->isUnsignedIntegerOrEnumerationType() && (OldValue.isSigned() && OldValue.isNegative())) { - Diag(Arg->getSourceRange().getBegin(), diag::warn_template_arg_negative) + Diag(Arg->getLocStart(), diag::warn_template_arg_negative) << OldValue.toString(10) << Value.toString(10) << Param->getType() << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); @@ -3835,7 +4168,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, else RequiredBits = OldValue.getMinSignedBits(); if (RequiredBits > AllowedBits) { - Diag(Arg->getSourceRange().getBegin(), + Diag(Arg->getLocStart(), diag::warn_template_arg_too_large) << OldValue.toString(10) << Value.toString(10) << Param->getType() << Arg->getSourceRange(); @@ -3850,25 +4183,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return Owned(Arg); } + QualType ArgType = Arg->getType(); DeclAccessPair FoundResult; // temporary for ResolveOverloadedFunction - // C++0x [temp.arg.nontype]p5 bullets 2, 4 and 6 permit conversion - // from a template argument of type std::nullptr_t to a non-type - // template parameter of type pointer to object, pointer to - // function, or pointer-to-member, respectively. - if (ArgType->isNullPtrType()) { - if (ParamType->isPointerType() || ParamType->isMemberPointerType()) { - Converted = TemplateArgument((NamedDecl *)0); - return Owned(Arg); - } - - if (ParamType->isNullPtrType()) { - llvm::APSInt Zero(Context.getTypeSize(Context.NullPtrTy), true); - Converted = TemplateArgument(Zero, Context.NullPtrTy); - return Owned(Arg); - } - } - // Handle pointer-to-function, reference-to-function, and // pointer-to-member-function all in (roughly) the same way. if (// -- For a non-type template-parameter of type pointer to @@ -3897,7 +4214,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType, true, FoundResult)) { - if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin())) + if (DiagnoseUseOfDecl(Fn, Arg->getLocStart())) return ExprError(); Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); @@ -3914,22 +4231,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return Owned(Arg); } - bool ObjCLifetimeConversion; - if (IsQualificationConversion(ArgType, ParamType.getNonReferenceType(), - false, ObjCLifetimeConversion)) { - Arg = ImpCastExprToType(Arg, ParamType, CK_NoOp, - Arg->getValueKind()).take(); - } else if (!Context.hasSameUnqualifiedType(ArgType, - ParamType.getNonReferenceType())) { - // We can't perform this conversion. - Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_not_convertible) - << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); - return ExprError(); - } - - if (CheckTemplateArgumentPointerToMember(Arg, Converted)) + if (CheckTemplateArgumentPointerToMember(*this, Param, ParamType, Arg, + Converted)) return ExprError(); return Owned(Arg); } @@ -3964,7 +4267,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, ParamRefType->getPointeeType(), true, FoundResult)) { - if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin())) + if (DiagnoseUseOfDecl(Fn, Arg->getLocStart())) return ExprError(); Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); @@ -3980,27 +4283,35 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return Owned(Arg); } + // Deal with parameters of type std::nullptr_t. + if (ParamType->isNullPtrType()) { + if (Arg->isTypeDependent() || Arg->isValueDependent()) { + Converted = TemplateArgument(Arg); + return Owned(Arg); + } + + switch (isNullPointerValueTemplateArgument(*this, Param, ParamType, Arg)) { + case NPV_NotNullPointer: + Diag(Arg->getExprLoc(), diag::err_template_arg_not_convertible) + << Arg->getType() << ParamType; + Diag(Param->getLocation(), diag::note_template_param_here); + return ExprError(); + + case NPV_Error: + return ExprError(); + + case NPV_NullPointer: + Converted = TemplateArgument((Decl *)0); + return Owned(Arg);; + } + } + // -- For a non-type template-parameter of type pointer to data // member, qualification conversions (4.4) are applied. assert(ParamType->isMemberPointerType() && "Only pointers to members remain"); - bool ObjCLifetimeConversion; - if (Context.hasSameUnqualifiedType(ParamType, ArgType)) { - // Types match exactly: nothing more to do here. - } else if (IsQualificationConversion(ArgType, ParamType, false, - ObjCLifetimeConversion)) { - Arg = ImpCastExprToType(Arg, ParamType, CK_NoOp, - Arg->getValueKind()).take(); - } else { - // We can't perform this conversion. - Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_not_convertible) - << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); - return ExprError(); - } - - if (CheckTemplateArgumentPointerToMember(Arg, Converted)) + if (CheckTemplateArgumentPointerToMember(*this, Param, ParamType, Arg, + Converted)) return ExprError(); return Owned(Arg); } @@ -4059,6 +4370,18 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, SourceLocation Loc) { assert(Arg.getKind() == TemplateArgument::Declaration && "Only declaration template arguments permitted here"); + + // For a NULL non-type template argument, return nullptr casted to the + // parameter's type. + if (!Arg.getAsDecl()) { + return ImpCastExprToType( + new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc), + ParamType, + ParamType->getAs<MemberPointerType>() + ? CK_NullToMemberPointer + : CK_NullToPointer); + } + ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl()); if (VD->getDeclContext()->isRecord() && @@ -4426,6 +4749,9 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, /// false. Otherwise, issues a diagnostic and returns true. bool Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { + if (!S) + return false; + // Find the nearest enclosing declaration scope. while ((S->getFlags() & Scope::DeclScope) == 0 || (S->getFlags() & Scope::TemplateParamScope) != 0) @@ -4453,7 +4779,7 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { /// \brief Determine what kind of template specialization the given declaration /// is. -static TemplateSpecializationKind getTemplateSpecializationKind(NamedDecl *D) { +static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D) { if (!D) return TSK_Undeclared; @@ -4509,8 +4835,11 @@ static bool CheckTemplateSpecializationScope(Sema &S, EntityKind = 4; else if (isa<RecordDecl>(Specialized)) EntityKind = 5; + else if (isa<EnumDecl>(Specialized) && S.getLangOpts().CPlusPlus0x) + EntityKind = 6; else { - S.Diag(Loc, diag::err_template_spec_unknown_kind); + S.Diag(Loc, diag::err_template_spec_unknown_kind) + << S.getLangOpts().CPlusPlus0x; S.Diag(Specialized->getLocation(), diag::note_specialized_entity); return true; } @@ -4535,7 +4864,7 @@ static bool CheckTemplateSpecializationScope(Sema &S, } if (S.CurContext->isRecord() && !IsPartialSpecialization) { - if (S.getLangOptions().MicrosoftExt) { + if (S.getLangOpts().MicrosoftExt) { // Do not warn for class scope explicit specialization during // instantiation, warning was already emitted during pattern // semantic analysis. @@ -4549,12 +4878,21 @@ static bool CheckTemplateSpecializationScope(Sema &S, } } + if (S.CurContext->isRecord() && + !S.CurContext->Equals(Specialized->getDeclContext())) { + // Make sure that we're specializing in the right record context. + // Otherwise, things can go horribly wrong. + S.Diag(Loc, diag::err_template_spec_decl_class_scope) + << Specialized; + return true; + } + // C++ [temp.class.spec]p6: // A class template partial specialization may be declared or redeclared // in any namespace scope in which its definition may be defined (14.5.1 // and 14.5.2). bool ComplainedAboutScope = false; - DeclContext *SpecializedContext + DeclContext *SpecializedContext = Specialized->getDeclContext()->getEnclosingNamespaceContext(); DeclContext *DC = S.CurContext->getEnclosingNamespaceContext(); if ((!PrevDecl || @@ -4571,24 +4909,28 @@ static bool CheckTemplateSpecializationScope(Sema &S, // C++0x [temp.expl.spec]p2: // An explicit specialization shall be declared in a namespace enclosing // the specialized template. - if (!DC->InEnclosingNamespaceSetOf(SpecializedContext) && - !(S.getLangOptions().CPlusPlus0x && DC->Encloses(SpecializedContext))) { - bool IsCPlusPlus0xExtension - = !S.getLangOptions().CPlusPlus0x && DC->Encloses(SpecializedContext); - if (isa<TranslationUnitDecl>(SpecializedContext)) - S.Diag(Loc, IsCPlusPlus0xExtension - ? diag::ext_template_spec_decl_out_of_scope_global - : diag::err_template_spec_decl_out_of_scope_global) + if (!DC->InEnclosingNamespaceSetOf(SpecializedContext)) { + bool IsCPlusPlus0xExtension = DC->Encloses(SpecializedContext); + if (isa<TranslationUnitDecl>(SpecializedContext)) { + assert(!IsCPlusPlus0xExtension && + "DC encloses TU but isn't in enclosing namespace set"); + S.Diag(Loc, diag::err_template_spec_decl_out_of_scope_global) << EntityKind << Specialized; - else if (isa<NamespaceDecl>(SpecializedContext)) - S.Diag(Loc, IsCPlusPlus0xExtension - ? diag::ext_template_spec_decl_out_of_scope - : diag::err_template_spec_decl_out_of_scope) - << EntityKind << Specialized - << cast<NamedDecl>(SpecializedContext); + } else if (isa<NamespaceDecl>(SpecializedContext)) { + int Diag; + if (!IsCPlusPlus0xExtension) + Diag = diag::err_template_spec_decl_out_of_scope; + else if (!S.getLangOpts().CPlusPlus0x) + Diag = diag::ext_template_spec_decl_out_of_scope; + else + Diag = diag::warn_cxx98_compat_template_spec_decl_out_of_scope; + S.Diag(Loc, Diag) + << EntityKind << Specialized << cast<NamedDecl>(SpecializedContext); + } S.Diag(Specialized->getLocation(), diag::note_specialized_entity); - ComplainedAboutScope = true; + ComplainedAboutScope = + !(IsCPlusPlus0xExtension && S.getLangOpts().CPlusPlus0x); } } @@ -4718,23 +5060,6 @@ static bool CheckClassTemplatePartialSpecializationArgs(Sema &S, return false; } -/// \brief Retrieve the previous declaration of the given declaration. -static NamedDecl *getPreviousDecl(NamedDecl *ND) { - if (VarDecl *VD = dyn_cast<VarDecl>(ND)) - return VD->getPreviousDeclaration(); - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) - return FD->getPreviousDeclaration(); - if (TagDecl *TD = dyn_cast<TagDecl>(ND)) - return TD->getPreviousDeclaration(); - if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(ND)) - return TD->getPreviousDeclaration(); - if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND)) - return FTD->getPreviousDeclaration(); - if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(ND)) - return CTD->getPreviousDeclaration(); - return 0; -} - DeclResult Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK, @@ -4875,9 +5200,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TemplateArgs, false, Converted)) return true; - assert((Converted.size() == ClassTemplate->getTemplateParameters()->size()) && - "Converted template argument list is too short!"); - // Find the class template (partial) specialization declaration that // corresponds to these arguments. if (isPartialSpecialization) { @@ -5005,17 +5327,13 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // partial specialization are deducible from the template // arguments. If not, this class template partial specialization // will never be used. - SmallVector<bool, 8> DeducibleParams; - DeducibleParams.resize(TemplateParams->size()); + llvm::SmallBitVector DeducibleParams(TemplateParams->size()); MarkUsedTemplateParameters(Partial->getTemplateArgs(), true, TemplateParams->getDepth(), DeducibleParams); - unsigned NumNonDeducible = 0; - for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) - if (!DeducibleParams[I]) - ++NumNonDeducible; - if (NumNonDeducible) { + if (!DeducibleParams.all()) { + unsigned NumNonDeducible = DeducibleParams.size()-DeducibleParams.count(); Diag(TemplateNameLoc, diag::warn_partial_specs_not_deducible) << (NumNonDeducible > 1) << SourceRange(TemplateNameLoc, RAngleLoc); @@ -5065,7 +5383,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // use occurs; no diagnostic is required. if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) { bool Okay = false; - for (NamedDecl *Prev = PrevDecl; Prev; Prev = getPreviousDecl(Prev)) { + for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) { // Is there any previous explicit specialization declaration? if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) { Okay = true; @@ -5174,7 +5492,7 @@ Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, Scope *ParentScope = FnBodyScope->getParent(); - D.setFunctionDefinition(true); + D.setFunctionDefinitionKind(FDK_Definition); Decl *DP = HandleDeclarator(ParentScope, D, move(TemplateParameterLists)); if (FunctionTemplateDecl *FunctionTemplate @@ -5189,6 +5507,7 @@ Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, /// \brief Strips various properties off an implicit instantiation /// that has just been explicitly specialized. static void StripImplicitInstantiation(NamedDecl *D) { + // FIXME: "make check" is clean if the call to dropAttrs() is commented out. D->dropAttrs(); if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { @@ -5196,6 +5515,23 @@ static void StripImplicitInstantiation(NamedDecl *D) { } } +/// \brief Compute the diagnostic location for an explicit instantiation +// declaration or definition. +static SourceLocation DiagLocForExplicitInstantiation( + NamedDecl* D, SourceLocation PointOfInstantiation) { + // Explicit instantiations following a specialization have no effect and + // hence no PointOfInstantiation. In that case, walk decl backwards + // until a valid name loc is found. + SourceLocation PrevDiagLoc = PointOfInstantiation; + for (Decl *Prev = D; Prev && !PrevDiagLoc.isValid(); + Prev = Prev->getPreviousDecl()) { + PrevDiagLoc = Prev->getLocation(); + } + assert(PrevDiagLoc.isValid() && + "Explicit instantiation without point of instantiation?"); + return PrevDiagLoc; +} + /// \brief Diagnose cases where we have an explicit template specialization /// before/after an explicit template instantiation, producing diagnostics /// for those cases where they are required and determining whether the @@ -5262,7 +5598,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, // before the first use of that specialization that would cause an // implicit instantiation to take place, in every translation unit in // which such a use occurs; no diagnostic is required. - for (NamedDecl *Prev = PrevDecl; Prev; Prev = getPreviousDecl(Prev)) { + for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) { // Is there any previous explicit specialization declaration? if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) return false; @@ -5275,7 +5611,6 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, return true; } - break; case TSK_ExplicitInstantiationDeclaration: switch (PrevTSK) { @@ -5306,14 +5641,15 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, // translation unit, the definition shall follow the declaration. Diag(NewLoc, diag::err_explicit_instantiation_declaration_after_definition); - Diag(PrevPointOfInstantiation, + + // Explicit instantiations following a specialization have no effect and + // hence no PrevPointOfInstantiation. In that case, walk decl backwards + // until a valid name loc is found. + Diag(DiagLocForExplicitInstantiation(PrevDecl, PrevPointOfInstantiation), diag::note_explicit_instantiation_definition_here); - assert(PrevPointOfInstantiation.isValid() && - "Explicit instantiation without point of instantiation?"); HasNoEffect = true; return false; } - break; case TSK_ExplicitInstantiationDefinition: switch (PrevTSK) { @@ -5333,18 +5669,32 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, // In C++98/03 mode, we only give an extension warning here, because it // is not harmful to try to explicitly instantiate something that // has been explicitly specialized. - if (!getLangOptions().CPlusPlus0x) { - Diag(NewLoc, diag::ext_explicit_instantiation_after_specialization) - << PrevDecl; - Diag(PrevDecl->getLocation(), - diag::note_previous_template_specialization); - } + Diag(NewLoc, getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_explicit_instantiation_after_specialization : + diag::ext_explicit_instantiation_after_specialization) + << PrevDecl; + Diag(PrevDecl->getLocation(), + diag::note_previous_template_specialization); HasNoEffect = true; return false; case TSK_ExplicitInstantiationDeclaration: // We're explicity instantiating a definition for something for which we // were previously asked to suppress instantiations. That's fine. + + // C++0x [temp.explicit]p4: + // For a given set of template parameters, if an explicit instantiation + // of a template appears after a declaration of an explicit + // specialization for that template, the explicit instantiation has no + // effect. + for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) { + // Is there any previous explicit specialization declaration? + if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) { + HasNoEffect = true; + break; + } + } + return false; case TSK_ExplicitInstantiationDefinition: @@ -5354,12 +5704,11 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, // in a program, Diag(NewLoc, diag::err_explicit_instantiation_duplicate) << PrevDecl; - Diag(PrevPointOfInstantiation, + Diag(DiagLocForExplicitInstantiation(PrevDecl, PrevPointOfInstantiation), diag::note_previous_explicit_instantiation); HasNoEffect = true; return false; } - break; } llvm_unreachable("Missing specialization/instantiation case?"); @@ -5486,8 +5835,13 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, // Note: do not overwrite location info if previous template // specialization kind was explicit. TemplateSpecializationKind TSK = SpecInfo->getTemplateSpecializationKind(); - if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation) + if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation) { Specialization->setLocation(FD->getLocation()); + // C++11 [dcl.constexpr]p1: An explicit specialization of a constexpr + // function can differ from the template declaration with respect to + // the constexpr specifier. + Specialization->setConstexpr(FD->isConstexpr()); + } // FIXME: Check if the prior specialization has a point of instantiation. // If so, we have run afoul of . @@ -5601,6 +5955,14 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass(); MSInfo = PrevRecord->getMemberSpecializationInfo(); } + } else if (isa<EnumDecl>(Member)) { + EnumDecl *PrevEnum; + if (Previous.isSingleResult() && + (PrevEnum = dyn_cast<EnumDecl>(Previous.getFoundDecl()))) { + Instantiation = PrevEnum; + InstantiatedFrom = PrevEnum->getInstantiatedFromMemberEnum(); + MSInfo = PrevEnum->getMemberSpecializationInfo(); + } } if (!Instantiation) { @@ -5639,7 +6001,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { // C++ [temp.expl.spec]p6: // If a template, a member template or the member of a class template is - // explicitly specialized then that spe- cialization shall be declared + // explicitly specialized then that specialization shall be declared // before the first use of that specialization that would cause an implicit // instantiation to take place, in every translation unit in which such a // use occurs; no diagnostic is required. @@ -5691,8 +6053,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { cast<VarDecl>(InstantiatedFrom), TSK_ExplicitSpecialization); MarkUnusedFileScopedDecl(InstantiationVar); - } else { - assert(isa<CXXRecordDecl>(Member) && "Only member classes remain"); + } else if (isa<CXXRecordDecl>(Member)) { CXXRecordDecl *InstantiationClass = cast<CXXRecordDecl>(Instantiation); if (InstantiationClass->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) { @@ -5704,6 +6065,18 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass( cast<CXXRecordDecl>(InstantiatedFrom), TSK_ExplicitSpecialization); + } else { + assert(isa<EnumDecl>(Member) && "Only member enums remain"); + EnumDecl *InstantiationEnum = cast<EnumDecl>(Instantiation); + if (InstantiationEnum->getTemplateSpecializationKind() == + TSK_ImplicitInstantiation) { + InstantiationEnum->setTemplateSpecializationKind( + TSK_ExplicitSpecialization); + InstantiationEnum->setLocation(Member->getLocation()); + } + + cast<EnumDecl>(Member)->setInstantiationOfMemberEnum( + cast<EnumDecl>(InstantiatedFrom), TSK_ExplicitSpecialization); } // Save the caller the trouble of having to figure out which declaration @@ -5728,45 +6101,41 @@ static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D, return true; } - // C++0x [temp.explicit]p2: + // C++11 [temp.explicit]p3: // An explicit instantiation shall appear in an enclosing namespace of its - // template. + // template. If the name declared in the explicit instantiation is an + // unqualified name, the explicit instantiation shall appear in the + // namespace where its template is declared or, if that namespace is inline + // (7.3.1), any namespace from its enclosing namespace set. // // This is DR275, which we do not retroactively apply to C++98/03. - if (S.getLangOptions().CPlusPlus0x && - !CurContext->Encloses(OrigContext)) { - if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(OrigContext)) + if (WasQualifiedName) { + if (CurContext->Encloses(OrigContext)) + return false; + } else { + if (CurContext->InEnclosingNamespaceSetOf(OrigContext)) + return false; + } + + if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(OrigContext)) { + if (WasQualifiedName) S.Diag(InstLoc, - S.getLangOptions().CPlusPlus0x? - diag::err_explicit_instantiation_out_of_scope - : diag::warn_explicit_instantiation_out_of_scope_0x) + S.getLangOpts().CPlusPlus0x? + diag::err_explicit_instantiation_out_of_scope : + diag::warn_explicit_instantiation_out_of_scope_0x) << D << NS; else S.Diag(InstLoc, - S.getLangOptions().CPlusPlus0x? - diag::err_explicit_instantiation_must_be_global - : diag::warn_explicit_instantiation_out_of_scope_0x) - << D; - S.Diag(D->getLocation(), diag::note_explicit_instantiation_here); - return false; - } - - // C++0x [temp.explicit]p2: - // If the name declared in the explicit instantiation is an unqualified - // name, the explicit instantiation shall appear in the namespace where - // its template is declared or, if that namespace is inline (7.3.1), any - // namespace from its enclosing namespace set. - if (WasQualifiedName) - return false; - - if (CurContext->InEnclosingNamespaceSetOf(OrigContext)) - return false; - - S.Diag(InstLoc, - S.getLangOptions().CPlusPlus0x? - diag::err_explicit_instantiation_unqualified_wrong_namespace - : diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x) - << D << OrigContext; + S.getLangOpts().CPlusPlus0x? + diag::err_explicit_instantiation_unqualified_wrong_namespace : + diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x) + << D << NS; + } else + S.Diag(InstLoc, + S.getLangOpts().CPlusPlus0x? + diag::err_explicit_instantiation_must_be_global : + diag::warn_explicit_instantiation_must_be_global_0x) + << D; S.Diag(D->getLocation(), diag::note_explicit_instantiation_here); return false; } @@ -5776,7 +6145,7 @@ static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) { if (!SS.isSet()) return false; - // C++0x [temp.explicit]p2: + // C++11 [temp.explicit]p3: // If the explicit instantiation is for a member function, a member class // or a static data member of a class template specialization, the name of // the class template specialization in the qualified-id for the member @@ -5847,9 +6216,6 @@ Sema::ActOnExplicitInstantiation(Scope *S, TemplateArgs, false, Converted)) return true; - assert((Converted.size() == ClassTemplate->getTemplateParameters()->size()) && - "Converted template argument list is too short!"); - // Find the class template specialization declaration that // corresponds to these arguments. void *InsertPos = 0; @@ -5932,6 +6298,9 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization->setExternLoc(ExternLoc); Specialization->setTemplateKeywordLoc(TemplateLoc); + if (Attr) + ProcessDeclAttributeList(S, Specialization, Attr); + // Add the explicit instantiation into its lexical context. However, // since explicit instantiations are never found by name lookup, we // just put it into the declaration context directly. @@ -6000,7 +6369,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, KWLoc, SS, Name, NameLoc, Attr, AS_none, /*ModulePrivateLoc=*/SourceLocation(), MultiTemplateParamsArg(*this, 0, 0), - Owned, IsDependent, false, false, + Owned, IsDependent, SourceLocation(), false, TypeResult()); assert(!IsDependent && "explicit instantiation of dependent name not yet handled"); @@ -6008,11 +6377,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, return true; TagDecl *Tag = cast<TagDecl>(TagD); - if (Tag->isEnum()) { - Diag(TemplateLoc, diag::err_explicit_instantiation_enum) - << Context.getTypeDeclType(Tag); - return true; - } + assert(!Tag->isEnum() && "shouldn't see enumerations here"); if (Tag->isInvalidDecl()) return true; @@ -6053,7 +6418,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, // Verify that it is okay to explicitly instantiate here. CXXRecordDecl *PrevDecl - = cast_or_null<CXXRecordDecl>(Record->getPreviousDeclaration()); + = cast_or_null<CXXRecordDecl>(Record->getPreviousDecl()); if (!PrevDecl && Record->getDefinition()) PrevDecl = Record; if (PrevDecl) { @@ -6120,7 +6485,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, DeclarationName Name = NameInfo.getName(); if (!Name) { if (!D.isInvalidType()) - Diag(D.getDeclSpec().getSourceRange().getBegin(), + Diag(D.getDeclSpec().getLocStart(), diag::err_explicit_instantiation_requires_name) << D.getDeclSpec().getSourceRange() << D.getSourceRange(); @@ -6161,9 +6526,11 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // inline or constexpr specifiers. // Presumably, this also applies to member functions of class templates as // well. - if (D.getDeclSpec().isInlineSpecified() && getLangOptions().CPlusPlus0x) + if (D.getDeclSpec().isInlineSpecified()) Diag(D.getDeclSpec().getInlineSpecLoc(), - diag::err_explicit_instantiation_inline) + getLangOpts().CPlusPlus0x ? + diag::err_explicit_instantiation_inline : + diag::warn_explicit_instantiation_inline_0x) << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc()); if (D.getDeclSpec().isConstexprSpecified()) // FIXME: Add a fix-it to remove the 'constexpr' and add a 'const' if one is @@ -6326,7 +6693,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, return true; } - FunctionDecl *PrevDecl = Specialization->getPreviousDeclaration(); + FunctionDecl *PrevDecl = Specialization->getPreviousDecl(); if (!PrevDecl && Specialization->isThisDeclarationADefinition()) PrevDecl = Specialization; @@ -6346,6 +6713,9 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, } Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); + AttributeList *Attr = D.getDeclSpec().getAttributes().getList(); + if (Attr) + ProcessDeclAttributeList(S, Specialization, Attr); if (TSK == TSK_ExplicitInstantiationDefinition) InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization); @@ -6402,7 +6772,7 @@ Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // Create type-source location information for this type. TypeLocBuilder TLB; DependentNameTypeLoc TL = TLB.push<DependentNameTypeLoc>(Result); - TL.setKeywordLoc(TagLoc); + TL.setElaboratedKeywordLoc(TagLoc); TL.setQualifierLoc(SS.getWithLocInContext(Context)); TL.setNameLoc(NameLoc); return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); @@ -6415,9 +6785,11 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, if (SS.isInvalid()) return true; - if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() && - !getLangOptions().CPlusPlus0x) - Diag(TypenameLoc, diag::ext_typename_outside_of_template) + if (TypenameLoc.isValid() && S && !S->getTemplateParamParent()) + Diag(TypenameLoc, + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_typename_outside_of_template : + diag::ext_typename_outside_of_template) << FixItHint::CreateRemoval(TypenameLoc); NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); @@ -6429,12 +6801,12 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); if (isa<DependentNameType>(T)) { DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); - TL.setKeywordLoc(TypenameLoc); + TL.setElaboratedKeywordLoc(TypenameLoc); TL.setQualifierLoc(QualifierLoc); TL.setNameLoc(IdLoc); } else { ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc()); - TL.setKeywordLoc(TypenameLoc); + TL.setElaboratedKeywordLoc(TypenameLoc); TL.setQualifierLoc(QualifierLoc); cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(IdLoc); } @@ -6443,18 +6815,21 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, } TypeResult -Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, - const CXXScopeSpec &SS, - SourceLocation TemplateLoc, +Sema::ActOnTypenameType(Scope *S, + SourceLocation TypenameLoc, + const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, TemplateTy TemplateIn, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, SourceLocation RAngleLoc) { - if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() && - !getLangOptions().CPlusPlus0x) - Diag(TypenameLoc, diag::ext_typename_outside_of_template) - << FixItHint::CreateRemoval(TypenameLoc); + if (TypenameLoc.isValid() && S && !S->getTemplateParamParent()) + Diag(TypenameLoc, + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_typename_outside_of_template : + diag::ext_typename_outside_of_template) + << FixItHint::CreateRemoval(TypenameLoc); // Translate the parser's template argument list in our AST format. TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); @@ -6475,11 +6850,12 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, TypeLocBuilder Builder; DependentTemplateSpecializationTypeLoc SpecTL = Builder.push<DependentTemplateSpecializationTypeLoc>(T); + SpecTL.setElaboratedKeywordLoc(TypenameLoc); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + SpecTL.setTemplateKeywordLoc(TemplateKWLoc); + SpecTL.setTemplateNameLoc(TemplateNameLoc); SpecTL.setLAngleLoc(LAngleLoc); SpecTL.setRAngleLoc(RAngleLoc); - SpecTL.setKeywordLoc(TypenameLoc); - SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); - SpecTL.setNameLoc(TemplateNameLoc); for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); @@ -6489,22 +6865,20 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, if (T.isNull()) return true; - // Provide source-location information for the template specialization - // type. + // Provide source-location information for the template specialization type. TypeLocBuilder Builder; - TemplateSpecializationTypeLoc SpecTL + TemplateSpecializationTypeLoc SpecTL = Builder.push<TemplateSpecializationTypeLoc>(T); - - // FIXME: No place to set the location of the 'template' keyword! + SpecTL.setTemplateKeywordLoc(TemplateKWLoc); + SpecTL.setTemplateNameLoc(TemplateNameLoc); SpecTL.setLAngleLoc(LAngleLoc); SpecTL.setRAngleLoc(RAngleLoc); - SpecTL.setTemplateNameLoc(TemplateNameLoc); for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); T = Context.getElaboratedType(ETK_Typename, SS.getScopeRep(), T); ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T); - TL.setKeywordLoc(TypenameLoc); + TL.setElaboratedKeywordLoc(TypenameLoc); TL.setQualifierLoc(SS.getWithLocInContext(Context)); TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T); @@ -6588,10 +6962,6 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, Referenced = Result.getFoundDecl(); break; - - llvm_unreachable("unresolved using decl in non-dependent context"); - return QualType(); - case LookupResult::FoundOverloaded: DiagID = diag::err_typename_nested_not_type; Referenced = *Result.begin(); @@ -6650,6 +7020,11 @@ namespace { this->Loc = Loc; this->Entity = Entity; } + + ExprResult TransformLambdaExpr(LambdaExpr *E) { + // Lambdas never need to be transformed. + return E; + } }; } @@ -6762,7 +7137,7 @@ std::string Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgument *Args, unsigned NumArgs) { - llvm::SmallString<128> Str; + SmallString<128> Str; llvm::raw_svector_ostream Out(Str); if (!Params || Params->size() == 0 || NumArgs == 0) diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp index 93ea89d..2ea1e6f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -20,7 +20,7 @@ #include "clang/AST/StmtVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" -#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallBitVector.h" #include "TreeTransform.h" #include <algorithm> @@ -112,15 +112,16 @@ struct RefParamPartialOrderingComparison { static Sema::TemplateDeductionResult -DeduceTemplateArguments(Sema &S, - TemplateParameterList *TemplateParams, - QualType Param, - QualType Arg, - TemplateDeductionInfo &Info, - SmallVectorImpl<DeducedTemplateArgument> &Deduced, - unsigned TDF, - bool PartialOrdering = false, - SmallVectorImpl<RefParamPartialOrderingComparison> * +DeduceTemplateArgumentsByTypeMatch(Sema &S, + TemplateParameterList *TemplateParams, + QualType Param, + QualType Arg, + TemplateDeductionInfo &Info, + SmallVectorImpl<DeducedTemplateArgument> & + Deduced, + unsigned TDF, + bool PartialOrdering = false, + SmallVectorImpl<RefParamPartialOrderingComparison> * RefParamComparisons = 0); static Sema::TemplateDeductionResult @@ -277,7 +278,7 @@ checkDeducedTemplateArguments(ASTContext &Context, return X; } - return DeducedTemplateArgument(); + llvm_unreachable("Invalid TemplateArgument Kind!"); } /// \brief Deduce the value of the given non-type template parameter @@ -547,7 +548,7 @@ static TemplateParameter makeTemplateParameter(Decl *D) { /// arguments in a set of argument packs. static void PrepareArgumentPackDeduction(Sema &S, SmallVectorImpl<DeducedTemplateArgument> &Deduced, - const SmallVectorImpl<unsigned> &PackIndices, + ArrayRef<unsigned> PackIndices, SmallVectorImpl<DeducedTemplateArgument> &SavedPacks, SmallVectorImpl< SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks) { @@ -582,7 +583,7 @@ FinishArgumentPackDeduction(Sema &S, TemplateParameterList *TemplateParams, bool HasAnyArguments, SmallVectorImpl<DeducedTemplateArgument> &Deduced, - const SmallVectorImpl<unsigned> &PackIndices, + ArrayRef<unsigned> PackIndices, SmallVectorImpl<DeducedTemplateArgument> &SavedPacks, SmallVectorImpl< SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks, @@ -705,12 +706,11 @@ DeduceTemplateArguments(Sema &S, } if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(S, TemplateParams, - Params[ParamIdx], - Args[ArgIdx], - Info, Deduced, TDF, - PartialOrdering, - RefParamComparisons)) + = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + Params[ParamIdx], Args[ArgIdx], + Info, Deduced, TDF, + PartialOrdering, + RefParamComparisons)) return Result; ++ArgIdx; @@ -736,7 +736,7 @@ DeduceTemplateArguments(Sema &S, SmallVector<unsigned, 2> PackIndices; QualType Pattern = Expansion->getPattern(); { - llvm::BitVector SawIndices(TemplateParams->size()); + llvm::SmallBitVector SawIndices(TemplateParams->size()); SmallVector<UnexpandedParameterPack, 2> Unexpanded; S.collectUnexpandedParameterPacks(Pattern, Unexpanded); for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { @@ -766,9 +766,10 @@ DeduceTemplateArguments(Sema &S, // Deduce template arguments from the pattern. if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx], - Info, Deduced, TDF, PartialOrdering, - RefParamComparisons)) + = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern, + Args[ArgIdx], Info, Deduced, + TDF, PartialOrdering, + RefParamComparisons)) return Result; // Capture the deduced template arguments for each parameter pack expanded @@ -858,14 +859,15 @@ static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType, /// "success" result means that template argument deduction has not yet failed, /// but it may still fail, later, for other reasons. static Sema::TemplateDeductionResult -DeduceTemplateArguments(Sema &S, - TemplateParameterList *TemplateParams, - QualType ParamIn, QualType ArgIn, - TemplateDeductionInfo &Info, - SmallVectorImpl<DeducedTemplateArgument> &Deduced, - unsigned TDF, - bool PartialOrdering, - SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) { +DeduceTemplateArgumentsByTypeMatch(Sema &S, + TemplateParameterList *TemplateParams, + QualType ParamIn, QualType ArgIn, + TemplateDeductionInfo &Info, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + unsigned TDF, + bool PartialOrdering, + SmallVectorImpl<RefParamPartialOrderingComparison> * + RefParamComparisons) { // We only want to look at the canonical types, since typedefs and // sugar are not part of template argument deduction. QualType Param = S.Context.getCanonicalType(ParamIn); @@ -960,14 +962,6 @@ DeduceTemplateArguments(Sema &S, } } - // If the parameter type is not dependent, there is nothing to deduce. - if (!Param->isDependentType()) { - if (!(TDF & TDF_SkipNonDependent) && Param != Arg) - return Sema::TDK_NonDeducedMismatch; - - return Sema::TDK_Success; - } - // C++ [temp.deduct.type]p9: // A template type argument T, a template template argument TT or a // template non-type argument i can be deduced if P and A have one of @@ -1035,7 +1029,7 @@ DeduceTemplateArguments(Sema &S, // Objective-C ARC: // If template deduction would produce an argument type with lifetime type // but no lifetime qualifier, the __strong lifetime qualifier is inferred. - if (S.getLangOptions().ObjCAutoRefCount && + if (S.getLangOpts().ObjCAutoRefCount && DeducedType->isObjCLifetimeType() && !DeducedQs.hasObjCLifetime()) DeducedQs.setObjCLifetime(Qualifiers::OCL_Strong); @@ -1081,6 +1075,17 @@ DeduceTemplateArguments(Sema &S, if (Param.getCVRQualifiers() != Arg.getCVRQualifiers()) return Sema::TDK_NonDeducedMismatch; } + + // If the parameter type is not dependent, there is nothing to deduce. + if (!Param->isDependentType()) { + if (!(TDF & TDF_SkipNonDependent) && Param != Arg) + return Sema::TDK_NonDeducedMismatch; + + return Sema::TDK_Success; + } + } else if (!Param->isDependentType() && + Param.getUnqualifiedType() == Arg.getUnqualifiedType()) { + return Sema::TDK_Success; } switch (Param->getTypeClass()) { @@ -1093,9 +1098,9 @@ DeduceTemplateArguments(Sema &S, case Type::TemplateTypeParm: case Type::SubstTemplateTypeParmPack: llvm_unreachable("Type nodes handled above"); - - // These types cannot be used in templates or cannot be dependent, so - // deduction always fails. + + // These types cannot be dependent, so simply check whether the types are + // the same. case Type::Builtin: case Type::VariableArray: case Type::Vector: @@ -1104,23 +1109,32 @@ DeduceTemplateArguments(Sema &S, case Type::Enum: case Type::ObjCObject: case Type::ObjCInterface: - case Type::ObjCObjectPointer: - return Sema::TDK_NonDeducedMismatch; - + case Type::ObjCObjectPointer: { + if (TDF & TDF_SkipNonDependent) + return Sema::TDK_Success; + + if (TDF & TDF_IgnoreQualifiers) { + Param = Param.getUnqualifiedType(); + Arg = Arg.getUnqualifiedType(); + } + + return Param == Arg? Sema::TDK_Success : Sema::TDK_NonDeducedMismatch; + } + // _Complex T [placeholder extension] case Type::Complex: if (const ComplexType *ComplexArg = Arg->getAs<ComplexType>()) - return DeduceTemplateArguments(S, TemplateParams, + return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, cast<ComplexType>(Param)->getElementType(), - ComplexArg->getElementType(), - Info, Deduced, TDF); + ComplexArg->getElementType(), + Info, Deduced, TDF); return Sema::TDK_NonDeducedMismatch; // _Atomic T [extension] case Type::Atomic: if (const AtomicType *AtomicArg = Arg->getAs<AtomicType>()) - return DeduceTemplateArguments(S, TemplateParams, + return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, cast<AtomicType>(Param)->getValueType(), AtomicArg->getValueType(), Info, Deduced, TDF); @@ -1140,8 +1154,8 @@ DeduceTemplateArguments(Sema &S, } unsigned SubTDF = TDF & (TDF_IgnoreQualifiers | TDF_DerivedClass); - return DeduceTemplateArguments(S, TemplateParams, - cast<PointerType>(Param)->getPointeeType(), + return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + cast<PointerType>(Param)->getPointeeType(), PointeeType, Info, Deduced, SubTDF); } @@ -1152,10 +1166,9 @@ DeduceTemplateArguments(Sema &S, if (!ReferenceArg) return Sema::TDK_NonDeducedMismatch; - return DeduceTemplateArguments(S, TemplateParams, + return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, cast<LValueReferenceType>(Param)->getPointeeType(), - ReferenceArg->getPointeeType(), - Info, Deduced, 0); + ReferenceArg->getPointeeType(), Info, Deduced, 0); } // T && [C++0x] @@ -1164,10 +1177,10 @@ DeduceTemplateArguments(Sema &S, if (!ReferenceArg) return Sema::TDK_NonDeducedMismatch; - return DeduceTemplateArguments(S, TemplateParams, - cast<RValueReferenceType>(Param)->getPointeeType(), - ReferenceArg->getPointeeType(), - Info, Deduced, 0); + return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + cast<RValueReferenceType>(Param)->getPointeeType(), + ReferenceArg->getPointeeType(), + Info, Deduced, 0); } // T [] (implied, but not stated explicitly) @@ -1178,10 +1191,10 @@ DeduceTemplateArguments(Sema &S, return Sema::TDK_NonDeducedMismatch; unsigned SubTDF = TDF & TDF_IgnoreQualifiers; - return DeduceTemplateArguments(S, TemplateParams, - S.Context.getAsIncompleteArrayType(Param)->getElementType(), - IncompleteArrayArg->getElementType(), - Info, Deduced, SubTDF); + return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + S.Context.getAsIncompleteArrayType(Param)->getElementType(), + IncompleteArrayArg->getElementType(), + Info, Deduced, SubTDF); } // T [integer-constant] @@ -1197,10 +1210,10 @@ DeduceTemplateArguments(Sema &S, return Sema::TDK_NonDeducedMismatch; unsigned SubTDF = TDF & TDF_IgnoreQualifiers; - return DeduceTemplateArguments(S, TemplateParams, - ConstantArrayParm->getElementType(), - ConstantArrayArg->getElementType(), - Info, Deduced, SubTDF); + return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + ConstantArrayParm->getElementType(), + ConstantArrayArg->getElementType(), + Info, Deduced, SubTDF); } // type [i] @@ -1215,10 +1228,10 @@ DeduceTemplateArguments(Sema &S, const DependentSizedArrayType *DependentArrayParm = S.Context.getAsDependentSizedArrayType(Param); if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(S, TemplateParams, - DependentArrayParm->getElementType(), - ArrayArg->getElementType(), - Info, Deduced, SubTDF)) + = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + DependentArrayParm->getElementType(), + ArrayArg->getElementType(), + Info, Deduced, SubTDF)) return Result; // Determine the array bound is something we can deduce. @@ -1272,10 +1285,10 @@ DeduceTemplateArguments(Sema &S, // Check return types. if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(S, TemplateParams, - FunctionProtoParam->getResultType(), - FunctionProtoArg->getResultType(), - Info, Deduced, 0)) + = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + FunctionProtoParam->getResultType(), + FunctionProtoArg->getResultType(), + Info, Deduced, 0)) return Result; return DeduceTemplateArguments(S, TemplateParams, @@ -1334,8 +1347,8 @@ DeduceTemplateArguments(Sema &S, SmallVector<const RecordType *, 8> ToVisit; ToVisit.push_back(RecordT); bool Successful = false; - SmallVectorImpl<DeducedTemplateArgument> DeducedOrig(0); - DeducedOrig = Deduced; + SmallVector<DeducedTemplateArgument, 8> DeducedOrig(Deduced.begin(), + Deduced.end()); while (!ToVisit.empty()) { // Retrieve the next class in the inheritance hierarchy. const RecordType *NextT = ToVisit.back(); @@ -1357,7 +1370,8 @@ DeduceTemplateArguments(Sema &S, // from this base class. if (BaseResult == Sema::TDK_Success) { Successful = true; - DeducedOrig = Deduced; + DeducedOrig.clear(); + DeducedOrig.append(Deduced.begin(), Deduced.end()); } else Deduced = DeducedOrig; @@ -1399,17 +1413,18 @@ DeduceTemplateArguments(Sema &S, return Sema::TDK_NonDeducedMismatch; if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(S, TemplateParams, - MemPtrParam->getPointeeType(), - MemPtrArg->getPointeeType(), - Info, Deduced, - TDF & TDF_IgnoreQualifiers)) + = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + MemPtrParam->getPointeeType(), + MemPtrArg->getPointeeType(), + Info, Deduced, + TDF & TDF_IgnoreQualifiers)) return Result; - return DeduceTemplateArguments(S, TemplateParams, - QualType(MemPtrParam->getClass(), 0), - QualType(MemPtrArg->getClass(), 0), - Info, Deduced, 0); + return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + QualType(MemPtrParam->getClass(), 0), + QualType(MemPtrArg->getClass(), 0), + Info, Deduced, + TDF & TDF_IgnoreQualifiers); } // (clang extension) @@ -1424,10 +1439,10 @@ DeduceTemplateArguments(Sema &S, if (!BlockPtrArg) return Sema::TDK_NonDeducedMismatch; - return DeduceTemplateArguments(S, TemplateParams, - BlockPtrParam->getPointeeType(), - BlockPtrArg->getPointeeType(), Info, - Deduced, 0); + return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + BlockPtrParam->getPointeeType(), + BlockPtrArg->getPointeeType(), + Info, Deduced, 0); } // (clang extension) @@ -1441,11 +1456,10 @@ DeduceTemplateArguments(Sema &S, return Sema::TDK_NonDeducedMismatch; // Perform deduction on the element types. - return DeduceTemplateArguments(S, TemplateParams, - VectorParam->getElementType(), - VectorArg->getElementType(), - Info, Deduced, - TDF); + return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + VectorParam->getElementType(), + VectorArg->getElementType(), + Info, Deduced, TDF); } if (const DependentSizedExtVectorType *VectorArg @@ -1455,11 +1469,10 @@ DeduceTemplateArguments(Sema &S, // ordering. // Perform deduction on the element types. - return DeduceTemplateArguments(S, TemplateParams, - VectorParam->getElementType(), - VectorArg->getElementType(), - Info, Deduced, - TDF); + return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + VectorParam->getElementType(), + VectorArg->getElementType(), + Info, Deduced, TDF); } return Sema::TDK_NonDeducedMismatch; @@ -1475,11 +1488,10 @@ DeduceTemplateArguments(Sema &S, if (const ExtVectorType *VectorArg = dyn_cast<ExtVectorType>(Arg)) { // Perform deduction on the element types. if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(S, TemplateParams, - VectorParam->getElementType(), - VectorArg->getElementType(), - Info, Deduced, - TDF)) + = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + VectorParam->getElementType(), + VectorArg->getElementType(), + Info, Deduced, TDF)) return Result; // Perform deduction on the vector size, if we can. @@ -1498,11 +1510,10 @@ DeduceTemplateArguments(Sema &S, = dyn_cast<DependentSizedExtVectorType>(Arg)) { // Perform deduction on the element types. if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(S, TemplateParams, - VectorParam->getElementType(), - VectorArg->getElementType(), - Info, Deduced, - TDF)) + = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + VectorParam->getElementType(), + VectorArg->getElementType(), + Info, Deduced, TDF)) return Result; // Perform deduction on the vector size, if we can. @@ -1531,7 +1542,7 @@ DeduceTemplateArguments(Sema &S, return Sema::TDK_Success; } - return Sema::TDK_Success; + llvm_unreachable("Invalid Type Class!"); } static Sema::TemplateDeductionResult @@ -1553,8 +1564,10 @@ DeduceTemplateArguments(Sema &S, case TemplateArgument::Type: if (Arg.getKind() == TemplateArgument::Type) - return DeduceTemplateArguments(S, TemplateParams, Param.getAsType(), - Arg.getAsType(), Info, Deduced, 0); + return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + Param.getAsType(), + Arg.getAsType(), + Info, Deduced, 0); Info.FirstArg = Param; Info.SecondArg = Arg; return Sema::TDK_NonDeducedMismatch; @@ -1570,12 +1583,10 @@ DeduceTemplateArguments(Sema &S, case TemplateArgument::TemplateExpansion: llvm_unreachable("caller should handle pack expansions"); - break; case TemplateArgument::Declaration: if (Arg.getKind() == TemplateArgument::Declaration && - Param.getAsDecl()->getCanonicalDecl() == - Arg.getAsDecl()->getCanonicalDecl()) + isSameDeclaration(Param.getAsDecl(), Arg.getAsDecl())) return Sema::TDK_Success; Info.FirstArg = Param; @@ -1630,7 +1641,7 @@ DeduceTemplateArguments(Sema &S, llvm_unreachable("Argument packs should be expanded by the caller!"); } - return Sema::TDK_Success; + llvm_unreachable("Invalid TemplateArgument Kind!"); } /// \brief Determine whether there is a template argument to be used for @@ -1746,7 +1757,7 @@ DeduceTemplateArguments(Sema &S, // parameter packs expanded by the pack expansion. SmallVector<unsigned, 2> PackIndices; { - llvm::BitVector SawIndices(TemplateParams->size()); + llvm::SmallBitVector SawIndices(TemplateParams->size()); SmallVector<UnexpandedParameterPack, 2> Unexpanded; S.collectUnexpandedParameterPacks(Pattern, Unexpanded); for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { @@ -1846,8 +1857,7 @@ static bool isSameTemplateArg(ASTContext &Context, Context.getCanonicalType(Y.getAsType()); case TemplateArgument::Declaration: - return X.getAsDecl()->getCanonicalDecl() == - Y.getAsDecl()->getCanonicalDecl(); + return isSameDeclaration(X.getAsDecl(), Y.getAsDecl()); case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: @@ -1880,7 +1890,7 @@ static bool isSameTemplateArg(ASTContext &Context, return true; } - return false; + llvm_unreachable("Invalid TemplateArgument Kind!"); } /// \brief Allocate a TemplateArgumentLoc where all locations have @@ -1905,7 +1915,6 @@ getTrivialTemplateArgumentLoc(Sema &S, switch (Arg.getKind()) { case TemplateArgument::Null: llvm_unreachable("Can't get a NULL template argument here"); - break; case TemplateArgument::Type: return TemplateArgumentLoc(Arg, @@ -1914,7 +1923,7 @@ getTrivialTemplateArgumentLoc(Sema &S, case TemplateArgument::Declaration: { Expr *E = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc) - .takeAs<Expr>(); + .takeAs<Expr>(); return TemplateArgumentLoc(TemplateArgument(E), E); } @@ -1950,7 +1959,7 @@ getTrivialTemplateArgumentLoc(Sema &S, return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo()); } - return TemplateArgumentLoc(); + llvm_unreachable("Invalid TemplateArgument Kind!"); } @@ -2021,7 +2030,8 @@ FinishTemplateArgumentDeduction(Sema &S, const TemplateArgumentList &TemplateArgs, SmallVectorImpl<DeducedTemplateArgument> &Deduced, TemplateDeductionInfo &Info) { - // Trap errors. + // Unevaluated SFINAE context. + EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated); Sema::SFINAETrap Trap(S); Sema::ContextRAII SavedContext(S, Partial); @@ -2147,7 +2157,11 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, // argument list if the template arguments of the partial // specialization can be deduced from the actual template argument // list (14.8.2). + + // Unevaluated SFINAE context. + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); SFINAETrap Trap(*this); + SmallVector<DeducedTemplateArgument, 4> Deduced; Deduced.resize(Partial->getTemplateParameters()->size()); if (TemplateDeductionResult Result @@ -2228,8 +2242,8 @@ Sema::SubstituteExplicitTemplateArguments( return TDK_Success; } - // Substitution of the explicit template arguments into a function template - /// is a SFINAE context. Trap any errors that might occur. + // Unevaluated SFINAE context. + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); SFINAETrap Trap(*this); // C++ [temp.arg.explicit]p3: @@ -2288,33 +2302,45 @@ Sema::SubstituteExplicitTemplateArguments( } } + const FunctionProtoType *Proto + = Function->getType()->getAs<FunctionProtoType>(); + assert(Proto && "Function template does not have a prototype?"); + // Instantiate the types of each of the function parameters given the - // explicitly-specified template arguments. - if (SubstParmTypes(Function->getLocation(), + // explicitly-specified template arguments. If the function has a trailing + // return type, substitute it after the arguments to ensure we substitute + // in lexical order. + if (Proto->hasTrailingReturn() && + SubstParmTypes(Function->getLocation(), Function->param_begin(), Function->getNumParams(), MultiLevelTemplateArgumentList(*ExplicitArgumentList), ParamTypes)) return TDK_SubstitutionFailure; - // If the caller wants a full function type back, instantiate the return - // type and form that function type. - if (FunctionType) { - // FIXME: exception-specifications? - const FunctionProtoType *Proto - = Function->getType()->getAs<FunctionProtoType>(); - assert(Proto && "Function template does not have a prototype?"); - - QualType ResultType - = SubstType(Proto->getResultType(), - MultiLevelTemplateArgumentList(*ExplicitArgumentList), - Function->getTypeSpecStartLoc(), - Function->getDeclName()); - if (ResultType.isNull() || Trap.hasErrorOccurred()) - return TDK_SubstitutionFailure; + // Instantiate the return type. + // FIXME: exception-specifications? + QualType ResultType + = SubstType(Proto->getResultType(), + MultiLevelTemplateArgumentList(*ExplicitArgumentList), + Function->getTypeSpecStartLoc(), + Function->getDeclName()); + if (ResultType.isNull() || Trap.hasErrorOccurred()) + return TDK_SubstitutionFailure; + // Instantiate the types of each of the function parameters given the + // explicitly-specified template arguments if we didn't do so earlier. + if (!Proto->hasTrailingReturn() && + SubstParmTypes(Function->getLocation(), + Function->param_begin(), Function->getNumParams(), + MultiLevelTemplateArgumentList(*ExplicitArgumentList), + ParamTypes)) + return TDK_SubstitutionFailure; + + if (FunctionType) { *FunctionType = BuildFunctionType(ResultType, ParamTypes.data(), ParamTypes.size(), Proto->isVariadic(), + Proto->hasTrailingReturn(), Proto->getTypeQuals(), Proto->getRefQualifier(), Function->getLocation(), @@ -2451,8 +2477,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); - // Template argument deduction for function templates in a SFINAE context. - // Trap any errors that might occur. + // Unevaluated SFINAE context. + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); SFINAETrap Trap(*this); // Enter a new template instantiation context while we instantiate the @@ -2681,36 +2707,48 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, if (R.IsAddressOfOperand) TDF |= TDF_IgnoreQualifiers; - // If there were explicit template arguments, we can only find - // something via C++ [temp.arg.explicit]p3, i.e. if the arguments - // unambiguously name a full specialization. - if (Ovl->hasExplicitTemplateArgs()) { - // But we can still look for an explicit specialization. - if (FunctionDecl *ExplicitSpec - = S.ResolveSingleFunctionTemplateSpecialization(Ovl)) - return GetTypeOfFunction(S.Context, R, ExplicitSpec); - return QualType(); - } - // C++0x [temp.deduct.call]p6: // When P is a function type, pointer to function type, or pointer // to member function type: if (!ParamType->isFunctionType() && !ParamType->isFunctionPointerType() && - !ParamType->isMemberFunctionPointerType()) - return QualType(); + !ParamType->isMemberFunctionPointerType()) { + if (Ovl->hasExplicitTemplateArgs()) { + // But we can still look for an explicit specialization. + if (FunctionDecl *ExplicitSpec + = S.ResolveSingleFunctionTemplateSpecialization(Ovl)) + return GetTypeOfFunction(S.Context, R, ExplicitSpec); + } + return QualType(); + } + + // Gather the explicit template arguments, if any. + TemplateArgumentListInfo ExplicitTemplateArgs; + if (Ovl->hasExplicitTemplateArgs()) + Ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs); QualType Match; for (UnresolvedSetIterator I = Ovl->decls_begin(), E = Ovl->decls_end(); I != E; ++I) { NamedDecl *D = (*I)->getUnderlyingDecl(); - // - If the argument is an overload set containing one or more - // function templates, the parameter is treated as a - // non-deduced context. - if (isa<FunctionTemplateDecl>(D)) - return QualType(); + if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) { + // - If the argument is an overload set containing one or more + // function templates, the parameter is treated as a + // non-deduced context. + if (!Ovl->hasExplicitTemplateArgs()) + return QualType(); + + // Otherwise, see if we can resolve a function type + FunctionDecl *Specialization = 0; + TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc()); + if (S.DeduceTemplateArguments(FunTmpl, &ExplicitTemplateArgs, + Specialization, Info)) + continue; + + D = Specialization; + } FunctionDecl *Fn = cast<FunctionDecl>(D); QualType ArgType = GetTypeOfFunction(S.Context, R, Fn); @@ -2737,9 +2775,8 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, Deduced(TemplateParams->size()); TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc()); Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(S, TemplateParams, - ParamType, ArgType, - Info, Deduced, TDF); + = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType, + ArgType, Info, Deduced, TDF); if (Result) continue; if (!Match.isNull()) return QualType(); Match = ArgType; @@ -2866,6 +2903,44 @@ static bool hasDeducibleTemplateParameters(Sema &S, FunctionTemplateDecl *FunctionTemplate, QualType T); +/// \brief Perform template argument deduction by matching a parameter type +/// against a single expression, where the expression is an element of +/// an initializer list that was originally matched against the argument +/// type. +static Sema::TemplateDeductionResult +DeduceTemplateArgumentByListElement(Sema &S, + TemplateParameterList *TemplateParams, + QualType ParamType, Expr *Arg, + TemplateDeductionInfo &Info, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + unsigned TDF) { + // Handle the case where an init list contains another init list as the + // element. + if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) { + QualType X; + if (!S.isStdInitializerList(ParamType.getNonReferenceType(), &X)) + return Sema::TDK_Success; // Just ignore this expression. + + // Recurse down into the init list. + for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) { + if (Sema::TemplateDeductionResult Result = + DeduceTemplateArgumentByListElement(S, TemplateParams, X, + ILE->getInit(i), + Info, Deduced, TDF)) + return Result; + } + return Sema::TDK_Success; + } + + // For all other cases, just match by type. + QualType ArgType = Arg->getType(); + if (AdjustFunctionParmAndArgTypesForDeduction(S, TemplateParams, ParamType, + ArgType, Arg, TDF)) + return Sema::TDK_FailedOverloadResolution; + return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType, + ArgType, Info, Deduced, TDF); +} + /// \brief Perform template argument deduction from a function call /// (C++ [temp.deduct.call]). /// @@ -2895,7 +2970,7 @@ static bool hasDeducibleTemplateParameters(Sema &S, Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); @@ -2904,10 +2979,10 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // Template argument deduction is done by comparing each function template // parameter type (call it P) with the type of the corresponding argument // of the call (call it A) as described below. - unsigned CheckArgs = NumArgs; - if (NumArgs < Function->getMinRequiredArguments()) + unsigned CheckArgs = Args.size(); + if (Args.size() < Function->getMinRequiredArguments()) return TDK_TooFewArguments; - else if (NumArgs > Function->getNumParams()) { + else if (Args.size() > Function->getNumParams()) { const FunctionProtoType *Proto = Function->getType()->getAs<FunctionProtoType>(); if (Proto->isTemplateVariadic()) @@ -2973,15 +3048,37 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, if (!hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType)) continue; + // If the argument is an initializer list ... + if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) { + // ... then the parameter is an undeduced context, unless the parameter + // type is (reference to cv) std::initializer_list<P'>, in which case + // deduction is done for each element of the initializer list, and the + // result is the deduced type if it's the same for all elements. + QualType X; + // Removing references was already done. + if (!isStdInitializerList(ParamType, &X)) + continue; + + for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) { + if (TemplateDeductionResult Result = + DeduceTemplateArgumentByListElement(*this, TemplateParams, X, + ILE->getInit(i), + Info, Deduced, TDF)) + return Result; + } + // Don't track the argument type, since an initializer list has none. + continue; + } + // Keep track of the argument type and corresponding parameter index, // so we can check for compatibility between the deduced A and A. OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx-1, ArgType)); if (TemplateDeductionResult Result - = ::DeduceTemplateArguments(*this, TemplateParams, - ParamType, ArgType, Info, Deduced, - TDF)) + = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, + ParamType, ArgType, + Info, Deduced, TDF)) return Result; continue; @@ -3002,7 +3099,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, QualType ParamPattern = ParamExpansion->getPattern(); SmallVector<unsigned, 2> PackIndices; { - llvm::BitVector SawIndices(TemplateParams->size()); + llvm::SmallBitVector SawIndices(TemplateParams->size()); SmallVector<UnexpandedParameterPack, 2> Unexpanded; collectUnexpandedParameterPacks(ParamPattern, Unexpanded); for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { @@ -3026,7 +3123,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, PrepareArgumentPackDeduction(*this, Deduced, PackIndices, SavedPacks, NewlyDeducedPacks); bool HasAnyArguments = false; - for (; ArgIdx < NumArgs; ++ArgIdx) { + for (; ArgIdx < Args.size(); ++ArgIdx) { HasAnyArguments = true; QualType OrigParamType = ParamPattern; @@ -3044,17 +3141,35 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, break; } - // Keep track of the argument type and corresponding argument index, - // so we can check for compatibility between the deduced A and A. - if (hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType)) - OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx, - ArgType)); + // As above, initializer lists need special handling. + if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) { + QualType X; + if (!isStdInitializerList(ParamType, &X)) { + ++ArgIdx; + break; + } - if (TemplateDeductionResult Result - = ::DeduceTemplateArguments(*this, TemplateParams, - ParamType, ArgType, Info, Deduced, - TDF)) - return Result; + for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) { + if (TemplateDeductionResult Result = + DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, X, + ILE->getInit(i)->getType(), + Info, Deduced, TDF)) + return Result; + } + } else { + + // Keep track of the argument type and corresponding argument index, + // so we can check for compatibility between the deduced A and A. + if (hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType)) + OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx, + ArgType)); + + if (TemplateDeductionResult Result + = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, + ParamType, ArgType, Info, + Deduced, TDF)) + 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 @@ -3135,8 +3250,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, NumExplicitlySpecified = Deduced.size(); } - // Template argument deduction for function templates in a SFINAE context. - // Trap any errors that might occur. + // Unevaluated SFINAE context. + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); SFINAETrap Trap(*this); Deduced.resize(TemplateParams->size()); @@ -3144,7 +3259,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, if (!ArgFunctionType.isNull()) { // Deduce template arguments from the function type. if (TemplateDeductionResult Result - = ::DeduceTemplateArguments(*this, TemplateParams, + = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, FunctionType, ArgFunctionType, Info, Deduced, TDF_TopLevelParameterTypeList)) return Result; @@ -3220,8 +3335,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, A = A.getUnqualifiedType(); } - // Template argument deduction for function templates in a SFINAE context. - // Trap any errors that might occur. + // Unevaluated SFINAE context. + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); SFINAETrap Trap(*this); // C++ [temp.deduct.conv]p1: @@ -3255,8 +3370,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, (P->isMemberPointerType() && A->isMemberPointerType())) TDF |= TDF_IgnoreQualifiers; if (TemplateDeductionResult Result - = ::DeduceTemplateArguments(*this, TemplateParams, - P, A, Info, Deduced, TDF)) + = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, + P, A, Info, Deduced, TDF)) return Result; // Finish template argument deduction. @@ -3325,6 +3440,11 @@ namespace { return Result; } } + + ExprResult TransformLambdaExpr(LambdaExpr *E) { + // Lambdas never need to be transformed. + return E; + } }; } @@ -3339,14 +3459,18 @@ namespace { /// dependent. This will be set to null if deduction succeeded, but auto /// substitution failed; the appropriate diagnostic will already have been /// produced in that case. -/// -/// \returns true if deduction succeeded, false if it failed. -bool -Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *Init, +Sema::DeduceAutoResult +Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init, TypeSourceInfo *&Result) { + if (Init->getType()->isNonOverloadPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(Init); + if (result.isInvalid()) return DAR_FailedAlreadyDiagnosed; + Init = result.take(); + } + if (Init->isTypeDependent()) { Result = Type; - return true; + return DAR_Succeeded; } SourceLocation Loc = Init->getExprLoc(); @@ -3372,41 +3496,70 @@ Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *Init, Deduced.resize(1); QualType InitType = Init->getType(); unsigned TDF = 0; - if (AdjustFunctionParmAndArgTypesForDeduction(*this, &TemplateParams, - FuncParam, InitType, Init, - TDF)) - return false; TemplateDeductionInfo Info(Context, Loc); - if (::DeduceTemplateArguments(*this, &TemplateParams, - FuncParam, InitType, Info, Deduced, - TDF)) - return false; + + InitListExpr * InitList = dyn_cast<InitListExpr>(Init); + if (InitList) { + for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) { + if (DeduceTemplateArgumentByListElement(*this, &TemplateParams, + TemplArg, + InitList->getInit(i), + Info, Deduced, TDF)) + return DAR_Failed; + } + } else { + if (AdjustFunctionParmAndArgTypesForDeduction(*this, &TemplateParams, + FuncParam, InitType, Init, + TDF)) + return DAR_Failed; + + if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam, + InitType, Info, Deduced, TDF)) + return DAR_Failed; + } QualType DeducedType = Deduced[0].getAsType(); if (DeducedType.isNull()) - return false; - + return DAR_Failed; + + if (InitList) { + DeducedType = BuildStdInitializerList(DeducedType, Loc); + if (DeducedType.isNull()) + return DAR_FailedAlreadyDiagnosed; + } + Result = SubstituteAutoTransform(*this, DeducedType).TransformType(Type); - + // Check that the deduced argument type is compatible with the original // argument type per C++ [temp.deduct.call]p4. - if (Result && + if (!InitList && Result && CheckOriginalCallArgDeduction(*this, Sema::OriginalCallArg(FuncParam,0,InitType), Result->getType())) { Result = 0; - return false; + return DAR_Failed; } - return true; + return DAR_Succeeded; +} + +void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) { + if (isa<InitListExpr>(Init)) + Diag(VDecl->getLocation(), + diag::err_auto_var_deduction_failure_from_init_list) + << VDecl->getDeclName() << VDecl->getType() << Init->getSourceRange(); + else + Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure) + << VDecl->getDeclName() << VDecl->getType() << Init->getType() + << Init->getSourceRange(); } static void -MarkUsedTemplateParameters(Sema &SemaRef, QualType T, +MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, bool OnlyDeduced, unsigned Level, - SmallVectorImpl<bool> &Deduced); + llvm::SmallBitVector &Deduced); /// \brief If this is a non-static member function, static void MaybeAddImplicitObjectParameterType(ASTContext &Context, @@ -3481,17 +3634,17 @@ static bool isAtLeastAsSpecializedAs(Sema &S, // first argument of the free function or static member, which // seems to match existing practice. SmallVector<QualType, 4> Args1; - unsigned Skip1 = !S.getLangOptions().CPlusPlus0x && + unsigned Skip1 = !S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1; - if (S.getLangOptions().CPlusPlus0x && IsNonStatic1 && !IsNonStatic2) + if (S.getLangOpts().CPlusPlus0x && IsNonStatic1 && !IsNonStatic2) MaybeAddImplicitObjectParameterType(S.Context, Method1, Args1); Args1.insert(Args1.end(), Proto1->arg_type_begin() + Skip1, Proto1->arg_type_end()); SmallVector<QualType, 4> Args2; - Skip2 = !S.getLangOptions().CPlusPlus0x && + Skip2 = !S.getLangOpts().CPlusPlus0x && IsNonStatic1 && !IsNonStatic2; - if (S.getLangOptions().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1) + if (S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1) MaybeAddImplicitObjectParameterType(S.Context, Method2, Args2); Args2.insert(Args2.end(), Proto2->arg_type_begin() + Skip2, Proto2->arg_type_end()); @@ -3515,19 +3668,23 @@ 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 (DeduceTemplateArguments(S, TemplateParams, Proto2->getResultType(), - Proto1->getResultType(), Info, Deduced, - TDF_None, /*PartialOrdering=*/true, - RefParamComparisons)) + if (DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + Proto2->getResultType(), + Proto1->getResultType(), + Info, Deduced, TDF_None, + /*PartialOrdering=*/true, + RefParamComparisons)) return false; break; case TPOC_Other: // - In other contexts (14.6.6.2) the function template's function type // is used. - if (DeduceTemplateArguments(S, TemplateParams, FD2->getType(), - FD1->getType(), Info, Deduced, TDF_None, - /*PartialOrdering=*/true, RefParamComparisons)) + if (DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, + FD2->getType(), FD1->getType(), + Info, Deduced, TDF_None, + /*PartialOrdering=*/true, + RefParamComparisons)) return false; break; } @@ -3550,31 +3707,31 @@ static bool isAtLeastAsSpecializedAs(Sema &S, } // Figure out which template parameters were used. - SmallVector<bool, 4> UsedParameters; - UsedParameters.resize(TemplateParams->size()); + llvm::SmallBitVector UsedParameters(TemplateParams->size()); switch (TPOC) { case TPOC_Call: { unsigned NumParams = std::min(NumCallArguments, std::min(Proto1->getNumArgs(), Proto2->getNumArgs())); - if (S.getLangOptions().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1) - ::MarkUsedTemplateParameters(S, Method2->getThisType(S.Context), false, + if (S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1) + ::MarkUsedTemplateParameters(S.Context, Method2->getThisType(S.Context), + false, TemplateParams->getDepth(), UsedParameters); for (unsigned I = Skip2; I < NumParams; ++I) - ::MarkUsedTemplateParameters(S, Proto2->getArgType(I), false, + ::MarkUsedTemplateParameters(S.Context, Proto2->getArgType(I), false, TemplateParams->getDepth(), UsedParameters); break; } case TPOC_Conversion: - ::MarkUsedTemplateParameters(S, Proto2->getResultType(), false, + ::MarkUsedTemplateParameters(S.Context, Proto2->getResultType(), false, TemplateParams->getDepth(), UsedParameters); break; case TPOC_Other: - ::MarkUsedTemplateParameters(S, FD2->getType(), false, + ::MarkUsedTemplateParameters(S.Context, FD2->getType(), false, TemplateParams->getDepth(), UsedParameters); break; @@ -3777,7 +3934,8 @@ Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin, const PartialDiagnostic &NoneDiag, const PartialDiagnostic &AmbigDiag, const PartialDiagnostic &CandidateDiag, - bool Complain) { + bool Complain, + QualType TargetType) { if (SpecBegin == SpecEnd) { if (Complain) Diag(Loc, NoneDiag); @@ -3831,11 +3989,16 @@ Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin, if (Complain) // FIXME: Can we order the candidates in some sane way? - for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) - Diag((*I)->getLocation(), CandidateDiag) - << getTemplateArgumentBindingsText( + for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) { + PartialDiagnostic PD = CandidateDiag; + PD << getTemplateArgumentBindingsText( cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(), *cast<FunctionDecl>(*I)->getTemplateSpecializationArgs()); + if (!TargetType.isNull()) + HandleFunctionTypeMismatch(PD, cast<FunctionDecl>(*I)->getType(), + TargetType); + Diag((*I)->getLocation(), PD); + } return SpecEnd; } @@ -3887,7 +4050,8 @@ Sema::getMoreSpecializedPartialSpecialization( // Determine whether PS1 is at least as specialized as PS2 Deduced.resize(PS2->getTemplateParameters()->size()); - bool Better1 = !::DeduceTemplateArguments(*this, PS2->getTemplateParameters(), + bool Better1 = !DeduceTemplateArgumentsByTypeMatch(*this, + PS2->getTemplateParameters(), PT2, PT1, Info, Deduced, TDF_None, /*PartialOrdering=*/true, /*RefParamComparisons=*/0); @@ -3902,7 +4066,8 @@ Sema::getMoreSpecializedPartialSpecialization( // Determine whether PS2 is at least as specialized as PS1 Deduced.clear(); Deduced.resize(PS1->getTemplateParameters()->size()); - bool Better2 = !::DeduceTemplateArguments(*this, PS1->getTemplateParameters(), + bool Better2 = !DeduceTemplateArgumentsByTypeMatch(*this, + PS1->getTemplateParameters(), PT1, PT2, Info, Deduced, TDF_None, /*PartialOrdering=*/true, /*RefParamComparisons=*/0); @@ -3921,20 +4086,20 @@ Sema::getMoreSpecializedPartialSpecialization( } static void -MarkUsedTemplateParameters(Sema &SemaRef, +MarkUsedTemplateParameters(ASTContext &Ctx, const TemplateArgument &TemplateArg, bool OnlyDeduced, unsigned Depth, - SmallVectorImpl<bool> &Used); + llvm::SmallBitVector &Used); /// \brief Mark the template parameters that are used by the given /// expression. static void -MarkUsedTemplateParameters(Sema &SemaRef, +MarkUsedTemplateParameters(ASTContext &Ctx, const Expr *E, bool OnlyDeduced, unsigned Depth, - SmallVectorImpl<bool> &Used) { + llvm::SmallBitVector &Used) { // We can deduce from a pack expansion. if (const PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(E)) E = Expansion->getPattern(); @@ -3961,28 +4126,28 @@ MarkUsedTemplateParameters(Sema &SemaRef, /// \brief Mark the template parameters that are used by the given /// nested name specifier. static void -MarkUsedTemplateParameters(Sema &SemaRef, +MarkUsedTemplateParameters(ASTContext &Ctx, NestedNameSpecifier *NNS, bool OnlyDeduced, unsigned Depth, - SmallVectorImpl<bool> &Used) { + llvm::SmallBitVector &Used) { if (!NNS) return; - MarkUsedTemplateParameters(SemaRef, NNS->getPrefix(), OnlyDeduced, Depth, + MarkUsedTemplateParameters(Ctx, NNS->getPrefix(), OnlyDeduced, Depth, Used); - MarkUsedTemplateParameters(SemaRef, QualType(NNS->getAsType(), 0), + MarkUsedTemplateParameters(Ctx, QualType(NNS->getAsType(), 0), OnlyDeduced, Depth, Used); } /// \brief Mark the template parameters that are used by the given /// template name. static void -MarkUsedTemplateParameters(Sema &SemaRef, +MarkUsedTemplateParameters(ASTContext &Ctx, TemplateName Name, bool OnlyDeduced, unsigned Depth, - SmallVectorImpl<bool> &Used) { + llvm::SmallBitVector &Used) { if (TemplateDecl *Template = Name.getAsTemplateDecl()) { if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) { @@ -3993,20 +4158,20 @@ MarkUsedTemplateParameters(Sema &SemaRef, } if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) - MarkUsedTemplateParameters(SemaRef, QTN->getQualifier(), OnlyDeduced, + MarkUsedTemplateParameters(Ctx, QTN->getQualifier(), OnlyDeduced, Depth, Used); if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) - MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced, + MarkUsedTemplateParameters(Ctx, DTN->getQualifier(), OnlyDeduced, Depth, Used); } /// \brief Mark the template parameters that are used by the given /// type. static void -MarkUsedTemplateParameters(Sema &SemaRef, QualType T, +MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, bool OnlyDeduced, unsigned Depth, - SmallVectorImpl<bool> &Used) { + llvm::SmallBitVector &Used) { if (T.isNull()) return; @@ -4014,10 +4179,10 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, if (!T->isDependentType()) return; - T = SemaRef.Context.getCanonicalType(T); + T = Ctx.getCanonicalType(T); switch (T->getTypeClass()) { case Type::Pointer: - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, cast<PointerType>(T)->getPointeeType(), OnlyDeduced, Depth, @@ -4025,7 +4190,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, break; case Type::BlockPointer: - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, cast<BlockPointerType>(T)->getPointeeType(), OnlyDeduced, Depth, @@ -4034,7 +4199,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, case Type::LValueReference: case Type::RValueReference: - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, cast<ReferenceType>(T)->getPointeeType(), OnlyDeduced, Depth, @@ -4043,29 +4208,29 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, case Type::MemberPointer: { const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr()); - MarkUsedTemplateParameters(SemaRef, MemPtr->getPointeeType(), OnlyDeduced, + MarkUsedTemplateParameters(Ctx, MemPtr->getPointeeType(), OnlyDeduced, Depth, Used); - MarkUsedTemplateParameters(SemaRef, QualType(MemPtr->getClass(), 0), + MarkUsedTemplateParameters(Ctx, QualType(MemPtr->getClass(), 0), OnlyDeduced, Depth, Used); break; } case Type::DependentSizedArray: - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, cast<DependentSizedArrayType>(T)->getSizeExpr(), OnlyDeduced, Depth, Used); // Fall through to check the element type case Type::ConstantArray: case Type::IncompleteArray: - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, cast<ArrayType>(T)->getElementType(), OnlyDeduced, Depth, Used); break; case Type::Vector: case Type::ExtVector: - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, cast<VectorType>(T)->getElementType(), OnlyDeduced, Depth, Used); break; @@ -4073,19 +4238,19 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, case Type::DependentSizedExtVector: { const DependentSizedExtVectorType *VecType = cast<DependentSizedExtVectorType>(T); - MarkUsedTemplateParameters(SemaRef, VecType->getElementType(), OnlyDeduced, + MarkUsedTemplateParameters(Ctx, VecType->getElementType(), OnlyDeduced, Depth, Used); - MarkUsedTemplateParameters(SemaRef, VecType->getSizeExpr(), OnlyDeduced, + MarkUsedTemplateParameters(Ctx, VecType->getSizeExpr(), OnlyDeduced, Depth, Used); break; } case Type::FunctionProto: { const FunctionProtoType *Proto = cast<FunctionProtoType>(T); - MarkUsedTemplateParameters(SemaRef, Proto->getResultType(), OnlyDeduced, + MarkUsedTemplateParameters(Ctx, Proto->getResultType(), OnlyDeduced, Depth, Used); for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I) - MarkUsedTemplateParameters(SemaRef, Proto->getArgType(I), OnlyDeduced, + MarkUsedTemplateParameters(Ctx, Proto->getArgType(I), OnlyDeduced, Depth, Used); break; } @@ -4100,10 +4265,10 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, case Type::SubstTemplateTypeParmPack: { const SubstTemplateTypeParmPackType *Subst = cast<SubstTemplateTypeParmPackType>(T); - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, QualType(Subst->getReplacedParameter(), 0), OnlyDeduced, Depth, Used); - MarkUsedTemplateParameters(SemaRef, Subst->getArgumentPack(), + MarkUsedTemplateParameters(Ctx, Subst->getArgumentPack(), OnlyDeduced, Depth, Used); break; } @@ -4115,7 +4280,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, case Type::TemplateSpecialization: { const TemplateSpecializationType *Spec = cast<TemplateSpecializationType>(T); - MarkUsedTemplateParameters(SemaRef, Spec->getTemplateName(), OnlyDeduced, + MarkUsedTemplateParameters(Ctx, Spec->getTemplateName(), OnlyDeduced, Depth, Used); // C++0x [temp.deduct.type]p9: @@ -4127,28 +4292,28 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, break; for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) - MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth, + MarkUsedTemplateParameters(Ctx, Spec->getArg(I), OnlyDeduced, Depth, Used); break; } case Type::Complex: if (!OnlyDeduced) - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, cast<ComplexType>(T)->getElementType(), OnlyDeduced, Depth, Used); break; case Type::Atomic: if (!OnlyDeduced) - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, cast<AtomicType>(T)->getValueType(), OnlyDeduced, Depth, Used); break; case Type::DependentName: if (!OnlyDeduced) - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, cast<DependentNameType>(T)->getQualifier(), OnlyDeduced, Depth, Used); break; @@ -4157,7 +4322,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, const DependentTemplateSpecializationType *Spec = cast<DependentTemplateSpecializationType>(T); if (!OnlyDeduced) - MarkUsedTemplateParameters(SemaRef, Spec->getQualifier(), + MarkUsedTemplateParameters(Ctx, Spec->getQualifier(), OnlyDeduced, Depth, Used); // C++0x [temp.deduct.type]p9: @@ -4169,47 +4334,47 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, break; for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) - MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth, + MarkUsedTemplateParameters(Ctx, Spec->getArg(I), OnlyDeduced, Depth, Used); break; } case Type::TypeOf: if (!OnlyDeduced) - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, cast<TypeOfType>(T)->getUnderlyingType(), OnlyDeduced, Depth, Used); break; case Type::TypeOfExpr: if (!OnlyDeduced) - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, cast<TypeOfExprType>(T)->getUnderlyingExpr(), OnlyDeduced, Depth, Used); break; case Type::Decltype: if (!OnlyDeduced) - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, cast<DecltypeType>(T)->getUnderlyingExpr(), OnlyDeduced, Depth, Used); break; case Type::UnaryTransform: if (!OnlyDeduced) - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, cast<UnaryTransformType>(T)->getUnderlyingType(), OnlyDeduced, Depth, Used); break; case Type::PackExpansion: - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, cast<PackExpansionType>(T)->getPattern(), OnlyDeduced, Depth, Used); break; case Type::Auto: - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, cast<AutoType>(T)->getDeducedType(), OnlyDeduced, Depth, Used); @@ -4235,31 +4400,31 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, /// \brief Mark the template parameters that are used by this /// template argument. static void -MarkUsedTemplateParameters(Sema &SemaRef, +MarkUsedTemplateParameters(ASTContext &Ctx, const TemplateArgument &TemplateArg, bool OnlyDeduced, unsigned Depth, - SmallVectorImpl<bool> &Used) { + llvm::SmallBitVector &Used) { switch (TemplateArg.getKind()) { case TemplateArgument::Null: case TemplateArgument::Integral: - case TemplateArgument::Declaration: + case TemplateArgument::Declaration: break; case TemplateArgument::Type: - MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsType(), OnlyDeduced, + MarkUsedTemplateParameters(Ctx, TemplateArg.getAsType(), OnlyDeduced, Depth, Used); break; case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: - MarkUsedTemplateParameters(SemaRef, + MarkUsedTemplateParameters(Ctx, TemplateArg.getAsTemplateOrTemplatePattern(), OnlyDeduced, Depth, Used); break; case TemplateArgument::Expression: - MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsExpr(), OnlyDeduced, + MarkUsedTemplateParameters(Ctx, TemplateArg.getAsExpr(), OnlyDeduced, Depth, Used); break; @@ -4267,7 +4432,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, for (TemplateArgument::pack_iterator P = TemplateArg.pack_begin(), PEnd = TemplateArg.pack_end(); P != PEnd; ++P) - MarkUsedTemplateParameters(SemaRef, *P, OnlyDeduced, Depth, Used); + MarkUsedTemplateParameters(Ctx, *P, OnlyDeduced, Depth, Used); break; } } @@ -4284,7 +4449,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, void Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, bool OnlyDeduced, unsigned Depth, - SmallVectorImpl<bool> &Used) { + llvm::SmallBitVector &Used) { // C++0x [temp.deduct.type]p9: // If the template argument list of P contains a pack expansion that is not // the last template argument, the entire template argument list is a @@ -4294,15 +4459,16 @@ Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, return; for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) - ::MarkUsedTemplateParameters(*this, TemplateArgs[I], OnlyDeduced, + ::MarkUsedTemplateParameters(Context, TemplateArgs[I], OnlyDeduced, Depth, Used); } /// \brief Marks all of the template parameters that will be deduced by a /// call to the given function template. void -Sema::MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate, - SmallVectorImpl<bool> &Deduced) { +Sema::MarkDeducedTemplateParameters(ASTContext &Ctx, + FunctionTemplateDecl *FunctionTemplate, + llvm::SmallBitVector &Deduced) { TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); Deduced.clear(); @@ -4310,7 +4476,7 @@ Sema::MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate, FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) - ::MarkUsedTemplateParameters(*this, Function->getParamDecl(I)->getType(), + ::MarkUsedTemplateParameters(Ctx, Function->getParamDecl(I)->getType(), true, TemplateParams->getDepth(), Deduced); } @@ -4322,14 +4488,9 @@ bool hasDeducibleTemplateParameters(Sema &S, TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); - SmallVector<bool, 4> Deduced; - Deduced.resize(TemplateParams->size()); - ::MarkUsedTemplateParameters(S, T, true, TemplateParams->getDepth(), + llvm::SmallBitVector Deduced(TemplateParams->size()); + ::MarkUsedTemplateParameters(S.Context, T, true, TemplateParams->getDepth(), Deduced); - for (unsigned I = 0, N = Deduced.size(); I != N; ++I) - if (Deduced[I]) - return true; - - return false; + return Deduced.any(); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp index 301bf6a..4740145 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -163,8 +163,8 @@ bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const { case DefaultTemplateArgumentChecking: return false; } - - return true; + + llvm_unreachable("Invalid InstantiationKind!"); } Sema::InstantiatingTemplate:: @@ -404,15 +404,15 @@ bool Sema::InstantiatingTemplate::CheckInstantiationDepth( SemaRef.ActiveTemplateInstantiations.size()); if ((SemaRef.ActiveTemplateInstantiations.size() - SemaRef.NonInstantiationEntries) - <= SemaRef.getLangOptions().InstantiationDepth) + <= SemaRef.getLangOpts().InstantiationDepth) return false; SemaRef.Diag(PointOfInstantiation, diag::err_template_recursion_depth_exceeded) - << SemaRef.getLangOptions().InstantiationDepth + << SemaRef.getLangOpts().InstantiationDepth << InstantiationRange; SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth) - << SemaRef.getLangOptions().InstantiationDepth; + << SemaRef.getLangOpts().InstantiationDepth; return true; } @@ -469,6 +469,11 @@ void Sema::PrintInstantiationStack() { diag::note_template_static_data_member_def_here) << VD << Active->InstantiationRange; + } else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) { + Diags.Report(Active->PointOfInstantiation, + diag::note_template_enum_def_here) + << ED + << Active->InstantiationRange; } else { Diags.Report(Active->PointOfInstantiation, diag::note_template_type_alias_instantiation_here) @@ -732,6 +737,14 @@ namespace { /// this declaration. Decl *TransformDecl(SourceLocation Loc, Decl *D); + void transformAttrs(Decl *Old, Decl *New) { + SemaRef.InstantiateAttrs(TemplateArgs, Old, New); + } + + void transformedLocalDecl(Decl *Old, Decl *New) { + SemaRef.CurrentInstantiationScope->InstantiatedLocal(Old, New); + } + /// \brief Transform the definition of the given declaration by /// instantiating it. Decl *TransformDefinition(SourceLocation Loc, Decl *D); @@ -778,7 +791,8 @@ namespace { FunctionProtoTypeLoc TL); ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, int indexAdjustment, - llvm::Optional<unsigned> NumExpansions); + llvm::Optional<unsigned> NumExpansions, + bool ExpectParameterPack); /// \brief Transforms a template type parameter type by performing /// substitution of the corresponding template type argument. @@ -1099,15 +1113,21 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef( type = argExpr->getType(); } else if (arg.getKind() == TemplateArgument::Declaration) { - ValueDecl *VD = cast<ValueDecl>(arg.getAsDecl()); - - // Find the instantiation of the template argument. This is - // required for nested templates. - VD = cast_or_null<ValueDecl>( - getSema().FindInstantiatedDecl(loc, VD, TemplateArgs)); - if (!VD) - return ExprError(); - + ValueDecl *VD; + if (Decl *D = arg.getAsDecl()) { + VD = cast<ValueDecl>(D); + + // Find the instantiation of the template argument. This is + // required for nested templates. + VD = cast_or_null<ValueDecl>( + getSema().FindInstantiatedDecl(loc, VD, TemplateArgs)); + if (!VD) + return ExprError(); + } else { + // Propagate NULL template argument. + VD = 0; + } + // Derive the type we want the substituted decl to have. This had // better be non-dependent, or these checks will have serious problems. if (parm->isExpandedParameterPack()) { @@ -1194,9 +1214,10 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB, ParmVarDecl * TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm, int indexAdjustment, - llvm::Optional<unsigned> NumExpansions) { + llvm::Optional<unsigned> NumExpansions, + bool ExpectParameterPack) { return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment, - NumExpansions); + NumExpansions, ExpectParameterPack); } QualType @@ -1450,7 +1471,8 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, const MultiLevelTemplateArgumentList &TemplateArgs, int indexAdjustment, - llvm::Optional<unsigned> NumExpansions) { + llvm::Optional<unsigned> NumExpansions, + bool ExpectParameterPack) { TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); TypeSourceInfo *NewDI = 0; @@ -1471,7 +1493,16 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, // Therefore, make its type a pack expansion type. NewDI = CheckPackExpansion(NewDI, ExpansionTL.getEllipsisLoc(), NumExpansions); - } + } else if (ExpectParameterPack) { + // We expected to get a parameter pack but didn't (because the type + // itself is not a pack expansion type), so complain. This can occur when + // the substitution goes through an alias template that "loses" the + // pack expansion. + Diag(OldParm->getLocation(), + diag::err_function_parameter_pack_without_parameter_packs) + << NewDI->getType(); + return 0; + } } else { NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(), OldParm->getDeclName()); @@ -1506,11 +1537,9 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, NewParm->setUninstantiatedDefaultArg(Arg); NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg()); - - // FIXME: When OldParm is a parameter pack and NewParm is not a parameter - // pack, we actually have a set of instantiated locations. Maintain this set! + if (OldParm->isParameterPack() && !NewParm->isParameterPack()) { - // Add the new parameter to + // Add the new parameter to the instantiated parameter pack. CurrentInstantiationScope->InstantiatedLocalPackArg(OldParm, NewParm); } else { // Introduce an Old -> New mapping @@ -1654,6 +1683,59 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, return Invalid; } +// Defined via #include from SemaTemplateInstantiateDecl.cpp +namespace clang { + namespace sema { + Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, Sema &S, + const MultiLevelTemplateArgumentList &TemplateArgs); + } +} + +/// Determine whether we would be unable to instantiate this template (because +/// it either has no definition, or is in the process of being instantiated). +static bool DiagnoseUninstantiableTemplate(Sema &S, + SourceLocation PointOfInstantiation, + TagDecl *Instantiation, + bool InstantiatedFromMember, + TagDecl *Pattern, + TagDecl *PatternDef, + TemplateSpecializationKind TSK, + bool Complain = true) { + if (PatternDef && !PatternDef->isBeingDefined()) + return false; + + if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) { + // Say nothing + } else if (PatternDef) { + assert(PatternDef->isBeingDefined()); + S.Diag(PointOfInstantiation, + diag::err_template_instantiate_within_definition) + << (TSK != TSK_ImplicitInstantiation) + << S.Context.getTypeDeclType(Instantiation); + // Not much point in noting the template declaration here, since + // we're lexically inside it. + Instantiation->setInvalidDecl(); + } else if (InstantiatedFromMember) { + S.Diag(PointOfInstantiation, + diag::err_implicit_instantiate_member_undefined) + << S.Context.getTypeDeclType(Instantiation); + S.Diag(Pattern->getLocation(), diag::note_member_of_template_here); + } else { + S.Diag(PointOfInstantiation, diag::err_template_instantiate_undefined) + << (TSK != TSK_ImplicitInstantiation) + << S.Context.getTypeDeclType(Instantiation); + S.Diag(Pattern->getLocation(), diag::note_template_decl_here); + } + + // In general, Instantiation isn't marked invalid to get more than one + // error for multiple undefined instantiations. But the code that does + // explicit declaration -> explicit definition conversion can't handle + // invalid declarations, so mark as invalid in that case. + if (TSK == TSK_ExplicitInstantiationDeclaration) + Instantiation->setInvalidDecl(); + return true; +} + /// \brief Instantiate the definition of a class from a given pattern. /// /// \param PointOfInstantiation The point of instantiation within the @@ -1686,31 +1768,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, CXXRecordDecl *PatternDef = cast_or_null<CXXRecordDecl>(Pattern->getDefinition()); - if (!PatternDef || PatternDef->isBeingDefined()) { - if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) { - // Say nothing - } else if (PatternDef) { - assert(PatternDef->isBeingDefined()); - Diag(PointOfInstantiation, - diag::err_template_instantiate_within_definition) - << (TSK != TSK_ImplicitInstantiation) - << Context.getTypeDeclType(Instantiation); - // Not much point in noting the template declaration here, since - // we're lexically inside it. - Instantiation->setInvalidDecl(); - } else if (Pattern == Instantiation->getInstantiatedFromMemberClass()) { - Diag(PointOfInstantiation, - diag::err_implicit_instantiate_member_undefined) - << Context.getTypeDeclType(Instantiation); - Diag(Pattern->getLocation(), diag::note_member_of_template_here); - } else { - Diag(PointOfInstantiation, diag::err_template_instantiate_undefined) - << (TSK != TSK_ImplicitInstantiation) - << Context.getTypeDeclType(Instantiation); - Diag(Pattern->getLocation(), diag::note_template_decl_here); - } + if (DiagnoseUninstantiableTemplate(*this, PointOfInstantiation, Instantiation, + Instantiation->getInstantiatedFromMemberClass(), + Pattern, PatternDef, TSK, Complain)) return true; - } Pattern = PatternDef; // \brief Record the point of instantiation. @@ -1719,7 +1780,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, MSInfo->setTemplateSpecializationKind(TSK); MSInfo->setPointOfInstantiation(PointOfInstantiation); } else if (ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) { + = dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) { Spec->setTemplateSpecializationKind(TSK); Spec->setPointOfInstantiation(PointOfInstantiation); } @@ -1756,6 +1817,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, SmallVector<Decl*, 4> Fields; SmallVector<std::pair<FieldDecl*, FieldDecl*>, 4> FieldsWithMemberInitializers; + // Delay instantiation of late parsed attributes. + LateInstantiatedAttrVec LateAttrs; + Instantiator.enableLateAttributeInstantiation(&LateAttrs); + for (RecordDecl::decl_iterator Member = Pattern->decls_begin(), MemberEnd = Pattern->decls_end(); Member != MemberEnd; ++Member) { @@ -1784,7 +1849,21 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, if (OldField->getInClassInitializer()) FieldsWithMemberInitializers.push_back(std::make_pair(OldField, Field)); - } else if (NewMember->isInvalidDecl()) + } else if (EnumDecl *Enum = dyn_cast<EnumDecl>(NewMember)) { + // C++11 [temp.inst]p1: The implicit instantiation of a class template + // specialization causes the implicit instantiation of the definitions + // of unscoped member enumerations. + // Record a point of instantiation for this implicit instantiation. + if (TSK == TSK_ImplicitInstantiation && !Enum->isScoped() && + Enum->isCompleteDefinition()) { + MemberSpecializationInfo *MSInfo =Enum->getMemberSpecializationInfo(); + assert(MSInfo && "no spec info for member enum specialization"); + MSInfo->setTemplateSpecializationKind(TSK_ImplicitInstantiation); + MSInfo->setPointOfInstantiation(PointOfInstantiation); + } + } + + if (NewMember->isInvalidDecl()) Invalid = true; } else { // FIXME: Eventually, a NULL return will mean that one of the @@ -1804,22 +1883,42 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, FieldDecl *NewField = FieldsWithMemberInitializers[I].second; Expr *OldInit = OldField->getInClassInitializer(); - SourceLocation LParenLoc, RParenLoc; - ASTOwningVector<Expr*> NewArgs(*this); - if (InstantiateInitializer(OldInit, TemplateArgs, LParenLoc, NewArgs, - RParenLoc)) + ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs, + /*CXXDirectInit=*/false); + if (NewInit.isInvalid()) NewField->setInvalidDecl(); else { - assert(NewArgs.size() == 1 && "wrong number of in-class initializers"); - ActOnCXXInClassMemberInitializer(NewField, LParenLoc, NewArgs[0]); + Expr *Init = NewInit.take(); + assert(Init && "no-argument initializer in class"); + assert(!isa<ParenListExpr>(Init) && "call-style init in class"); + ActOnCXXInClassMemberInitializer(NewField, + Init->getSourceRange().getBegin(), Init); } } + // Instantiate late parsed attributes, and attach them to their decls. + // See Sema::InstantiateAttrs + for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(), + E = LateAttrs.end(); I != E; ++I) { + assert(CurrentInstantiationScope == Instantiator.getStartingScope()); + CurrentInstantiationScope = I->Scope; + Attr *NewAttr = + instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs); + I->NewDecl->addAttr(NewAttr); + LocalInstantiationScope::deleteScopes(I->Scope, + Instantiator.getStartingScope()); + } + Instantiator.disableLateAttributeInstantiation(); + LateAttrs.clear(); + if (!FieldsWithMemberInitializers.empty()) ActOnFinishDelayedMemberInitializers(Instantiation); - if (TSK == TSK_ImplicitInstantiation) + if (TSK == TSK_ImplicitInstantiation) { + Instantiation->setLocation(Pattern->getLocation()); + Instantiation->setLocStart(Pattern->getInnerLocStart()); Instantiation->setRBraceLoc(Pattern->getRBraceLoc()); + } if (Instantiation->isInvalidDecl()) Invalid = true; @@ -1854,6 +1953,63 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, return Invalid; } +/// \brief Instantiate the definition of an enum from a given pattern. +/// +/// \param PointOfInstantiation The point of instantiation within the +/// source code. +/// \param Instantiation is the declaration whose definition is being +/// instantiated. This will be a member enumeration of a class +/// temploid specialization, or a local enumeration within a +/// function temploid specialization. +/// \param Pattern The templated declaration from which the instantiation +/// occurs. +/// \param TemplateArgs The template arguments to be substituted into +/// the pattern. +/// \param TSK The kind of implicit or explicit instantiation to perform. +/// +/// \return \c true if an error occurred, \c false otherwise. +bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation, + EnumDecl *Instantiation, EnumDecl *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs, + TemplateSpecializationKind TSK) { + EnumDecl *PatternDef = Pattern->getDefinition(); + if (DiagnoseUninstantiableTemplate(*this, PointOfInstantiation, Instantiation, + Instantiation->getInstantiatedFromMemberEnum(), + Pattern, PatternDef, TSK,/*Complain*/true)) + return true; + Pattern = PatternDef; + + // Record the point of instantiation. + if (MemberSpecializationInfo *MSInfo + = Instantiation->getMemberSpecializationInfo()) { + MSInfo->setTemplateSpecializationKind(TSK); + MSInfo->setPointOfInstantiation(PointOfInstantiation); + } + + InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation); + if (Inst) + return true; + + // Enter the scope of this instantiation. We don't use + // PushDeclContext because we don't have a scope. + ContextRAII SavedContext(*this, Instantiation); + EnterExpressionEvaluationContext EvalContext(*this, + Sema::PotentiallyEvaluated); + + LocalInstantiationScope Scope(*this, /*MergeWithParentScope*/true); + + // Pull attributes from the pattern onto the instantiation. + InstantiateAttrs(TemplateArgs, Pattern, Instantiation); + + TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs); + Instantiator.InstantiateEnumDefinition(Instantiation, Pattern); + + // Exit the scope of this instantiation. + SavedContext.pop(); + + return Instantiation->isInvalidDecl(); +} + namespace { /// \brief A partial specialization whose template arguments have matched /// a given template-id. @@ -1886,7 +2042,8 @@ Sema::InstantiateClassTemplateSpecialization( // If this is an explicit instantiation definition, mark the // vtable as used. - if (TSK == TSK_ExplicitInstantiationDefinition) + if (TSK == TSK_ExplicitInstantiationDefinition && + !ClassTemplateSpec->isInvalidDecl()) MarkVTableUsed(PointOfInstantiation, ClassTemplateSpec, true); return false; @@ -2120,7 +2277,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, // 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. - if (Record->isInjectedClassName() || Record->getPreviousDeclaration()) + if (Record->isInjectedClassName() || Record->getPreviousDecl()) continue; MemberSpecializationInfo *MSInfo = Record->getMemberSpecializationInfo(); @@ -2173,6 +2330,36 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, if (Pattern) InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs, TSK); + } else if (EnumDecl *Enum = dyn_cast<EnumDecl>(*D)) { + MemberSpecializationInfo *MSInfo = Enum->getMemberSpecializationInfo(); + assert(MSInfo && "No member specialization information?"); + + if (MSInfo->getTemplateSpecializationKind() + == TSK_ExplicitSpecialization) + continue; + + if (CheckSpecializationInstantiationRedecl( + PointOfInstantiation, TSK, Enum, + MSInfo->getTemplateSpecializationKind(), + MSInfo->getPointOfInstantiation(), SuppressNew) || + SuppressNew) + continue; + + if (Enum->getDefinition()) + continue; + + EnumDecl *Pattern = Enum->getInstantiatedFromMemberEnum(); + assert(Pattern && "Missing instantiated-from-template information"); + + if (TSK == TSK_ExplicitInstantiationDefinition) { + if (!Pattern->getDefinition()) + continue; + + InstantiateEnum(PointOfInstantiation, Enum, Pattern, TemplateArgs, TSK); + } else { + MSInfo->setTemplateSpecializationKind(TSK); + MSInfo->setPointOfInstantiation(PointOfInstantiation); + } } } } @@ -2287,7 +2474,7 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) { // If this is a tag declaration, it's possible that we need to look for // a previous declaration. if (const TagDecl *Tag = dyn_cast<TagDecl>(CheckD)) - CheckD = Tag->getPreviousDeclaration(); + CheckD = Tag->getPreviousDecl(); else CheckD = 0; } while (CheckD); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 02a05d5..8afe7ac 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -57,26 +57,30 @@ bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl, return false; } -// FIXME: Is this still too simple? +// Include attribute instantiation code. +#include "clang/Sema/AttrTemplateInstantiate.inc" + void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, - const Decl *Tmpl, Decl *New) { + 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; + // FIXME: This should be generalized to more than just the AlignedAttr. if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) { if (Aligned->isAlignmentDependent()) { - // The alignment expression is not potentially evaluated. - EnterExpressionEvaluationContext Unevaluated(*this, - Sema::Unevaluated); - if (Aligned->isAlignmentExpr()) { + // The alignment expression is a constant expression. + EnterExpressionEvaluationContext Unevaluated(*this, + Sema::ConstantEvaluated); + ExprResult Result = SubstExpr(Aligned->getAlignmentExpr(), TemplateArgs); if (!Result.isInvalid()) AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>()); - } - else { + } else { TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(), TemplateArgs, Aligned->getLocation(), @@ -88,9 +92,18 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, } } - // FIXME: Is cloning correct for all attributes? - Attr *NewAttr = TmplAttr->clone(Context); - New->addAttr(NewAttr); + 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; + if (CurrentInstantiationScope) + Saved = CurrentInstantiationScope->cloneScopes(OuterMostScope); + LateAttrs->push_back(LateInstantiatedAttribute(TmplAttr, Saved, New)); + } else { + Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, + *this, TemplateArgs); + New->addAttr(NewAttr); + } } } @@ -164,13 +177,18 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, } } - if (TypedefNameDecl *Prev = D->getPreviousDeclaration()) { + if (TypedefNameDecl *Prev = D->getPreviousDecl()) { NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev, TemplateArgs); if (!InstPrev) return 0; - Typedef->setPreviousDeclaration(cast<TypedefNameDecl>(InstPrev)); + TypedefNameDecl *InstPrevTypedef = cast<TypedefNameDecl>(InstPrev); + + // If the typedef types are not identical, reject them. + SemaRef.isIncompatibleTypedef(InstPrevTypedef, Typedef); + + Typedef->setPreviousDeclaration(InstPrevTypedef); } SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef); @@ -206,7 +224,7 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { TypeAliasDecl *Pattern = D->getTemplatedDecl(); TypeAliasTemplateDecl *PrevAliasTemplate = 0; - if (Pattern->getPreviousDeclaration()) { + if (Pattern->getPreviousDecl()) { DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); if (Found.first != Found.second) { PrevAliasTemplate = dyn_cast<TypeAliasTemplateDecl>(*Found.first); @@ -234,66 +252,6 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { return Inst; } -/// \brief Instantiate an initializer, breaking it into separate -/// initialization arguments. -/// -/// \param Init The initializer to instantiate. -/// -/// \param TemplateArgs Template arguments to be substituted into the -/// initializer. -/// -/// \param NewArgs Will be filled in with the instantiation arguments. -/// -/// \returns true if an error occurred, false otherwise -bool Sema::InstantiateInitializer(Expr *Init, - const MultiLevelTemplateArgumentList &TemplateArgs, - SourceLocation &LParenLoc, - ASTOwningVector<Expr*> &NewArgs, - SourceLocation &RParenLoc) { - NewArgs.clear(); - LParenLoc = SourceLocation(); - RParenLoc = SourceLocation(); - - if (!Init) - return false; - - if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init)) - Init = ExprTemp->getSubExpr(); - - while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init)) - Init = Binder->getSubExpr(); - - if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init)) - Init = ICE->getSubExprAsWritten(); - - if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { - LParenLoc = ParenList->getLParenLoc(); - RParenLoc = ParenList->getRParenLoc(); - return SubstExprs(ParenList->getExprs(), ParenList->getNumExprs(), - true, TemplateArgs, NewArgs); - } - - if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) { - if (!isa<CXXTemporaryObjectExpr>(Construct)) { - if (SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true, - TemplateArgs, NewArgs)) - return true; - - // FIXME: Fake locations! - LParenLoc = PP.getLocForEndOfToken(Init->getLocStart()); - RParenLoc = LParenLoc; - return false; - } - } - - ExprResult Result = SubstExpr(Init, TemplateArgs); - if (Result.isInvalid()) - return true; - - NewArgs.push_back(Result.takeAs<Expr>()); - return false; -} - Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { // If this is the variable for an anonymous struct or union, // instantiate the anonymous struct/union type first. @@ -324,8 +282,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { D->getStorageClass(), D->getStorageClassAsWritten()); Var->setThreadSpecified(D->isThreadSpecified()); - Var->setCXXDirectInitializer(D->hasCXXDirectInitializer()); + Var->setInitStyle(D->getInitStyle()); Var->setCXXForRangeDecl(D->isCXXForRangeDecl()); + Var->setConstexpr(D->isConstexpr()); // Substitute the nested name specifier, if any. if (SubstQualifier(D, Var)) @@ -351,18 +310,23 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { Sema::LookupOrdinaryName, Sema::ForRedeclaration); if (D->isStaticDataMember()) SemaRef.LookupQualifiedName(Previous, Owner, false); + + // In ARC, infer 'retaining' for variables of retainable type. + if (SemaRef.getLangOpts().ObjCAutoRefCount && + SemaRef.inferObjCARCLifetime(Var)) + Var->setInvalidDecl(); + SemaRef.CheckVariableDeclaration(Var, Previous); if (D->isOutOfLine()) { - if (!D->isStaticDataMember()) - D->getLexicalDeclContext()->addDecl(Var); + D->getLexicalDeclContext()->addDecl(Var); Owner->makeDeclVisibleInContext(Var); } else { Owner->addDecl(Var); if (Owner->isFunctionOrMethod()) SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Var); } - SemaRef.InstantiateAttrs(TemplateArgs, D, Var); + SemaRef.InstantiateAttrs(TemplateArgs, D, Var, LateAttrs, StartingScope); // Link instantiations of static data members back to the template from // which they were instantiated. @@ -374,31 +338,21 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { // We already have an initializer in the class. } else if (D->getInit()) { if (Var->isStaticDataMember() && !D->isOutOfLine()) - SemaRef.PushExpressionEvaluationContext(Sema::Unevaluated); + SemaRef.PushExpressionEvaluationContext(Sema::ConstantEvaluated); else SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); // Instantiate the initializer. - SourceLocation LParenLoc, RParenLoc; - ASTOwningVector<Expr*> InitArgs(SemaRef); - if (!SemaRef.InstantiateInitializer(D->getInit(), TemplateArgs, LParenLoc, - InitArgs, RParenLoc)) { + ExprResult Init = SemaRef.SubstInitializer(D->getInit(), TemplateArgs, + D->getInitStyle() == VarDecl::CallInit); + if (!Init.isInvalid()) { bool TypeMayContainAuto = true; - // Attach the initializer to the declaration, if we have one. - if (InitArgs.size() == 0) + if (Init.get()) { + bool DirectInit = D->isDirectInit(); + SemaRef.AddInitializerToDecl(Var, Init.take(), DirectInit, + TypeMayContainAuto); + } else SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto); - else if (D->hasCXXDirectInitializer()) { - // Add the direct initializer to the declaration. - SemaRef.AddCXXDirectInitializerToDecl(Var, - LParenLoc, - move_arg(InitArgs), - RParenLoc, - TypeMayContainAuto); - } else { - assert(InitArgs.size() == 1); - Expr *Init = InitArgs.take()[0]; - SemaRef.AddInitializerToDecl(Var, Init, false, TypeMayContainAuto); - } } else { // FIXME: Not too happy about invalidating the declaration // because of a bogus initializer. @@ -456,8 +410,9 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { if (Invalid) BitWidth = 0; else if (BitWidth) { - // The bit-width expression is not potentially evaluated. - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + // The bit-width expression is a constant expression. + EnterExpressionEvaluationContext Unevaluated(SemaRef, + Sema::ConstantEvaluated); ExprResult InstantiatedBitWidth = SemaRef.SubstExpr(BitWidth, TemplateArgs); @@ -483,7 +438,7 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { return 0; } - SemaRef.InstantiateAttrs(TemplateArgs, D, Field); + SemaRef.InstantiateAttrs(TemplateArgs, D, Field, LateAttrs, StartingScope); if (Invalid) Field->setInvalidDecl(); @@ -552,7 +507,8 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { if (!InstTy) return 0; - FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getFriendLoc(), InstTy); + FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getLocation(), + D->getFriendLoc(), InstTy); if (!FD) return 0; @@ -584,8 +540,9 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) { Expr *AssertExpr = D->getAssertExpr(); - // The expression in a static assertion is not potentially evaluated. - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + // The expression in a static assertion is a constant expression. + EnterExpressionEvaluationContext Unevaluated(SemaRef, + Sema::ConstantEvaluated); ExprResult InstantiatedAssertExpr = SemaRef.SubstExpr(AssertExpr, TemplateArgs); @@ -601,25 +558,32 @@ Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) { } Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { + EnumDecl *PrevDecl = 0; + if (D->getPreviousDecl()) { + NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), + D->getPreviousDecl(), + TemplateArgs); + if (!Prev) return 0; + PrevDecl = cast<EnumDecl>(Prev); + } + EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, D->getLocStart(), D->getLocation(), D->getIdentifier(), - /*PrevDecl=*/0, D->isScoped(), + PrevDecl, D->isScoped(), D->isScopedUsingClassTag(), D->isFixed()); if (D->isFixed()) { - if (TypeSourceInfo* TI = D->getIntegerTypeSourceInfo()) { + if (TypeSourceInfo *TI = D->getIntegerTypeSourceInfo()) { // If we have type source information for the underlying type, it means it // has been explicitly set by the user. Perform substitution on it before // moving on. SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); - Enum->setIntegerTypeSourceInfo(SemaRef.SubstType(TI, - TemplateArgs, - UnderlyingLoc, - DeclarationName())); - - if (!Enum->getIntegerTypeSourceInfo()) + TypeSourceInfo *NewTI = SemaRef.SubstType(TI, TemplateArgs, UnderlyingLoc, + DeclarationName()); + if (!NewTI || SemaRef.CheckEnumUnderlyingType(NewTI)) Enum->setIntegerType(SemaRef.Context.IntTy); - } - else { + else + Enum->setIntegerTypeSourceInfo(NewTI); + } else { assert(!D->getIntegerType()->isDependentType() && "Dependent type without type source info"); Enum->setIntegerType(D->getIntegerType()); @@ -628,27 +592,62 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { SemaRef.InstantiateAttrs(TemplateArgs, D, Enum); - Enum->setInstantiationOfMemberEnum(D); + Enum->setInstantiationOfMemberEnum(D, TSK_ImplicitInstantiation); Enum->setAccess(D->getAccess()); if (SubstQualifier(D, Enum)) return 0; Owner->addDecl(Enum); - Enum->startDefinition(); + + EnumDecl *Def = D->getDefinition(); + if (Def && Def != D) { + // If this is an out-of-line definition of an enum member template, check + // that the underlying types match in the instantiation of both + // declarations. + if (TypeSourceInfo *TI = Def->getIntegerTypeSourceInfo()) { + SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); + QualType DefnUnderlying = + SemaRef.SubstType(TI->getType(), TemplateArgs, + UnderlyingLoc, DeclarationName()); + SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(), + DefnUnderlying, Enum); + } + } if (D->getDeclContext()->isFunctionOrMethod()) SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum); + // C++11 [temp.inst]p1: The implicit instantiation of a class template + // specialization causes the implicit instantiation of the declarations, but + // not the definitions of scoped member enumerations. + // FIXME: There appears to be no wording for what happens for an enum defined + // within a block scope, but we treat that much like a member template. Only + // instantiate the definition when visiting the definition in that case, since + // we will visit all redeclarations. + if (!Enum->isScoped() && Def && + (!D->getDeclContext()->isFunctionOrMethod() || D->isCompleteDefinition())) + InstantiateEnumDefinition(Enum, Def); + + return Enum; +} + +void TemplateDeclInstantiator::InstantiateEnumDefinition( + EnumDecl *Enum, EnumDecl *Pattern) { + Enum->startDefinition(); + + // Update the location to refer to the definition. + Enum->setLocation(Pattern->getLocation()); + SmallVector<Decl*, 4> Enumerators; EnumConstantDecl *LastEnumConst = 0; - for (EnumDecl::enumerator_iterator EC = D->enumerator_begin(), - ECEnd = D->enumerator_end(); + for (EnumDecl::enumerator_iterator EC = Pattern->enumerator_begin(), + ECEnd = Pattern->enumerator_end(); EC != ECEnd; ++EC) { // The specified value for the enumerator. ExprResult Value = SemaRef.Owned((Expr *)0); if (Expr *UninstValue = EC->getInitExpr()) { - // The enumerator's value expression is not potentially evaluated. + // The enumerator's value expression is a constant expression. EnterExpressionEvaluationContext Unevaluated(SemaRef, - Sema::Unevaluated); + Sema::ConstantEvaluated); Value = SemaRef.SubstExpr(UninstValue, TemplateArgs); } @@ -679,7 +678,8 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { Enumerators.push_back(EnumConst); LastEnumConst = EnumConst; - if (D->getDeclContext()->isFunctionOrMethod()) { + if (Pattern->getDeclContext()->isFunctionOrMethod() && + !Enum->isScoped()) { // If the enumeration is within a function or method, record the enum // constant as a local. SemaRef.CurrentInstantiationScope->InstantiatedLocal(*EC, EnumConst); @@ -687,14 +687,11 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { } } - // FIXME: Fixup LBraceLoc and RBraceLoc - // FIXME: Empty Scope and AttributeList (required to handle attribute packed). - SemaRef.ActOnEnumBody(Enum->getLocation(), SourceLocation(), SourceLocation(), - Enum, + // FIXME: Fixup LBraceLoc + SemaRef.ActOnEnumBody(Enum->getLocation(), SourceLocation(), + Enum->getRBraceLoc(), Enum, Enumerators.data(), Enumerators.size(), 0, 0); - - return Enum; } Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) { @@ -728,7 +725,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { CXXRecordDecl *PrevDecl = 0; ClassTemplateDecl *PrevClassTemplate = 0; - if (!isFriend && Pattern->getPreviousDeclaration()) { + if (!isFriend && Pattern->getPreviousDecl()) { DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); if (Found.first != Found.second) { PrevClassTemplate = dyn_cast<ClassTemplateDecl>(*Found.first); @@ -860,10 +857,17 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { // Finish handling of friends. if (isFriend) { - DC->makeDeclVisibleInContext(Inst, /*Recoverable*/ false); + DC->makeDeclVisibleInContext(Inst); + Inst->setLexicalDeclContext(Owner); + RecordInst->setLexicalDeclContext(Owner); return Inst; } + if (D->isOutOfLine()) { + Inst->setLexicalDeclContext(D->getLexicalDeclContext()); + RecordInst->setLexicalDeclContext(D->getLexicalDeclContext()); + } + Owner->addDecl(Inst); if (!PrevClassTemplate) { @@ -958,9 +962,9 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { CXXRecordDecl *PrevDecl = 0; if (D->isInjectedClassName()) PrevDecl = cast<CXXRecordDecl>(Owner); - else if (D->getPreviousDeclaration()) { + else if (D->getPreviousDecl()) { NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), - D->getPreviousDeclaration(), + D->getPreviousDecl(), TemplateArgs); if (!Prev) return 0; PrevDecl = cast<CXXRecordDecl>(Prev); @@ -1010,11 +1014,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, // Check whether there is already a function template specialization for // this declaration. FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); - void *InsertPos = 0; if (FunctionTemplate && !TemplateParams) { std::pair<const TemplateArgument *, unsigned> Innermost = TemplateArgs.getInnermost(); + void *InsertPos = 0; FunctionDecl *SpecFunc = FunctionTemplate->findSpecialization(Innermost.first, Innermost.second, InsertPos); @@ -1037,8 +1041,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, LocalInstantiationScope Scope(SemaRef, MergeWithParentScope); SmallVector<ParmVarDecl *, 4> Params; - TypeSourceInfo *TInfo = D->getTypeSourceInfo(); - TInfo = SubstFunctionType(D, Params); + TypeSourceInfo *TInfo = SubstFunctionType(D, Params); if (!TInfo) return 0; QualType T = TInfo->getType(); @@ -1071,7 +1074,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, D->getLocation(), D->getDeclName(), T, TInfo, D->getStorageClass(), D->getStorageClassAsWritten(), D->isInlineSpecified(), D->hasWrittenPrototype(), - /*isConstexpr*/ false); + D->isConstexpr()); if (QualifierLoc) Function->setQualifierInfo(QualifierLoc); @@ -1145,7 +1148,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, TemplateArgumentList::CreateCopy(SemaRef.Context, Innermost.first, Innermost.second), - InsertPos); + /*InsertPos=*/0); } 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 @@ -1221,25 +1224,42 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, if (isFriend) { NamedDecl *PrevDecl; if (TemplateParams) - PrevDecl = FunctionTemplate->getPreviousDeclaration(); + PrevDecl = FunctionTemplate->getPreviousDecl(); else - PrevDecl = Function->getPreviousDeclaration(); + PrevDecl = Function->getPreviousDecl(); PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0); - DC->makeDeclVisibleInContext(PrincipalDecl, /*Recoverable=*/ false); + DC->makeDeclVisibleInContext(PrincipalDecl); bool queuedInstantiation = false; - if (!SemaRef.getLangOptions().CPlusPlus0x && + // 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().CPlusPlus0x || + SemaRef.Diags.getDiagnosticLevel( + diag::warn_cxx98_compat_friend_redefinition, + Function->getLocation()) + != DiagnosticsEngine::Ignored) && D->isThisDeclarationADefinition()) { // Check for a function body. const FunctionDecl *Definition = 0; if (Function->isDefined(Definition) && Definition->getTemplateSpecializationKind() == TSK_Undeclared) { - SemaRef.Diag(Function->getLocation(), diag::err_redefinition) - << Function->getDeclName(); + SemaRef.Diag(Function->getLocation(), + SemaRef.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_friend_redefinition : + diag::err_redefinition) << Function->getDeclName(); SemaRef.Diag(Definition->getLocation(), diag::note_previous_definition); - Function->setInvalidDecl(); + if (!SemaRef.getLangOpts().CPlusPlus0x) + Function->setInvalidDecl(); } // Check for redefinitions due to other instantiations of this or // a similar friend function. @@ -1250,7 +1270,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, continue; switch (R->getFriendObjectKind()) { case Decl::FOK_None: - if (!queuedInstantiation && R->isUsed(false)) { + if (!SemaRef.getLangOpts().CPlusPlus0x && + !queuedInstantiation && R->isUsed(false)) { if (MemberSpecializationInfo *MSInfo = Function->getMemberSpecializationInfo()) { if (MSInfo->getPointOfInstantiation().isInvalid()) { @@ -1267,10 +1288,14 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, if (const FunctionDecl *RPattern = R->getTemplateInstantiationPattern()) if (RPattern->isDefined(RPattern)) { - SemaRef.Diag(Function->getLocation(), diag::err_redefinition) + SemaRef.Diag(Function->getLocation(), + SemaRef.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_friend_redefinition : + diag::err_redefinition) << Function->getDeclName(); SemaRef.Diag(R->getLocation(), diag::note_previous_definition); - Function->setInvalidDecl(); + if (!SemaRef.getLangOpts().CPlusPlus0x) + Function->setInvalidDecl(); break; } } @@ -1291,7 +1316,6 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, TemplateParameterList *TemplateParams, bool IsClassScopeSpecialization) { FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); - void *InsertPos = 0; if (FunctionTemplate && !TemplateParams) { // We are creating a function template specialization from a function // template. Check whether there is already a function template @@ -1299,6 +1323,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, std::pair<const TemplateArgument *, unsigned> Innermost = TemplateArgs.getInnermost(); + void *InsertPos = 0; FunctionDecl *SpecFunc = FunctionTemplate->findSpecialization(Innermost.first, Innermost.second, InsertPos); @@ -1334,8 +1359,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, } SmallVector<ParmVarDecl *, 4> Params; - TypeSourceInfo *TInfo = D->getTypeSourceInfo(); - TInfo = SubstFunctionType(D, Params); + TypeSourceInfo *TInfo = SubstFunctionType(D, Params); if (!TInfo) return 0; QualType T = TInfo->getType(); @@ -1395,7 +1419,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, StartLoc, NameInfo, T, TInfo, Constructor->isExplicit(), Constructor->isInlineSpecified(), - false, /*isConstexpr*/ false); + false, Constructor->isConstexpr()); } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { Method = CXXDestructorDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, @@ -1406,7 +1430,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, StartLoc, NameInfo, T, TInfo, Conversion->isInlineSpecified(), Conversion->isExplicit(), - /*isConstexpr*/ false, + Conversion->isConstexpr(), Conversion->getLocEnd()); } else { Method = CXXMethodDecl::Create(SemaRef.Context, Record, @@ -1414,7 +1438,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, D->isStatic(), D->getStorageClassAsWritten(), D->isInlineSpecified(), - /*isConstexpr*/ false, D->getLocEnd()); + D->isConstexpr(), D->getLocEnd()); } if (QualifierLoc) @@ -1452,7 +1476,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, TemplateArgumentList::CreateCopy(SemaRef.Context, Innermost.first, Innermost.second), - InsertPos); + /*InsertPos=*/0); } else if (!isFriend) { // Record that this is an instantiation of a member function. Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); @@ -1504,6 +1528,12 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, SemaRef.CheckOverrideControl(Method); + // If a function is defined as defaulted or deleted, mark it as such now. + if (D->isDefaulted()) + Method->setDefaulted(); + if (D->isDeletedAsWritten()) + Method->setDeletedAsWritten(); + if (FunctionTemplate) { // If there's a function template, let our caller handle it. } else if (Method->isInvalidDecl() && !Previous.empty()) { @@ -1542,7 +1572,8 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) { ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0, - llvm::Optional<unsigned>()); + llvm::Optional<unsigned>(), + /*ExpectParameterPack=*/false); } Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( @@ -1825,6 +1856,12 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { if (NewUD->isInvalidDecl()) return NewUD; + if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) { + if (SemaRef.CheckInheritingConstructorUsingDecl(NewUD)) + NewUD->setInvalidDecl(); + return NewUD; + } + bool isFunctionScope = Owner->isFunctionOrMethod(); // Process the shadow decls. @@ -2094,7 +2131,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( // Add this partial specialization to the set of class template partial // specializations. - ClassTemplate->AddPartialSpecialization(InstPartialSpec, InsertPos); + ClassTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/0); return InstPartialSpec; } @@ -2124,6 +2161,8 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, OldIdx != NumOldParams; ++OldIdx) { ParmVarDecl *OldParam = OldProtoLoc->getArg(OldIdx); if (!OldParam->isParameterPack() || + // FIXME: Is this right? OldParam could expand to an empty parameter + // pack and the next parameter could be an unexpanded parameter pack (NewIdx < NumNewParams && NewProtoLoc->getArg(NewIdx)->isParameterPack())) { // Simple case: normal parameter, or a parameter pack that's @@ -2280,23 +2319,19 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, } Expr *NoexceptExpr = 0; if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) { - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated(SemaRef, + Sema::ConstantEvaluated); ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs); if (E.isUsable()) E = SemaRef.CheckBooleanCondition(E.get(), E.get()->getLocStart()); - + if (E.isUsable()) { - SourceLocation ErrLoc; - llvm::APSInt NoexceptVal; NoexceptExpr = E.take(); if (!NoexceptExpr->isTypeDependent() && - !NoexceptExpr->isValueDependent() && - !NoexceptExpr->isIntegerConstantExpr(NoexceptVal, SemaRef.Context, - &ErrLoc, /*evaluated=*/false)){ - SemaRef.Diag(ErrLoc, diag::err_noexcept_needs_constant_expression) - << NoexceptExpr->getSourceRange(); - NoexceptExpr = 0; - } + !NoexceptExpr->isValueDependent()) + NoexceptExpr = SemaRef.VerifyIntegerConstantExpression(NoexceptExpr, + 0, SemaRef.PDiag(diag::err_noexcept_needs_constant_expression), + /*AllowFold*/ false).take(); } } @@ -2318,19 +2353,13 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, EPI)); } - // C++0x [dcl.constexpr]p6: If the instantiated template specialization of - // a constexpr function template satisfies the requirements for a constexpr - // function, then it is a constexpr function. - if (Tmpl->isConstexpr() && - SemaRef.CheckConstexprFunctionDecl(New, Sema::CCK_Instantiation)) - New->setConstexpr(true); - const FunctionDecl* Definition = Tmpl; // Get the definition. Leaves the variable unchanged if undefined. Tmpl->isDefined(Definition); - SemaRef.InstantiateAttrs(TemplateArgs, Definition, New); + SemaRef.InstantiateAttrs(TemplateArgs, Definition, New, + LateAttrs, StartingScope); return false; } @@ -2450,6 +2479,9 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, if (Inst) return; + // Copy the inner loc start from the pattern. + Function->setInnerLocStart(PatternDecl->getInnerLocStart()); + // If we're performing recursive template instantiation, create our own // queue of pending implicit instantiations that we will instantiate later, // while we're still within our own instantiation context. @@ -2474,6 +2506,13 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, LocalInstantiationScope Scope(*this, MergeWithParentScope); + // 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); + // Introduce the instantiated function parameters into the local // instantiation scope, and set the parameter names to those used // in the template. @@ -2483,7 +2522,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, if (!PatternParam->isParameterPack()) { // Simple case: not a parameter pack. assert(FParamIdx < Function->getNumParams()); - ParmVarDecl *FunctionParam = Function->getParamDecl(I); + ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); FunctionParam->setDeclName(PatternParam->getDeclName()); Scope.InstantiatedLocal(PatternParam, FunctionParam); ++FParamIdx; @@ -2492,22 +2531,16 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // Expand the parameter pack. Scope.MakeInstantiatedLocalArgPack(PatternParam); - for (unsigned NumFParams = Function->getNumParams(); - FParamIdx < NumFParams; - ++FParamIdx) { + unsigned NumArgumentsInExpansion + = getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs); + for (unsigned Arg = 0; Arg < NumArgumentsInExpansion; ++Arg) { ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); FunctionParam->setDeclName(PatternParam->getDeclName()); Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam); + ++FParamIdx; } } - // 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); - if (PatternDecl->isDefaulted()) { ActOnFinishFunctionBody(Function, 0, /*IsInstantiation=*/true); @@ -2612,21 +2645,29 @@ void Sema::InstantiateStaticDataMemberDefinition( return; } + TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind(); + // Never instantiate an explicit specialization. - if (Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + if (TSK == TSK_ExplicitSpecialization) return; // C++0x [temp.explicit]p9: // Except for inline functions, other explicit instantiation declarations // have the effect of suppressing the implicit instantiation of the entity // to which they refer. - if (Var->getTemplateSpecializationKind() - == TSK_ExplicitInstantiationDeclaration) + if (TSK == TSK_ExplicitInstantiationDeclaration) return; + Consumer.HandleCXXStaticMemberVarInstantiation(Var); + // If we already have a definition, we're done. - if (Var->getDefinition()) + if (VarDecl *Def = Var->getDefinition()) { + // We may be explicitly instantiating something we've already implicitly + // instantiated. + Def->setTemplateSpecializationKind(Var->getTemplateSpecializationKind(), + PointOfInstantiation); return; + } InstantiatingTemplate Inst(*this, PointOfInstantiation, Var); if (Inst) @@ -2645,7 +2686,8 @@ void Sema::InstantiateStaticDataMemberDefinition( // Enter the scope of this instantiation. We don't use // PushDeclContext because we don't have a scope. ContextRAII previousContext(*this, Var->getDeclContext()); - + LocalInstantiationScope Local(*this); + VarDecl *OldVar = Var; Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(), getTemplateInstantiationArgs(Var))); @@ -2660,7 +2702,8 @@ void Sema::InstantiateStaticDataMemberDefinition( DeclGroupRef DG(Var); Consumer.HandleTopLevelDecl(DG); } - + Local.Exit(); + if (Recursive) { // Define any newly required vtables. DefineUsedVTables(); @@ -2683,18 +2726,6 @@ void Sema::InstantiateStaticDataMemberDefinition( } } -static MultiInitializer CreateMultiInitializer(SmallVectorImpl<Expr*> &Args, - const CXXCtorInitializer *Init) { - // FIXME: This is a hack that will do slightly the wrong thing for an - // initializer of the form foo({...}). - // The right thing to do would be to modify InstantiateInitializer to create - // the MultiInitializer. - if (Args.size() == 1 && isa<InitListExpr>(Args[0])) - return MultiInitializer(Args[0]); - return MultiInitializer(Init->getLParenLoc(), Args.data(), - Args.size(), Init->getRParenLoc()); -} - void Sema::InstantiateMemInitializers(CXXConstructorDecl *New, const CXXConstructorDecl *Tmpl, @@ -2714,14 +2745,11 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, if (!Init->isWritten()) continue; - SourceLocation LParenLoc, RParenLoc; - ASTOwningVector<Expr*> NewArgs(*this); - SourceLocation EllipsisLoc; if (Init->isPackExpansion()) { // This is a pack expansion. We should expand it now. - TypeLoc BaseTL = Init->getBaseClassInfo()->getTypeLoc(); + TypeLoc BaseTL = Init->getTypeSourceInfo()->getTypeLoc(); SmallVector<UnexpandedParameterPack, 2> Unexpanded; collectUnexpandedParameterPacks(BaseTL, Unexpanded); bool ShouldExpand = false; @@ -2744,14 +2772,15 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I); // Instantiate the initializer. - if (InstantiateInitializer(Init->getInit(), TemplateArgs, - LParenLoc, NewArgs, RParenLoc)) { + ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs, + /*CXXDirectInit=*/true); + if (TempInit.isInvalid()) { AnyErrors = true; break; } // Instantiate the base type. - TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(), + TypeSourceInfo *BaseTInfo = SubstType(Init->getTypeSourceInfo(), TemplateArgs, Init->getSourceLocation(), New->getDeclName()); @@ -2761,9 +2790,8 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, } // Build the initializer. - MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init)); MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(), - BaseTInfo, MultiInit, + BaseTInfo, TempInit.take(), New->getParent(), SourceLocation()); if (NewInit.isInvalid()) { @@ -2772,34 +2800,37 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, } NewInits.push_back(NewInit.get()); - NewArgs.clear(); } continue; } // Instantiate the initializer. - if (InstantiateInitializer(Init->getInit(), TemplateArgs, - LParenLoc, NewArgs, RParenLoc)) { + ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs, + /*CXXDirectInit=*/true); + if (TempInit.isInvalid()) { AnyErrors = true; continue; } MemInitResult NewInit; - if (Init->isBaseInitializer()) { - TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(), - TemplateArgs, - Init->getSourceLocation(), - New->getDeclName()); - if (!BaseTInfo) { + if (Init->isDelegatingInitializer() || Init->isBaseInitializer()) { + TypeSourceInfo *TInfo = SubstType(Init->getTypeSourceInfo(), + TemplateArgs, + Init->getSourceLocation(), + New->getDeclName()); + if (!TInfo) { AnyErrors = true; New->setInvalidDecl(); continue; } - MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init)); - NewInit = BuildBaseInitializer(BaseTInfo->getType(), BaseTInfo, MultiInit, - New->getParent(), EllipsisLoc); + if (Init->isBaseInitializer()) + NewInit = BuildBaseInitializer(TInfo->getType(), TInfo, TempInit.take(), + New->getParent(), EllipsisLoc); + else + NewInit = BuildDelegatingInitializer(TInfo, TempInit.take(), + cast<CXXRecordDecl>(CurContext->getParent())); } else if (Init->isMemberInitializer()) { FieldDecl *Member = cast_or_null<FieldDecl>(FindInstantiatedDecl( Init->getMemberLocation(), @@ -2811,8 +2842,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, continue; } - MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init)); - NewInit = BuildMemberInitializer(Member, MultiInit, + NewInit = BuildMemberInitializer(Member, TempInit.take(), Init->getSourceLocation()); } else if (Init->isIndirectMemberInitializer()) { IndirectFieldDecl *IndirectMember = @@ -2826,8 +2856,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, continue; } - MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init)); - NewInit = BuildMemberInitializer(IndirectMember, MultiInit, + NewInit = BuildMemberInitializer(IndirectMember, TempInit.take(), Init->getSourceLocation()); } @@ -2835,9 +2864,6 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, AnyErrors = true; New->setInvalidDecl(); } else { - // FIXME: It would be nice if ASTOwningVector had a release function. - NewArgs.take(); - NewInits.push_back(NewInit.get()); } } @@ -2850,6 +2876,45 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, AnyErrors); } +ExprResult Sema::SubstInitializer(Expr *Init, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool CXXDirectInit) { + // Initializers are instantiated like expressions, except that various outer + // layers are stripped. + if (!Init) + return Owned(Init); + + if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init)) + Init = ExprTemp->getSubExpr(); + + while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init)) + Init = Binder->getSubExpr(); + + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init)) + Init = ICE->getSubExprAsWritten(); + + // If this is a direct-initializer, we take apart CXXConstructExprs. + // Everything else is passed through. + CXXConstructExpr *Construct; + if (!CXXDirectInit || !(Construct = dyn_cast<CXXConstructExpr>(Init)) || + isa<CXXTemporaryObjectExpr>(Construct)) + return SubstExpr(Init, TemplateArgs); + + ASTOwningVector<Expr*> NewArgs(*this); + if (SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true, + TemplateArgs, NewArgs)) + return ExprError(); + + // Treat an empty initializer like none. + if (NewArgs.empty()) + return Owned((Expr*)0); + + // Build a ParenListExpr to represent anything else. + // FIXME: Fake locations! + SourceLocation Loc = PP.getLocForEndOfToken(Init->getLocStart()); + return ActOnParenListExpr(Loc, Loc, move_arg(NewArgs)); +} + // TODO: this could be templated if the various decl types used the // same method name. static bool isInstantiationOf(ClassTemplateDecl *Pattern, @@ -3090,7 +3155,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, DeclContext *ParentDC = D->getDeclContext(); if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) || - (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext())) { + (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext()) || + (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda())) { // D is a local of some kind. Look into the map of local // declarations to their instantiations. typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; @@ -3120,75 +3186,49 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, if (!Record->isDependentContext()) return D; - // If the RecordDecl is actually the injected-class-name or a - // "templated" declaration for a class template, class template - // partial specialization, or a member class of a class template, - // substitute into the injected-class-name of the class template - // or partial specialization to find the new DeclContext. - QualType T; + // Determine whether this record is the "templated" declaration describing + // a class template or class template partial specialization. ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate(); - - if (ClassTemplate) { - T = ClassTemplate->getInjectedClassNameSpecialization(); - } else if (ClassTemplatePartialSpecializationDecl *PartialSpec - = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) { - ClassTemplate = PartialSpec->getSpecializedTemplate(); - - // If we call SubstType with an InjectedClassNameType here we - // can end up in an infinite loop. - T = Context.getTypeDeclType(Record); - assert(isa<InjectedClassNameType>(T) && - "type of partial specialization is not an InjectedClassNameType"); - T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType(); - } - - if (!T.isNull()) { - // Substitute into the injected-class-name to get the type - // corresponding to the instantiation we want, which may also be - // the current instantiation (if we're in a template - // definition). This substitution should never fail, since we - // know we can instantiate the injected-class-name or we - // wouldn't have gotten to the injected-class-name! - - // FIXME: Can we use the CurrentInstantiationScope to avoid this - // extra instantiation in the common case? - T = SubstType(T, TemplateArgs, Loc, DeclarationName()); - assert(!T.isNull() && "Instantiation of injected-class-name cannot fail."); - - if (!T->isDependentType()) { - assert(T->isRecordType() && "Instantiation must produce a record type"); - return T->getAs<RecordType>()->getDecl(); + if (ClassTemplate) + ClassTemplate = ClassTemplate->getCanonicalDecl(); + else if (ClassTemplatePartialSpecializationDecl *PartialSpec + = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) + ClassTemplate = PartialSpec->getSpecializedTemplate()->getCanonicalDecl(); + + // Walk the current context to find either the record or an instantiation of + // it. + DeclContext *DC = CurContext; + while (!DC->isFileContext()) { + // If we're performing substitution while we're inside the template + // definition, we'll find our own context. We're done. + if (DC->Equals(Record)) + return Record; + + if (CXXRecordDecl *InstRecord = dyn_cast<CXXRecordDecl>(DC)) { + // Check whether we're in the process of instantiating a class template + // specialization of the template we're mapping. + if (ClassTemplateSpecializationDecl *InstSpec + = dyn_cast<ClassTemplateSpecializationDecl>(InstRecord)){ + ClassTemplateDecl *SpecTemplate = InstSpec->getSpecializedTemplate(); + if (ClassTemplate && isInstantiationOf(ClassTemplate, SpecTemplate)) + return InstRecord; + } + + // Check whether we're in the process of instantiating a member class. + if (isInstantiationOf(Record, InstRecord)) + return InstRecord; } - - // We are performing "partial" template instantiation to create - // the member declarations for the members of a class template - // specialization. Therefore, D is actually referring to something - // in the current instantiation. Look through the current - // context, which contains actual instantiations, to find the - // instantiation of the "current instantiation" that D refers - // to. - bool SawNonDependentContext = false; - for (DeclContext *DC = CurContext; !DC->isFileContext(); - DC = DC->getParent()) { - if (ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(DC)) - if (isInstantiationOf(ClassTemplate, - Spec->getSpecializedTemplate())) - return Spec; - - if (!DC->isDependentContext()) - SawNonDependentContext = true; + + + // Move to the outer template scope. + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) { + if (FD->getFriendObjectKind() && FD->getDeclContext()->isFileContext()){ + DC = FD->getLexicalDeclContext(); + continue; + } } - - // We're performing "instantiation" of a member of the current - // instantiation while we are type-checking the - // definition. Compute the declaration context and return that. - assert(!SawNonDependentContext && - "No dependent context while instantiating record"); - DeclContext *DC = computeDeclContext(T); - assert(DC && - "Unable to find declaration for the current instantiation"); - return cast<CXXRecordDecl>(DC); + + DC = DC->getParent(); } // Fall through to deal with other dependent record types (e.g., @@ -3260,6 +3300,20 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, << D->getDeclName() << Context.getTypeDeclType(cast<CXXRecordDecl>(ParentDC)); Diag(D->getLocation(), diag::note_non_instantiated_member_here); + } else if (EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) { + // This enumeration constant was found when the template was defined, + // but can't be found in the instantiation. This can happen if an + // unscoped enumeration member is explicitly specialized. + EnumDecl *Enum = cast<EnumDecl>(ED->getLexicalDeclContext()); + EnumDecl *Spec = cast<EnumDecl>(FindInstantiatedDecl(Loc, Enum, + TemplateArgs)); + assert(Spec->getTemplateSpecializationKind() == + TSK_ExplicitSpecialization); + Diag(Loc, diag::err_enumerator_does_not_exist) + << D->getDeclName() + << Context.getTypeDeclType(cast<TypeDecl>(Spec->getDeclContext())); + Diag(Spec->getLocation(), diag::note_enum_specialized_here) + << Context.getTypeDeclType(Spec); } else { // We should have found something, but didn't. llvm_unreachable("Unable to find instantiation of declaration!"); @@ -3312,12 +3366,12 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { // Don't try to instantiate declarations if the most recent redeclaration // is invalid. - if (Var->getMostRecentDeclaration()->isInvalidDecl()) + if (Var->getMostRecentDecl()->isInvalidDecl()) continue; // Check if the most recent declaration has changed the specialization kind // and removed the need for implicit instantiation. - switch (Var->getMostRecentDeclaration()->getTemplateSpecializationKind()) { + switch (Var->getMostRecentDecl()->getTemplateSpecializationKind()) { case TSK_Undeclared: llvm_unreachable("Cannot instantitiate an undeclared specialization."); case TSK_ExplicitInstantiationDeclaration: @@ -3326,7 +3380,7 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { case TSK_ExplicitInstantiationDefinition: // We only need an instantiation if the pending instantiation *is* the // explicit instantiation. - if (Var != Var->getMostRecentDeclaration()) continue; + if (Var != Var->getMostRecentDecl()) continue; case TSK_ImplicitInstantiation: break; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp index e383db9..a40100c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -73,15 +73,6 @@ namespace { return true; } - // \brief Record occurrences of function and non-type template parameter - // packs in a block-captured expression. - bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { - if (E->getDecl()->isParameterPack()) - Unexpanded.push_back(std::make_pair(E->getDecl(), E->getLocation())); - - return true; - } - /// \brief Record occurrences of template template parameter packs. bool TraverseTemplateName(TemplateName Template) { if (TemplateTemplateParmDecl *TTP @@ -93,6 +84,22 @@ namespace { return inherited::TraverseTemplateName(Template); } + /// \brief Suppress traversal into Objective-C container literal + /// elements that are pack expansions. + bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { + if (!E->containsUnexpandedParameterPack()) + return true; + + for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) { + ObjCDictionaryElement Element = E->getKeyValueElement(I); + if (Element.isPackExpansion()) + continue; + + TraverseStmt(Element.Key); + TraverseStmt(Element.Value); + } + return true; + } //------------------------------------------------------------------------ // Pruning the search for unexpanded parameter packs. //------------------------------------------------------------------------ @@ -155,10 +162,13 @@ namespace { /// \brief Diagnose all of the unexpanded parameter packs in the given /// vector. -static void -DiagnoseUnexpandedParameterPacks(Sema &S, SourceLocation Loc, - Sema::UnexpandedParameterPackContext UPPC, - const SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { +void +Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc, + UnexpandedParameterPackContext UPPC, + ArrayRef<UnexpandedParameterPack> Unexpanded) { + if (Unexpanded.empty()) + return; + SmallVector<SourceLocation, 4> Locations; SmallVector<IdentifierInfo *, 4> Names; llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown; @@ -179,13 +189,13 @@ DiagnoseUnexpandedParameterPacks(Sema &S, SourceLocation Loc, } DiagnosticBuilder DB - = Names.size() == 0? S.Diag(Loc, diag::err_unexpanded_parameter_pack_0) + = Names.size() == 0? Diag(Loc, diag::err_unexpanded_parameter_pack_0) << (int)UPPC - : Names.size() == 1? S.Diag(Loc, diag::err_unexpanded_parameter_pack_1) + : Names.size() == 1? Diag(Loc, diag::err_unexpanded_parameter_pack_1) << (int)UPPC << Names[0] - : Names.size() == 2? S.Diag(Loc, diag::err_unexpanded_parameter_pack_2) + : Names.size() == 2? Diag(Loc, diag::err_unexpanded_parameter_pack_2) << (int)UPPC << Names[0] << Names[1] - : S.Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more) + : Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more) << (int)UPPC << Names[0] << Names[1]; for (unsigned I = 0, N = Locations.size(); I != N; ++I) @@ -205,7 +215,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc( T->getTypeLoc()); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); - DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded); + DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded); return true; } @@ -220,7 +230,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(Expr *E, SmallVector<UnexpandedParameterPack, 2> Unexpanded; CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); - DiagnoseUnexpandedParameterPacks(*this, E->getLocStart(), UPPC, Unexpanded); + DiagnoseUnexpandedParameterPacks(E->getLocStart(), UPPC, Unexpanded); return true; } @@ -237,7 +247,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseNestedNameSpecifier(SS.getScopeRep()); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); - DiagnoseUnexpandedParameterPacks(*this, SS.getRange().getBegin(), + DiagnoseUnexpandedParameterPacks(SS.getRange().getBegin(), UPPC, Unexpanded); return true; } @@ -274,7 +284,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo, CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseType(NameInfo.getName().getCXXNameType()); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); - DiagnoseUnexpandedParameterPacks(*this, NameInfo.getLoc(), UPPC, Unexpanded); + DiagnoseUnexpandedParameterPacks(NameInfo.getLoc(), UPPC, Unexpanded); return true; } @@ -289,7 +299,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseTemplateName(Template); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); - DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded); + DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded); return true; } @@ -303,7 +313,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg, CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseTemplateArgumentLoc(Arg); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); - DiagnoseUnexpandedParameterPacks(*this, Arg.getLocation(), UPPC, Unexpanded); + DiagnoseUnexpandedParameterPacks(Arg.getLocation(), UPPC, Unexpanded); return true; } @@ -329,6 +339,24 @@ void Sema::collectUnexpandedParameterPacks(TypeLoc TL, CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL); } +void Sema::collectUnexpandedParameterPacks(CXXScopeSpec &SS, + SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { + NestedNameSpecifier *Qualifier = SS.getScopeRep(); + if (!Qualifier) + return; + + NestedNameSpecifierLoc QualifierLoc(Qualifier, SS.location_data()); + CollectUnexpandedParameterPacksVisitor(Unexpanded) + .TraverseNestedNameSpecifierLoc(QualifierLoc); +} + +void Sema::collectUnexpandedParameterPacks(const DeclarationNameInfo &NameInfo, + SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { + CollectUnexpandedParameterPacksVisitor(Unexpanded) + .TraverseDeclarationNameInfo(NameInfo); +} + + ParsedTemplateArgument Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg, SourceLocation EllipsisLoc) { @@ -367,7 +395,6 @@ Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg, return Arg.getTemplatePackExpansion(EllipsisLoc); } llvm_unreachable("Unhandled template argument kind?"); - return ParsedTemplateArgument(); } TypeResult Sema::ActOnPackExpansion(ParsedType Type, @@ -611,7 +638,6 @@ unsigned Sema::getNumArgumentsInExpansion(QualType T, } llvm_unreachable("No unexpanded parameter packs in type expansion."); - return 0; } bool Sema::containsUnexpandedParameterPacks(Declarator &D) { @@ -641,6 +667,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_char16: case TST_char32: case TST_int: + case TST_int128: case TST_half: case TST_float: case TST_double: @@ -674,7 +701,6 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { // declarator-id (conceptually), so the parser should not invoke this // routine at this time. llvm_unreachable("Could not have seen this kind of declarator chunk"); - break; case DeclaratorChunk::MemberPointer: if (Chunk.Mem.Scope().getScopeRep() && @@ -687,6 +713,19 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { return false; } +namespace { + +// Callback to only accept typo corrections that refer to parameter packs. +class ParameterPackValidatorCCC : public CorrectionCandidateCallback { + public: + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + NamedDecl *ND = candidate.getCorrectionDecl(); + return ND && ND->isParameterPack(); + } +}; + +} + /// \brief Called when an expression computing the size of a parameter pack /// is parsed. /// @@ -712,6 +751,7 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, LookupName(R, S); NamedDecl *ParameterPack = 0; + ParameterPackValidatorCCC Validator; switch (R.getResultKind()) { case LookupResult::Found: ParameterPack = R.getFoundDecl(); @@ -720,19 +760,16 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, case LookupResult::NotFound: case LookupResult::NotFoundInCurrentInstantiation: if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(), - R.getLookupKind(), S, 0, 0, - false, CTC_NoKeywords)) { - if (NamedDecl *CorrectedResult = Corrected.getCorrectionDecl()) - if (CorrectedResult->isParameterPack()) { - std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions())); - ParameterPack = CorrectedResult; - Diag(NameLoc, diag::err_sizeof_pack_no_pack_name_suggest) - << &Name << CorrectedQuotedStr - << FixItHint::CreateReplacement( - NameLoc, Corrected.getAsString(getLangOptions())); - Diag(ParameterPack->getLocation(), diag::note_parameter_pack_here) - << CorrectedQuotedStr; - } + R.getLookupKind(), S, 0, + Validator)) { + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); + ParameterPack = Corrected.getCorrectionDecl(); + Diag(NameLoc, diag::err_sizeof_pack_no_pack_name_suggest) + << &Name << CorrectedQuotedStr + << FixItHint::CreateReplacement( + NameLoc, Corrected.getAsString(getLangOpts())); + Diag(ParameterPack->getLocation(), diag::note_parameter_pack_here) + << CorrectedQuotedStr; } case LookupResult::FoundOverloaded: @@ -750,6 +787,8 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, return ExprError(); } + MarkAnyDeclReferenced(OpLoc, ParameterPack); + return new (Context) SizeOfPackExpr(Context.getSizeType(), OpLoc, ParameterPack, NameLoc, RParenLoc); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp index 2b563a5..c41df82 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/Basic/OpenCL.h" @@ -25,8 +26,10 @@ #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" +#include "clang/Sema/Lookup.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -503,7 +506,7 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, break; case AttributeList::AT_ns_returns_retained: - if (!state.getSema().getLangOptions().ObjCAutoRefCount) + if (!state.getSema().getLangOpts().ObjCAutoRefCount) break; // fallthrough @@ -546,7 +549,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, // faking up the function chunk is still the right thing to do. // Otherwise, we need to fake up a function declarator. - SourceLocation loc = declarator.getSourceRange().getBegin(); + SourceLocation loc = declarator.getLocStart(); // ...and *prepend* it to the declarator. declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction( @@ -555,6 +558,8 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, /*args*/ 0, 0, /*type quals*/ 0, /*ref-qualifier*/true, SourceLocation(), + /*const qualifier*/SourceLocation(), + /*volatile qualifier*/SourceLocation(), /*mutable qualifier*/SourceLocation(), /*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0, /*parens*/ loc, loc, @@ -580,7 +585,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { const DeclSpec &DS = declarator.getDeclSpec(); SourceLocation DeclLoc = declarator.getIdentifierLoc(); if (DeclLoc.isInvalid()) - DeclLoc = DS.getSourceRange().getBegin(); + DeclLoc = DS.getLocStart(); ASTContext &Context = S.Context; @@ -637,7 +642,10 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // If this is a missing declspec in a block literal return context, then it // is inferred from the return statements inside the block. - if (isOmittedBlockReturnType(declarator)) { + // The declspec is always missing in a lambda expr context; it is either + // specified with a trailing return type or inferred. + if (declarator.getContext() == Declarator::LambdaExprContext || + isOmittedBlockReturnType(declarator)) { Result = Context.DependentTy; break; } @@ -649,13 +657,13 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // allowed to be completely missing a declspec. This is handled in the // parser already though by it pretending to have seen an 'int' in this // case. - if (S.getLangOptions().ImplicitInt) { + if (S.getLangOpts().ImplicitInt) { // In C89 mode, we only warn if there is a completely missing declspec // when one is not allowed. if (DS.isEmpty()) { S.Diag(DeclLoc, diag::ext_missing_declspec) << DS.getSourceRange() - << FixItHint::CreateInsertion(DS.getSourceRange().getBegin(), "int"); + << FixItHint::CreateInsertion(DS.getLocStart(), "int"); } } else if (!DS.hasTypeSpecifier()) { // C99 and C++ require a type specifier. For example, C99 6.7.2p2 says: @@ -663,8 +671,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // specifiers in each declaration, and in the specifier-qualifier list in // each struct declaration and type name." // FIXME: Does Microsoft really have the implicit int extension in C++? - if (S.getLangOptions().CPlusPlus && - !S.getLangOptions().MicrosoftExt) { + if (S.getLangOpts().CPlusPlus && + !S.getLangOpts().MicrosoftExt) { S.Diag(DeclLoc, diag::err_missing_type_specifier) << DS.getSourceRange(); @@ -689,9 +697,10 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { Result = Context.LongLongTy; // long long is a C99 feature. - if (!S.getLangOptions().C99 && - !S.getLangOptions().CPlusPlus0x) - S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_longlong); + if (!S.getLangOpts().C99) + S.Diag(DS.getTypeSpecWidthLoc(), + S.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_longlong : diag::ext_longlong); break; } } else { @@ -703,14 +712,21 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { Result = Context.UnsignedLongLongTy; // long long is a C99 feature. - if (!S.getLangOptions().C99 && - !S.getLangOptions().CPlusPlus0x) - S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_longlong); + if (!S.getLangOpts().C99) + S.Diag(DS.getTypeSpecWidthLoc(), + S.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_longlong : diag::ext_longlong); break; } } break; } + case DeclSpec::TST_int128: + if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned) + Result = Context.UnsignedInt128Ty; + else + Result = Context.Int128Ty; + break; case DeclSpec::TST_half: Result = Context.HalfTy; break; case DeclSpec::TST_float: Result = Context.FloatTy; break; case DeclSpec::TST_double: @@ -719,7 +735,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { else Result = Context.DoubleTy; - if (S.getLangOptions().OpenCL && !S.getOpenCLOptions().cl_khr_fp64) { + if (S.getLangOpts().OpenCL && !S.getOpenCLOptions().cl_khr_fp64) { S.Diag(DS.getTypeSpecTypeLoc(), diag::err_double_requires_fp64); declarator.setInvalidType(true); } @@ -757,9 +773,6 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { ElaboratedTypeKeyword Keyword = ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType()); Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result); - - if (D->isInvalidDecl()) - declarator.setInvalidType(true); break; } case DeclSpec::TST_typename: { @@ -875,7 +888,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // Handle complex types. if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) { - if (S.getLangOptions().Freestanding) + if (S.getLangOpts().Freestanding) S.Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex); Result = Context.getComplexType(Result); } else if (DS.isTypeAltiVecVector()) { @@ -967,6 +980,25 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { TypeQuals &= ~DeclSpec::TQ_volatile; } + // C90 6.5.3 constraints: "The same type qualifier shall not appear more + // than once in the same specifier-list or qualifier-list, either directly + // or via one or more typedefs." + if (!S.getLangOpts().C99 && !S.getLangOpts().CPlusPlus + && TypeQuals & Result.getCVRQualifiers()) { + if (TypeQuals & DeclSpec::TQ_const && Result.isConstQualified()) { + S.Diag(DS.getConstSpecLoc(), diag::ext_duplicate_declspec) + << "const"; + } + + if (TypeQuals & DeclSpec::TQ_volatile && Result.isVolatileQualified()) { + S.Diag(DS.getVolatileSpecLoc(), diag::ext_duplicate_declspec) + << "volatile"; + } + + // C90 doesn't have restrict, so it doesn't force us to produce a warning + // in this case. + } + Qualifiers Quals = Qualifiers::fromCVRMask(TypeQuals); Result = Context.getQualifiedType(Result, Quals); } @@ -1049,12 +1081,14 @@ static QualType inferARCLifetimeForPointee(Sema &S, QualType type, } else if (type->isObjCARCImplicitlyUnretainedType()) { implicitLifetime = Qualifiers::OCL_ExplicitNone; - // If we are in an unevaluated context, like sizeof, assume ExplicitNone and - // don't give error. + // If we are in an unevaluated context, like sizeof, skip adding a + // qualification. } else if (S.ExprEvalContexts.back().Context == Sema::Unevaluated) { - implicitLifetime = Qualifiers::OCL_ExplicitNone; + return type; - // If that failed, give an error and recover using __autoreleasing. + // If that failed, give an error and recover using __strong. __strong + // is the option most likely to prevent spurious second-order diagnostics, + // like when binding a reference to a field. } else { // These types can show up in private ivars in system headers, so // we need this to not be an error in those cases. Instead we @@ -1066,7 +1100,7 @@ static QualType inferARCLifetimeForPointee(Sema &S, QualType type, } else { S.Diag(loc, diag::err_arc_indirect_no_ownership) << type << isReference; } - implicitLifetime = Qualifiers::OCL_Autoreleasing; + implicitLifetime = Qualifiers::OCL_Strong; } assert(implicitLifetime && "didn't infer any lifetime!"); @@ -1100,7 +1134,7 @@ QualType Sema::BuildPointerType(QualType T, assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType"); // In ARC, it is forbidden to build pointers to unqualified pointers. - if (getLangOptions().ObjCAutoRefCount) + if (getLangOpts().ObjCAutoRefCount) T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ false); // Build the pointer type. @@ -1157,7 +1191,7 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, } // In ARC, it is forbidden to build references to unqualified pointers. - if (getLangOptions().ObjCAutoRefCount) + if (getLangOpts().ObjCAutoRefCount) T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ true); // Handle restrict on references. @@ -1168,23 +1202,12 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, /// Check whether the specified array size makes the array type a VLA. If so, /// return true, if not, return the size of the array in SizeVal. -static bool isArraySizeVLA(Expr *ArraySize, llvm::APSInt &SizeVal, Sema &S) { - // If the size is an ICE, it certainly isn't a VLA. - if (ArraySize->isIntegerConstantExpr(SizeVal, S.Context)) - return false; - - // If we're in a GNU mode (like gnu99, but not c99) accept any evaluatable - // value as an extension. - Expr::EvalResult Result; - if (S.LangOpts.GNUMode && ArraySize->Evaluate(Result, S.Context)) { - if (!Result.hasSideEffects() && Result.Val.isInt()) { - SizeVal = Result.Val.getInt(); - S.Diag(ArraySize->getLocStart(), diag::ext_vla_folded_to_constant); - return false; - } - } - - return true; +static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) { + // If the size is an ICE, it certainly isn't a VLA. If we're in a GNU mode + // (like gnu99, but not c99) accept any evaluatable value as an extension. + return S.VerifyIntegerConstantExpression( + ArraySize, &SizeVal, S.PDiag(), S.LangOpts.GNUMode, + S.PDiag(diag::ext_vla_folded_to_constant)).isInvalid(); } @@ -1210,7 +1233,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, SourceRange Brackets, DeclarationName Entity) { SourceLocation Loc = Brackets.getBegin(); - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { // C++ [dcl.array]p1: // T is called the array element type; this type shall not be a reference // type, the (possibly cv-qualified) type void, a function type or an @@ -1262,6 +1285,13 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, return QualType(); } + // Do placeholder conversions on the array size expression. + if (ArraySize && ArraySize->hasPlaceholderType()) { + ExprResult Result = CheckPlaceholderExpr(ArraySize); + if (Result.isInvalid()) return QualType(); + ArraySize = Result.take(); + } + // Do lvalue-to-rvalue conversions on the array size expression. if (ArraySize && !ArraySize->isRValue()) { ExprResult Result = DefaultLvalueConversion(ArraySize); @@ -1272,14 +1302,15 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, } // C99 6.7.5.2p1: The size expression shall have integer type. - // TODO: in theory, if we were insane, we could allow contextual - // conversions to integer type here. - if (ArraySize && !ArraySize->isTypeDependent() && + // C++11 allows contextual conversions to such types. + if (!getLangOpts().CPlusPlus0x && + ArraySize && !ArraySize->isTypeDependent() && !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) { Diag(ArraySize->getLocStart(), diag::err_array_size_non_int) << ArraySize->getType() << ArraySize->getSourceRange(); return QualType(); } + llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType())); if (!ArraySize) { if (ASM == ArrayType::Star) @@ -1288,11 +1319,19 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, T = Context.getIncompleteArrayType(T, ASM, Quals); } else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) { T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets); - } else if (!T->isDependentType() && !T->isIncompleteType() && - !T->isConstantSizeType()) { + } else if ((!T->isDependentType() && !T->isIncompleteType() && + !T->isConstantSizeType()) || + isArraySizeVLA(*this, ArraySize, ConstVal)) { + // Even in C++11, don't allow contextual conversions in the array bound + // of a VLA. + if (getLangOpts().CPlusPlus0x && + !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) { + Diag(ArraySize->getLocStart(), diag::err_array_size_non_int) + << ArraySize->getType() << ArraySize->getSourceRange(); + return QualType(); + } + // C99: an array with an element type that has a non-constant-size is a VLA. - T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets); - } else if (isArraySizeVLA(ArraySize, ConstVal, *this)) { // C99: an array with a non-ICE size is a VLA. We accept any expression // that we can fold to a non-zero positive value as an extension. T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets); @@ -1315,6 +1354,13 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, isSFINAEContext()? diag::err_typecheck_zero_array_size : diag::ext_typecheck_zero_array_size) << ArraySize->getSourceRange(); + + if (ASM == ArrayType::Static) { + Diag(ArraySize->getLocStart(), + diag::warn_typecheck_zero_static_array_size) + << ArraySize->getSourceRange(); + ASM = ArrayType::Normal; + } } else if (!T->isDependentType() && !T->isVariablyModifiedType() && !T->isIncompleteType()) { // Is the array too large? @@ -1329,7 +1375,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, T = Context.getConstantArrayType(T, ConstVal, ASM, Quals); } // If this is not C99, extwarn about VLA's and C99 array size modifiers. - if (!getLangOptions().C99) { + if (!getLangOpts().C99) { if (T->isVariableArrayType()) { // Prohibit the use of non-POD types in VLAs. QualType BaseT = Context.getBaseElementType(T); @@ -1349,9 +1395,9 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, else Diag(Loc, diag::ext_vla); } else if (ASM != ArrayType::Normal || Quals != 0) - Diag(Loc, - getLangOptions().CPlusPlus? diag::err_c99_array_usage_cxx - : diag::ext_c99_array_usage); + Diag(Loc, + getLangOpts().CPlusPlus? diag::err_c99_array_usage_cxx + : diag::ext_c99_array_usage) << ASM; } return T; @@ -1412,6 +1458,8 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, /// /// \param Variadic Whether this is a variadic function type. /// +/// \param HasTrailingReturn Whether this function has a trailing return type. +/// /// \param Quals The cvr-qualifiers to be applied to the function type. /// /// \param Loc The location of the entity whose type involves this @@ -1426,7 +1474,8 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, QualType Sema::BuildFunctionType(QualType T, QualType *ParamTypes, unsigned NumParamTypes, - bool Variadic, unsigned Quals, + bool Variadic, bool HasTrailingReturn, + unsigned Quals, RefQualifierKind RefQualifier, SourceLocation Loc, DeclarationName Entity, FunctionType::ExtInfo Info) { @@ -1465,6 +1514,7 @@ QualType Sema::BuildFunctionType(QualType T, FunctionProtoType::ExtProtoInfo EPI; EPI.Variadic = Variadic; + EPI.HasTrailingReturn = HasTrailingReturn; EPI.TypeQuals = Quals; EPI.RefQualifier = RefQualifier; EPI.ExtInfo = Info; @@ -1476,7 +1526,6 @@ QualType Sema::BuildFunctionType(QualType T, /// /// \param T the type to which the member pointer refers. /// \param Class the class type into which the member pointer points. -/// \param CVR Qualifiers applied to the member pointer type /// \param Loc the location where this type begins /// \param Entity the name of the entity that will have this member pointer type /// @@ -1764,18 +1813,19 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, if (D.getAttributes()) distributeTypeAttrsFromDeclarator(state, T); - // C++0x [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context. - // In C++0x, a function declarator using 'auto' must have a trailing return + // C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context. + // In C++11, a function declarator using 'auto' must have a trailing return // type (this is checked later) and we can skip this. In other languages // using auto, we need to check regardless. if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto && - (!SemaRef.getLangOptions().CPlusPlus0x || !D.isFunctionDeclarator())) { + (!SemaRef.getLangOpts().CPlusPlus0x || !D.isFunctionDeclarator())) { int Error = -1; switch (D.getContext()) { case Declarator::KNRTypeListContext: llvm_unreachable("K&R type lists aren't allowed in C++"); - break; + case Declarator::LambdaExprContext: + llvm_unreachable("Can't specify a type specifier in lambda grammar"); case Declarator::ObjCParameterContext: case Declarator::ObjCResultContext: case Declarator::PrototypeContext: @@ -1808,6 +1858,9 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case Declarator::AliasTemplateContext: Error = 9; // Type alias break; + case Declarator::TrailingReturnContext: + Error = 10; // Function return type + break; case Declarator::TypeNameContext: Error = 11; // Generic break; @@ -1826,11 +1879,11 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, if (D.isFunctionDeclarator()) Error = 10; - // C++0x [dcl.spec.auto]p2: 'auto' is always fine if the declarator + // C++11 [dcl.spec.auto]p2: 'auto' is always fine if the declarator // contains a trailing return type. That is only legal at the outermost // level. Check all declarator chunks (outermost first) anyway, to give // better diagnostics. - if (SemaRef.getLangOptions().CPlusPlus0x && Error != -1) { + if (SemaRef.getLangOpts().CPlusPlus0x && Error != -1) { for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { unsigned chunkIndex = e - i - 1; state.setCurrentChunkIndex(chunkIndex); @@ -1851,20 +1904,28 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, << Error; T = SemaRef.Context.IntTy; D.setInvalidType(true); - } + } else + SemaRef.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), + diag::warn_cxx98_compat_auto_type_specifier); } - if (SemaRef.getLangOptions().CPlusPlus && + if (SemaRef.getLangOpts().CPlusPlus && OwnedTagDecl && OwnedTagDecl->isCompleteDefinition()) { // Check the contexts where C++ forbids the declaration of a new class // or enumeration in a type-specifier-seq. switch (D.getContext()) { + case Declarator::TrailingReturnContext: + // Class and enumeration definitions are syntactically not allowed in + // trailing return types. + llvm_unreachable("parser should not have allowed this"); + break; case Declarator::FileContext: case Declarator::MemberContext: case Declarator::BlockContext: case Declarator::ForContext: case Declarator::BlockLiteralContext: - // C++0x [dcl.type]p3: + case Declarator::LambdaExprContext: + // C++11 [dcl.type]p3: // A type-specifier-seq shall not define a class or enumeration unless // it appears in the type-id of an alias-declaration (7.1.3) that is not // the declaration of a template-declaration. @@ -1908,6 +1969,66 @@ 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>()); +} + static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, QualType declSpecType, TypeSourceInfo *TInfo) { @@ -1916,7 +2037,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, Declarator &D = state.getDeclarator(); Sema &S = state.getSema(); ASTContext &Context = S.Context; - const LangOptions &LangOpts = S.getLangOptions(); + const LangOptions &LangOpts = S.getLangOpts(); bool ImplicitlyNoexcept = false; if (D.getName().getKind() == UnqualifiedId::IK_OperatorFunctionId && @@ -1939,6 +2060,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, D.getContext() == Declarator::AliasDeclContext || D.getContext() == Declarator::AliasTemplateContext; + // Does T refer to a function type with a cv-qualifier or a ref-qualifier? + bool IsQualifiedFunction = T->isFunctionProtoType() && + (T->castAs<FunctionProtoType>()->getTypeQuals() != 0 || + T->castAs<FunctionProtoType>()->getRefQualifier() != RQ_None); + // Walk the DeclTypeInfo, building the recursive type as we go. // DeclTypeInfos are ordered from the identifier out, which is // opposite of what we want :). @@ -1946,8 +2072,11 @@ 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; + } switch (DeclType.Kind) { - default: llvm_unreachable("Unknown decltype!"); case DeclaratorChunk::Paren: T = S.BuildParenType(T); break; @@ -2019,8 +2148,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, ASM = ArrayType::Normal; D.setInvalidType(true); } - T = S.BuildArrayType(T, ASM, ArraySize, - Qualifiers::fromCVRMask(ATI.TypeQuals), + T = S.BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals, SourceRange(DeclType.Loc, DeclType.EndLoc), Name); break; } @@ -2029,6 +2157,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // does not have a K&R-style identifier list), then the arguments are part // of the type, otherwise the argument list is (). const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; + IsQualifiedFunction = FTI.TypeQuals || FTI.hasRefQualifier(); // Check for auto functions and trailing return type and adjust the // return type accordingly. @@ -2048,7 +2177,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, diag::err_trailing_return_in_parens) << T << D.getDeclSpec().getSourceRange(); D.setInvalidType(true); - } else if (T.hasQualifiers() || !isa<AutoType>(T)) { + } else if (D.getContext() != Declarator::LambdaExprContext && + (T.hasQualifiers() || !isa<AutoType>(T))) { S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), diag::err_trailing_return_without_auto) << T << D.getDeclSpec().getSourceRange(); @@ -2160,6 +2290,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, FunctionProtoType::ExtProtoInfo EPI; EPI.Variadic = FTI.isVariadic; + EPI.HasTrailingReturn = FTI.TrailingReturnType; EPI.TypeQuals = FTI.TypeQuals; EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None : FTI.RefQualifierIsLValueRef? RQ_LValue @@ -2260,15 +2391,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, NoexceptExpr->getType()->getCanonicalTypeUnqualified() == Context.BoolTy) && "Parser should have made sure that the expression is boolean"); - SourceLocation ErrLoc; - llvm::APSInt Dummy; - if (!NoexceptExpr->isValueDependent() && - !NoexceptExpr->isIntegerConstantExpr(Dummy, Context, &ErrLoc, - /*evaluated*/false)) - S.Diag(ErrLoc, diag::err_noexcept_needs_constant_expression) - << NoexceptExpr->getSourceRange(); - else - EPI.NoexceptExpr = NoexceptExpr; + if (!NoexceptExpr->isValueDependent()) + NoexceptExpr = S.VerifyIntegerConstantExpression(NoexceptExpr, 0, + S.PDiag(diag::err_noexcept_needs_constant_expression), + /*AllowFold*/ false).take(); + EPI.NoexceptExpr = NoexceptExpr; } } else if (FTI.getExceptionSpecType() == EST_None && ImplicitlyNoexcept && chunkIndex == 0) { @@ -2303,7 +2430,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: llvm_unreachable("Nested-name-specifier must name a type"); - break; case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: @@ -2360,7 +2486,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // top-level template type arguments. bool FreeFunction; if (!D.getCXXScopeSpec().isSet()) { - FreeFunction = (D.getContext() != Declarator::MemberContext || + FreeFunction = ((D.getContext() != Declarator::MemberContext && + D.getContext() != Declarator::LambdaExprContext) || D.getDeclSpec().isFriendSpecified()); } else { DeclContext *DC = S.computeDeclContext(D.getCXXScopeSpec()); @@ -2370,6 +2497,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // C++0x [dcl.constexpr]p8: A constexpr specifier for a non-static member // function that is not a constructor declares that function to be const. if (D.getDeclSpec().isConstexprSpecified() && !FreeFunction && + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static && D.getName().getKind() != UnqualifiedId::IK_ConstructorName && D.getName().getKind() != UnqualifiedId::IK_ConstructorTemplateId && !(FnTy->getTypeQuals() & DeclSpec::TQ_const)) { @@ -2381,86 +2509,57 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, FnTy->getNumArgs(), EPI); } - // C++0x [dcl.fct]p6: - // A ref-qualifier shall only be part of the function type for a - // non-static member function, the function type to which a pointer to - // member refers, or the top-level function type of a function typedef - // declaration. - if ((FnTy->getTypeQuals() != 0 || FnTy->getRefQualifier()) && - !(D.getContext() == Declarator::TemplateTypeArgContext && - !D.isFunctionDeclarator()) && !IsTypedefName && - (FreeFunction || - D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) { - if (D.getContext() == Declarator::TemplateTypeArgContext) { - // Accept qualified function types as template type arguments as a GNU - // extension. This is also the subject of C++ core issue 547. - std::string Quals; - if (FnTy->getTypeQuals() != 0) - 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; + // C++11 [dcl.fct]p6 (w/DR1417): + // An attempt to specify a function type with a cv-qualifier-seq or a + // ref-qualifier (including by typedef-name) is ill-formed unless it is: + // - the function type for a non-static member function, + // - the function type to which a pointer to member refers, + // - the top-level function type of a function typedef declaration or + // 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 + if (IsQualifiedFunction && + !(!FreeFunction && + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) && + !IsTypedefName && + D.getContext() != Declarator::TemplateTypeArgContext) { + SourceLocation Loc = D.getLocStart(); + SourceRange RemovalRange; + unsigned I; + if (D.isFunctionDeclarator(I)) { + SmallVector<SourceLocation, 4> RemovalLocs; + const DeclaratorChunk &Chunk = D.getTypeObject(I); + assert(Chunk.Kind == DeclaratorChunk::Function); + if (Chunk.Fun.hasRefQualifier()) + RemovalLocs.push_back(Chunk.Fun.getRefQualifierLoc()); + if (Chunk.Fun.TypeQuals & Qualifiers::Const) + RemovalLocs.push_back(Chunk.Fun.getConstQualifierLoc()); + if (Chunk.Fun.TypeQuals & Qualifiers::Volatile) + RemovalLocs.push_back(Chunk.Fun.getVolatileQualifierLoc()); + // FIXME: We do not track the location of the __restrict qualifier. + //if (Chunk.Fun.TypeQuals & Qualifiers::Restrict) + // RemovalLocs.push_back(Chunk.Fun.getRestrictQualifierLoc()); + if (!RemovalLocs.empty()) { + std::sort(RemovalLocs.begin(), RemovalLocs.end(), + SourceManager::LocBeforeThanCompare(S.getSourceManager())); + RemovalRange = SourceRange(RemovalLocs.front(), RemovalLocs.back()); + Loc = RemovalLocs.front(); } - - S.Diag(D.getIdentifierLoc(), - diag::ext_qualified_function_type_template_arg) - << Quals; - } else { - if (FnTy->getTypeQuals() != 0) { - if (D.isFunctionDeclarator()) - S.Diag(D.getIdentifierLoc(), - diag::err_invalid_qualified_function_type); - else - S.Diag(D.getIdentifierLoc(), - diag::err_invalid_qualified_typedef_function_type_use) - << FreeFunction; - } - - if (FnTy->getRefQualifier()) { - if (D.isFunctionDeclarator()) { - SourceLocation Loc = D.getIdentifierLoc(); - for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) { - const DeclaratorChunk &Chunk = D.getTypeObject(N-I-1); - if (Chunk.Kind == DeclaratorChunk::Function && - Chunk.Fun.hasRefQualifier()) { - Loc = Chunk.Fun.getRefQualifierLoc(); - break; - } - } - - S.Diag(Loc, diag::err_invalid_ref_qualifier_function_type) - << (FnTy->getRefQualifier() == RQ_LValue) - << FixItHint::CreateRemoval(Loc); - } else { - S.Diag(D.getIdentifierLoc(), - diag::err_invalid_ref_qualifier_typedef_function_type_use) - << FreeFunction - << (FnTy->getRefQualifier() == RQ_LValue); - } - } - - // Strip the cv-qualifiers and ref-qualifiers from the type. - FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo(); - EPI.TypeQuals = 0; - EPI.RefQualifier = RQ_None; - - T = Context.getFunctionType(FnTy->getResultType(), - FnTy->arg_type_begin(), - FnTy->getNumArgs(), EPI); } + + S.Diag(Loc, diag::err_invalid_qualified_function_type) + << FreeFunction << D.isFunctionDeclarator() << T + << getFunctionQualifiersAsString(FnTy) + << FixItHint::CreateRemoval(RemovalRange); + + // Strip the cv-qualifiers and ref-qualifiers from the type. + FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo(); + EPI.TypeQuals = 0; + EPI.RefQualifier = RQ_None; + + T = Context.getFunctionType(FnTy->getResultType(), + FnTy->arg_type_begin(), + FnTy->getNumArgs(), EPI); } } @@ -2540,6 +2639,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case Declarator::CXXCatchContext: case Declarator::ObjCCatchContext: case Declarator::BlockLiteralContext: + case Declarator::LambdaExprContext: + case Declarator::TrailingReturnContext: case Declarator::TemplateTypeArgContext: // FIXME: We may want to allow parameter packs in block-literal contexts // in the future. @@ -2573,7 +2674,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S) { if (T.isNull()) return Context.getNullTypeSourceInfo(); - if (D.isPrototypeContext() && getLangOptions().ObjCAutoRefCount) + if (D.isPrototypeContext() && getLangOpts().ObjCAutoRefCount) inferARCWriteback(state, T); return GetFullTypeForDeclarator(state, T, ReturnTypeInfo); @@ -2605,7 +2706,7 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state, const char *attrStr = 0; switch (ownership) { - case Qualifiers::OCL_None: llvm_unreachable("no ownership!"); break; + case Qualifiers::OCL_None: llvm_unreachable("no ownership!"); case Qualifiers::OCL_ExplicitNone: attrStr = "none"; break; case Qualifiers::OCL_Strong: attrStr = "strong"; break; case Qualifiers::OCL_Weak: attrStr = "weak"; break; @@ -2625,6 +2726,7 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state, // TODO: mark whether we did this inference? } +/// \brief Used for transfering ownership in casts resulting in l-values. static void transferARCOwnership(TypeProcessingState &state, QualType &declSpecTy, Qualifiers::ObjCLifetime ownership) { @@ -2632,6 +2734,7 @@ static void transferARCOwnership(TypeProcessingState &state, Declarator &D = state.getDeclarator(); int inner = -1; + bool hasIndirection = false; for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { DeclaratorChunk &chunk = D.getTypeObject(i); switch (chunk.Kind) { @@ -2642,11 +2745,15 @@ static void transferARCOwnership(TypeProcessingState &state, case DeclaratorChunk::Array: case DeclaratorChunk::Reference: case DeclaratorChunk::Pointer: + if (inner != -1) + hasIndirection = true; inner = i; break; case DeclaratorChunk::BlockPointer: - return transferARCOwnershipToDeclaratorChunk(state, ownership, i); + if (inner != -1) + transferARCOwnershipToDeclaratorChunk(state, ownership, i); + return; case DeclaratorChunk::Function: case DeclaratorChunk::MemberPointer: @@ -2655,13 +2762,13 @@ static void transferARCOwnership(TypeProcessingState &state, } if (inner == -1) - return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership); + return; DeclaratorChunk &chunk = D.getTypeObject(inner); if (chunk.Kind == DeclaratorChunk::Pointer) { if (declSpecTy->isObjCRetainableType()) return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership); - if (declSpecTy->isObjCObjectType()) + if (declSpecTy->isObjCObjectType() && hasIndirection) return transferARCOwnershipToDeclaratorChunk(state, ownership, inner); } else { assert(chunk.Kind == DeclaratorChunk::Array || @@ -2678,7 +2785,7 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) { if (declSpecTy.isNull()) return Context.getNullTypeSourceInfo(); - if (getLangOptions().ObjCAutoRefCount) { + if (getLangOpts().ObjCAutoRefCount) { Qualifiers::ObjCLifetime ownership = Context.getInnerObjCOwnership(FromTy); if (ownership != Qualifiers::OCL_None) transferARCOwnership(state, declSpecTy, ownership); @@ -2720,7 +2827,6 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { return AttributeList::AT_pcs; } llvm_unreachable("unexpected attribute kind!"); - return AttributeList::Kind(); } static void fillAttributedTypeLoc(AttributedTypeLoc TL, @@ -2866,51 +2972,28 @@ namespace { return; } } - TL.setKeywordLoc(Keyword != ETK_None - ? DS.getTypeSpecTypeLoc() - : SourceLocation()); + TL.setElaboratedKeywordLoc(Keyword != ETK_None + ? DS.getTypeSpecTypeLoc() + : SourceLocation()); const CXXScopeSpec& SS = DS.getTypeSpecScope(); TL.setQualifierLoc(SS.getWithLocInContext(Context)); Visit(TL.getNextTypeLoc().getUnqualifiedLoc()); } void VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { - ElaboratedTypeKeyword Keyword - = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType()); - if (DS.getTypeSpecType() == TST_typename) { - TypeSourceInfo *TInfo = 0; - Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); - if (TInfo) { - TL.copy(cast<DependentNameTypeLoc>(TInfo->getTypeLoc())); - return; - } - } - TL.setKeywordLoc(Keyword != ETK_None - ? DS.getTypeSpecTypeLoc() - : SourceLocation()); - const CXXScopeSpec& SS = DS.getTypeSpecScope(); - TL.setQualifierLoc(SS.getWithLocInContext(Context)); - TL.setNameLoc(DS.getTypeSpecTypeNameLoc()); + assert(DS.getTypeSpecType() == TST_typename); + TypeSourceInfo *TInfo = 0; + Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); + assert(TInfo); + TL.copy(cast<DependentNameTypeLoc>(TInfo->getTypeLoc())); } void VisitDependentTemplateSpecializationTypeLoc( DependentTemplateSpecializationTypeLoc TL) { - ElaboratedTypeKeyword Keyword - = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType()); - if (Keyword == ETK_Typename) { - TypeSourceInfo *TInfo = 0; - Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); - if (TInfo) { - TL.copy(cast<DependentTemplateSpecializationTypeLoc>( - TInfo->getTypeLoc())); - return; - } - } - TL.initializeLocal(Context, SourceLocation()); - TL.setKeywordLoc(Keyword != ETK_None - ? DS.getTypeSpecTypeLoc() - : SourceLocation()); - const CXXScopeSpec& SS = DS.getTypeSpecScope(); - TL.setQualifierLoc(SS.getWithLocInContext(Context)); - TL.setNameLoc(DS.getTypeSpecTypeNameLoc()); + assert(DS.getTypeSpecType() == TST_typename); + TypeSourceInfo *TInfo = 0; + Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); + assert(TInfo); + TL.copy(cast<DependentTemplateSpecializationTypeLoc>( + TInfo->getTypeLoc())); } void VisitTagTypeLoc(TagTypeLoc TL) { TL.setNameLoc(DS.getTypeSpecTypeNameLoc()); @@ -2972,7 +3055,7 @@ namespace { assert(isa<DependentNameType>(ClsTy) && "Unexpected TypeLoc"); { DependentNameTypeLoc DNTLoc = cast<DependentNameTypeLoc>(ClsTL); - DNTLoc.setKeywordLoc(SourceLocation()); + DNTLoc.setElaboratedKeywordLoc(SourceLocation()); DNTLoc.setQualifierLoc(NNSLoc.getPrefix()); DNTLoc.setNameLoc(NNSLoc.getLocalBeginLoc()); } @@ -2982,7 +3065,7 @@ namespace { case NestedNameSpecifier::TypeSpecWithTemplate: if (isa<ElaboratedType>(ClsTy)) { ElaboratedTypeLoc ETLoc = *cast<ElaboratedTypeLoc>(&ClsTL); - ETLoc.setKeywordLoc(SourceLocation()); + ETLoc.setElaboratedKeywordLoc(SourceLocation()); ETLoc.setQualifierLoc(NNSLoc.getPrefix()); TypeLoc NamedTL = ETLoc.getNamedTypeLoc(); NamedTL.initializeFullCopy(NNSLoc.getTypeLoc()); @@ -2995,7 +3078,6 @@ namespace { case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: llvm_unreachable("Nested-name-specifier must name a type"); - break; } // Finally fill in MemberPointerLocInfo fields. @@ -3124,7 +3206,7 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) { if (D.getContext() != Declarator::ObjCParameterContext) checkUnusedDeclAttributes(D); - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { // Check that there are no default arguments (C++ only). CheckExtraCXXDefaultArguments(D); } @@ -3205,6 +3287,36 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, Type = S.Context.getAddrSpaceQualType(Type, ASIdx); } +/// Does this type have a "direct" ownership qualifier? That is, +/// is it written like "__strong id", as opposed to something like +/// "typeof(foo)", where that happens to be strong? +static bool hasDirectOwnershipQualifier(QualType type) { + // Fast path: no qualifier at all. + assert(type.getQualifiers().hasObjCLifetime()); + + while (true) { + // __strong id + if (const AttributedType *attr = dyn_cast<AttributedType>(type)) { + if (attr->getAttrKind() == AttributedType::attr_objc_ownership) + return true; + + type = attr->getModifiedType(); + + // X *__strong (...) + } else if (const ParenType *paren = dyn_cast<ParenType>(type)) { + type = paren->getInnerType(); + + // That's it for things we want to complain about. In particular, + // we do not want to look through typedefs, typeof(expr), + // typeof(type), or any other way that the type is somehow + // abstracted. + } else { + + return false; + } + } +} + /// handleObjCOwnershipTypeAttr - Process an objc_ownership /// attribute on the specified type. /// @@ -3212,20 +3324,27 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, AttributeList &attr, QualType &type) { - if (!type->isObjCRetainableType() && !type->isDependentType()) - return false; + bool NonObjCPointer = false; + + if (!type->isDependentType()) { + if (const PointerType *ptr = type->getAs<PointerType>()) { + QualType pointee = ptr->getPointeeType(); + if (pointee->isObjCRetainableType() || pointee->isPointerType()) + return false; + // It is important not to lose the source info that there was an attribute + // applied to non-objc pointer. We will create an attributed type but + // its type will be the same as the original type. + NonObjCPointer = true; + } else if (!type->isObjCRetainableType()) { + return false; + } + } Sema &S = state.getSema(); SourceLocation AttrLoc = attr.getLoc(); if (AttrLoc.isMacroID()) AttrLoc = S.getSourceManager().getImmediateExpansionRange(AttrLoc).first; - if (type.getQualifiers().getObjCLifetime()) { - S.Diag(AttrLoc, diag::err_attr_objc_ownership_redundant) - << type; - return true; - } - if (!attr.getParameterName()) { S.Diag(AttrLoc, diag::err_attribute_argument_n_not_string) << "objc_ownership" << 1; @@ -3233,6 +3352,11 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, return true; } + // Consume lifetime attributes without further comment outside of + // ARC mode. + if (!S.getLangOpts().ObjCAutoRefCount) + return true; + Qualifiers::ObjCLifetime lifetime; if (attr.getParameterName()->isStr("none")) lifetime = Qualifiers::OCL_ExplicitNone; @@ -3249,15 +3373,49 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, return true; } - // Consume lifetime attributes without further comment outside of - // ARC mode. - if (!S.getLangOptions().ObjCAutoRefCount) - return true; + SplitQualType underlyingType = type.split(); + + // Check for redundant/conflicting ownership qualifiers. + if (Qualifiers::ObjCLifetime previousLifetime + = type.getQualifiers().getObjCLifetime()) { + // If it's written directly, that's an error. + if (hasDirectOwnershipQualifier(type)) { + S.Diag(AttrLoc, diag::err_attr_objc_ownership_redundant) + << type; + return true; + } + + // Otherwise, if the qualifiers actually conflict, pull sugar off + // until we reach a type that is directly qualified. + if (previousLifetime != lifetime) { + // This should always terminate: the canonical type is + // qualified, so some bit of sugar must be hiding it. + while (!underlyingType.Quals.hasObjCLifetime()) { + underlyingType = underlyingType.getSingleStepDesugaredType(); + } + underlyingType.Quals.removeObjCLifetime(); + } + } + + underlyingType.Quals.addObjCLifetime(lifetime); + + if (NonObjCPointer) { + StringRef name = attr.getName()->getName(); + switch (lifetime) { + case Qualifiers::OCL_None: + case Qualifiers::OCL_ExplicitNone: + break; + case Qualifiers::OCL_Strong: name = "__strong"; break; + case Qualifiers::OCL_Weak: name = "__weak"; break; + case Qualifiers::OCL_Autoreleasing: name = "__autoreleasing"; break; + } + S.Diag(AttrLoc, diag::warn_objc_object_attribute_wrong_type) + << name << type; + } - Qualifiers qs; - qs.setObjCLifetime(lifetime); QualType origType = type; - type = S.Context.getQualifiedType(type, qs); + if (!NonObjCPointer) + type = S.Context.getQualifiedType(underlyingType); // If we have a valid source location for the attribute, use an // AttributedType instead. @@ -3267,7 +3425,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, // Forbid __weak if the runtime doesn't support it. if (lifetime == Qualifiers::OCL_Weak && - !S.getLangOptions().ObjCRuntimeHasWeak) { + !S.getLangOpts().ObjCRuntimeHasWeak && !NonObjCPointer) { // Actually, delay this until we know what we're parsing. if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { @@ -3438,9 +3596,9 @@ namespace { SplitQualType SplitOld = Old.split(); // As a special case, tail-recurse if there are no qualifiers. - if (SplitOld.second.empty()) - return wrap(C, SplitOld.first, I); - return C.getQualifiedType(wrap(C, SplitOld.first, I), SplitOld.second); + if (SplitOld.Quals.empty()) + return wrap(C, SplitOld.Ty, I); + return C.getQualifiedType(wrap(C, SplitOld.Ty, I), SplitOld.Quals); } QualType wrap(ASTContext &C, const Type *Old, unsigned I) { @@ -3484,7 +3642,6 @@ namespace { } llvm_unreachable("unknown wrapping kind"); - return QualType(); } }; } @@ -3515,7 +3672,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, // ns_returns_retained is not always a type attribute, but if we got // here, we're treating it as one right now. if (attr.getKind() == AttributeList::AT_ns_returns_retained) { - assert(S.getLangOptions().ObjCAutoRefCount && + assert(S.getLangOpts().ObjCAutoRefCount && "ns_returns_retained treated as type attribute in non-ARC"); if (attr.getNumArgs()) return true; @@ -3712,11 +3869,12 @@ static void HandleExtVectorTypeAttr(QualType &CurType, // Special case where the argument is a template id. if (Attr.getParameterName()) { CXXScopeSpec SS; + SourceLocation TemplateKWLoc; UnqualifiedId id; id.setIdentifier(Attr.getParameterName(), Attr.getLoc()); - - ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, id, false, - false); + + ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc, + id, false, false); if (Size.isInvalid()) return; @@ -3857,7 +4015,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, break; case AttributeList::AT_ns_returns_retained: - if (!state.getSema().getLangOptions().ObjCAutoRefCount) + if (!state.getSema().getLangOpts().ObjCAutoRefCount) break; // fallthrough into the function attrs @@ -3988,9 +4146,52 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, // "Can't ask whether a dependent type is complete"); // If we have a complete type, we're done. - if (!T->isIncompleteType()) + NamedDecl *Def = 0; + if (!T->isIncompleteType(&Def)) { + // If we know about the definition but it is not visible, complain. + if (diag != 0 && Def && !LookupResult::isVisible(Def)) { + // 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. + if (isSFINAEContext() || HiddenDefinitions.insert(Def)) { + Diag(Loc, diag::err_module_private_definition) << T; + Diag(Def->getLocation(), diag::note_previous_definition); + } + } + return false; + } + const TagType *Tag = T->getAs<TagType>(); + const ObjCInterfaceType *IFace = 0; + + if (Tag) { + // Avoid diagnosing invalid decls as incomplete. + if (Tag->getDecl()->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; + + // 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 we have a class template specialization or a class member of a // class template specialization, or an array with known size of such, // try to instantiate it. @@ -4006,12 +4207,12 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, /*Complain=*/diag != 0); } else if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Record->getDecl())) { - if (CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass()) { - MemberSpecializationInfo *MSInfo = Rec->getMemberSpecializationInfo(); - assert(MSInfo && "Missing member specialization information?"); + CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass(); + if (!Rec->isBeingDefined() && Pattern) { + MemberSpecializationInfo *MSI = Rec->getMemberSpecializationInfo(); + assert(MSI && "Missing member specialization information?"); // This record was instantiated from a class within a template. - if (MSInfo->getTemplateSpecializationKind() - != TSK_ExplicitSpecialization) + if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) return InstantiateClass(Loc, Rec, Pattern, getTemplateInstantiationArgs(Rec), TSK_ImplicitInstantiation, @@ -4022,23 +4223,10 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, if (diag == 0) return true; - - const TagType *Tag = T->getAs<TagType>(); - - // Avoid diagnosing invalid decls as incomplete. - if (Tag && Tag->getDecl()->isInvalidDecl()) - return true; - - // Give the external AST source a chance to complete the type. - if (Tag && Tag->getDecl()->hasExternalLexicalStorage()) { - Context.getExternalSource()->CompleteType(Tag->getDecl()); - if (!Tag->isIncompleteType()) - return false; - } - + // We have an incomplete type. Produce a diagnostic. Diag(Loc, PD) << T; - + // If we have a note, produce it. if (!Note.first.isInvalid()) Diag(Note.first, Note.second); @@ -4049,7 +4237,11 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, Diag(Tag->getDecl()->getLocation(), Tag->isBeingDefined() ? diag::note_type_being_defined : diag::note_forward_declaration) - << QualType(Tag, 0); + << QualType(Tag, 0); + + // If the Objective-C class was a forward declaration, produce a note. + if (IFace && !IFace->getDecl()->isInvalidDecl()) + Diag(IFace->getDecl()->getLocation(), diag::note_forward_class); return true; } @@ -4083,18 +4275,16 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, /// @param PD The partial diagnostic that will be printed out if T is not a /// literal type. /// -/// @param AllowIncompleteType If true, an incomplete type will be considered -/// acceptable. -/// /// @returns @c true if @p T is not a literal type and a diagnostic was emitted, /// @c false otherwise. bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, - const PartialDiagnostic &PD, - bool AllowIncompleteType) { + const PartialDiagnostic &PD) { assert(!T->isDependentType() && "type should not be dependent"); - bool Incomplete = RequireCompleteType(Loc, T, 0); - if (T->isLiteralType() || (AllowIncompleteType && Incomplete)) + QualType ElemType = Context.getBaseElementType(T); + RequireCompleteType(Loc, ElemType, 0); + + if (T->isLiteralType()) return false; if (PD.getDiagID() == 0) @@ -4105,50 +4295,35 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, if (T->isVariableArrayType()) return true; - const RecordType *RT = T->getBaseElementTypeUnsafe()->getAs<RecordType>(); + const RecordType *RT = ElemType->getAs<RecordType>(); if (!RT) return true; const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + // FIXME: Better diagnostic for incomplete class? + if (!RD->isCompleteDefinition()) + return true; + // If the class has virtual base classes, then it's not an aggregate, and - // cannot have any constexpr constructors, so is non-literal. This is better - // to diagnose than the resulting absence of constexpr constructors. + // cannot have any constexpr constructors or a trivial default constructor, + // so is non-literal. This is better to diagnose than the resulting absence + // of constexpr constructors. if (RD->getNumVBases()) { Diag(RD->getLocation(), diag::note_non_literal_virtual_base) << RD->isStruct() << RD->getNumVBases(); for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), E = RD->vbases_end(); I != E; ++I) - Diag(I->getSourceRange().getBegin(), + Diag(I->getLocStart(), diag::note_constexpr_virtual_base_here) << I->getSourceRange(); - } else if (!RD->isAggregate() && !RD->hasConstexprNonCopyMoveConstructor()) { + } else if (!RD->isAggregate() && !RD->hasConstexprNonCopyMoveConstructor() && + !RD->hasTrivialDefaultConstructor()) { Diag(RD->getLocation(), diag::note_non_literal_no_constexpr_ctors) << RD; - - switch (RD->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - break; - - case TSK_ImplicitInstantiation: - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - // If the base template had constexpr constructors which were - // instantiated as non-constexpr constructors, explain why. - for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(), - E = RD->ctor_end(); I != E; ++I) { - if ((*I)->isCopyConstructor() || (*I)->isMoveConstructor()) - continue; - - FunctionDecl *Base = (*I)->getInstantiatedFromMemberFunction(); - if (Base && Base->isConstexpr()) - CheckConstexprFunctionDecl(*I, CCK_NoteNonConstexprInstantiation); - } - } } 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()) { - Diag(I->getSourceRange().getBegin(), + Diag(I->getLocStart(), diag::note_non_literal_base_class) << RD << I->getType() << I->getSourceRange(); return true; @@ -4156,12 +4331,11 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, } for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); I != E; ++I) { - if (!(*I)->getType()->isLiteralType()) { + if (!(*I)->getType()->isLiteralType() || + (*I)->getType().isVolatileQualified()) { Diag((*I)->getLocation(), diag::note_non_literal_field) - << RD << (*I) << (*I)->getType(); - return true; - } else if ((*I)->isMutable()) { - Diag((*I)->getLocation(), diag::note_non_literal_mutable_field) << RD; + << RD << (*I) << (*I)->getType() + << (*I)->getType().isVolatileQualified(); return true; } } @@ -4211,12 +4385,73 @@ QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) { return Context.getTypeOfExprType(E); } +/// getDecltypeForExpr - Given an expr, will return the decltype for +/// that expression, according to the rules in C++11 +/// [dcl.type.simple]p4 and C++11 [expr.lambda.prim]p18. +static QualType getDecltypeForExpr(Sema &S, Expr *E) { + if (E->isTypeDependent()) + return S.Context.DependentTy; + + // C++11 [dcl.type.simple]p4: + // The type denoted by decltype(e) is defined as follows: + // + // - if e is an unparenthesized id-expression or an unparenthesized class + // member access (5.2.5), decltype(e) is the type of the entity named + // by e. If there is no such entity, or if e names a set of overloaded + // functions, the program is ill-formed; + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { + if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) + return VD->getType(); + } + if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) { + if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) + return FD->getType(); + } + + // C++11 [expr.lambda.prim]p18: + // Every occurrence of decltype((x)) where x is a possibly + // parenthesized id-expression that names an entity of automatic + // storage duration is treated as if x were transformed into an + // access to a corresponding data member of the closure type that + // would have been declared if x were an odr-use of the denoted + // entity. + using namespace sema; + if (S.getCurLambda()) { + if (isa<ParenExpr>(E)) { + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) { + if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { + QualType T = S.getCapturedDeclRefType(Var, DRE->getLocation()); + if (!T.isNull()) + return S.Context.getLValueReferenceType(T); + } + } + } + } + + + // C++11 [dcl.type.simple]p4: + // [...] + QualType T = E->getType(); + switch (E->getValueKind()) { + // - otherwise, if e is an xvalue, decltype(e) is T&&, where T is the + // type of e; + case VK_XValue: T = S.Context.getRValueReferenceType(T); break; + // - otherwise, if e is an lvalue, decltype(e) is T&, where T is the + // type of e; + case VK_LValue: T = S.Context.getLValueReferenceType(T); break; + // - otherwise, decltype(e) is the type of e. + case VK_RValue: break; + } + + return T; +} + QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) { ExprResult ER = CheckPlaceholderExpr(E); if (ER.isInvalid()) return QualType(); E = ER.take(); - return Context.getDecltypeType(E); + return Context.getDecltypeType(E, getDecltypeForExpr(*this, E)); } QualType Sema::BuildUnaryTransformType(QualType BaseType, @@ -4245,12 +4480,14 @@ QualType Sema::BuildUnaryTransformType(QualType BaseType, QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) { if (!T->isDependentType()) { + // FIXME: It isn't entirely clear whether incomplete atomic types + // are allowed or not; for simplicity, ban them for the moment. + if (RequireCompleteType(Loc, T, + PDiag(diag::err_atomic_specifier_bad_type) << 0)) + return QualType(); + int DisallowedKind = -1; - if (T->isIncompleteType()) - // FIXME: It isn't entirely clear whether incomplete atomic types - // are allowed or not; for simplicity, ban them for the moment. - DisallowedKind = 0; - else if (T->isArrayType()) + if (T->isArrayType()) DisallowedKind = 1; else if (T->isFunctionType()) DisallowedKind = 2; diff --git a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp index aa0bc08..8b19be7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp @@ -169,7 +169,7 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { // 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.getLangOptions().MicrosoftExt) + if (!S.getLangOpts().MicrosoftExt) S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << 2 /*variable and function*/; return; diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h index bb49eee..fdb861e 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h +++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h @@ -112,6 +112,11 @@ class TreeTransform { protected: Sema &SemaRef; + /// \brief The set of local declarations that have been transformed, for + /// cases where we are forced to build new declarations within the transformer + /// rather than in the subclass (e.g., lambda closure types). + llvm::DenseMap<Decl *, Decl *> TransformedLocalDecls; + public: /// \brief Initializes a new tree transformer. TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { } @@ -351,10 +356,36 @@ public: /// \brief Transform the given declaration, which is referenced from a type /// or expression. /// - /// By default, acts as the identity function on declarations. Subclasses + /// By default, acts as the identity function on declarations, unless the + /// transformer has had to transform the declaration itself. Subclasses /// may override this function to provide alternate behavior. - Decl *TransformDecl(SourceLocation Loc, Decl *D) { return D; } + Decl *TransformDecl(SourceLocation Loc, Decl *D) { + llvm::DenseMap<Decl *, Decl *>::iterator Known + = TransformedLocalDecls.find(D); + if (Known != TransformedLocalDecls.end()) + return Known->second; + + return D; + } + /// \brief Transform the attributes associated with the given declaration and + /// place them on the new declaration. + /// + /// By default, this operation does nothing. Subclasses may override this + /// behavior to transform attributes. + void transformAttrs(Decl *Old, Decl *New) { } + + /// \brief Note that a local declaration has been transformed by this + /// transformer. + /// + /// Local declarations are typically transformed via a call to + /// TransformDefinition. However, in some cases (e.g., lambda expressions), + /// the transformer itself has to transform the declarations. This routine + /// can be overridden by a subclass that keeps track of such mappings. + void transformedLocalDecl(Decl *Old, Decl *New) { + TransformedLocalDecls[Old] = New; + } + /// \brief Transform the definition of the given declaration. /// /// By default, invokes TransformDecl() to transform the declaration. @@ -418,7 +449,7 @@ public: /// Subclasses may override this function to provide alternate behavior. TemplateName TransformTemplateName(CXXScopeSpec &SS, TemplateName Name, - SourceLocation NameLoc, + SourceLocation NameLoc, QualType ObjectType = QualType(), NamedDecl *FirstQualifierInScope = 0); @@ -530,7 +561,8 @@ public: /// scope index; can be negative ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, int indexAdjustment, - llvm::Optional<unsigned> NumExpansions); + llvm::Optional<unsigned> NumExpansions, + bool ExpectParameterPack); QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL); @@ -665,7 +697,8 @@ public: QualType RebuildFunctionProtoType(QualType T, QualType *ParamTypes, unsigned NumParamTypes, - bool Variadic, unsigned Quals, + bool Variadic, bool HasTrailingReturn, + unsigned Quals, RefQualifierKind RefQualifier, const FunctionType::ExtInfo &Info); @@ -845,7 +878,6 @@ public: case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: llvm_unreachable("Tag lookup cannot find non-tags"); - return QualType(); case LookupResult::Ambiguous: // Let the LookupResult structure handle ambiguities. @@ -1291,7 +1323,20 @@ public: return getSema().BuildCXXForRangeStmt(ForLoc, ColonLoc, Range, BeginEnd, Cond, Inc, LoopVar, RParenLoc); } - + + /// \brief Build a new C++0x range-based for statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildMSDependentExistsStmt(SourceLocation KeywordLoc, + bool IsIfExists, + NestedNameSpecifierLoc QualifierLoc, + DeclarationNameInfo NameInfo, + Stmt *Nested) { + return getSema().BuildMSDependentExistsStmt(KeywordLoc, IsIfExists, + QualifierLoc, NameInfo, Nested); + } + /// \brief Attach body to a C++0x range-based for statement. /// /// By default, performs semantic analysis to finish the new statement. @@ -1450,11 +1495,14 @@ public: ExprResult RebuildMemberExpr(Expr *Base, SourceLocation OpLoc, bool isArrow, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &MemberNameInfo, ValueDecl *Member, NamedDecl *FoundDecl, const TemplateArgumentListInfo *ExplicitTemplateArgs, NamedDecl *FirstQualifierInScope) { + ExprResult BaseResult = getSema().PerformMemberExprBaseConversion(Base, + isArrow); if (!Member->getDeclName()) { // We have a reference to an unnamed field. This is always the // base of an anonymous struct/union member access, i.e. the @@ -1463,8 +1511,8 @@ public: assert(Member->getType()->isRecordType() && "unnamed member not of record type?"); - ExprResult BaseResult = - getSema().PerformObjectMemberConversion(Base, + BaseResult = + getSema().PerformObjectMemberConversion(BaseResult.take(), QualifierLoc.getNestedNameSpecifier(), FoundDecl, Member); if (BaseResult.isInvalid()) @@ -1482,9 +1530,6 @@ public: CXXScopeSpec SS; SS.Adopt(QualifierLoc); - ExprResult BaseResult = getSema().DefaultFunctionArrayConversion(Base); - if (BaseResult.isInvalid()) - return ExprError(); Base = BaseResult.take(); QualType BaseType = Base->getType(); @@ -1495,7 +1540,8 @@ public: R.resolveKind(); return getSema().BuildMemberReferenceExpr(Base, BaseType, OpLoc, isArrow, - SS, FirstQualifierInScope, + SS, TemplateKWLoc, + FirstQualifierInScope, R, ExplicitTemplateArgs); } @@ -1559,7 +1605,8 @@ public: DeclarationNameInfo NameInfo(&Accessor, AccessorLoc); return getSema().BuildMemberReferenceExpr(Base, Base->getType(), OpLoc, /*IsArrow*/ false, - SS, /*FirstQualifierInScope*/ 0, + SS, SourceLocation(), + /*FirstQualifierInScope*/ 0, NameInfo, /* TemplateArgs */ 0); } @@ -1629,10 +1676,9 @@ public: /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. ExprResult RebuildParenListExpr(SourceLocation LParenLoc, - MultiExprArg SubExprs, - SourceLocation RParenLoc) { - return getSema().ActOnParenOrParenListExpr(LParenLoc, RParenLoc, - move(SubExprs)); + MultiExprArg SubExprs, + SourceLocation RParenLoc) { + return getSema().ActOnParenListExpr(LParenLoc, RParenLoc, move(SubExprs)); } /// \brief Build a new address-of-label expression. @@ -1736,8 +1782,6 @@ public: default: llvm_unreachable("Invalid C++ named cast"); } - - return ExprError(); } /// \brief Build a new C++ static_cast expression. @@ -1878,6 +1922,7 @@ public: ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc, QualType ThisType, bool isImplicit) { + getSema().CheckCXXThisCapture(ThisLoc); return getSema().Owned( new (getSema().Context) CXXThisExpr(ThisLoc, ThisType, isImplicit)); @@ -1928,9 +1973,8 @@ public: QualType AllocatedType, TypeSourceInfo *AllocatedTypeInfo, Expr *ArraySize, - SourceLocation ConstructorLParen, - MultiExprArg ConstructorArgs, - SourceLocation ConstructorRParen) { + SourceRange DirectInitRange, + Expr *Initializer) { return getSema().BuildCXXNew(StartLoc, UseGlobal, PlacementLParen, move(PlacementArgs), @@ -1939,9 +1983,8 @@ public: AllocatedType, AllocatedTypeInfo, ArraySize, - ConstructorLParen, - move(ConstructorArgs), - ConstructorRParen); + DirectInitRange, + Initializer); } /// \brief Build a new C++ "delete" expression. @@ -1979,6 +2022,17 @@ public: 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. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildTypeTrait(TypeTrait Trait, + SourceLocation StartLoc, + ArrayRef<TypeSourceInfo *> Args, + SourceLocation RParenLoc) { + return getSema().BuildTypeTrait(Trait, StartLoc, Args, RParenLoc); + } + /// \brief Build a new array type trait expression. /// /// By default, performs semantic analysis to build the new expression. @@ -2009,14 +2063,15 @@ public: /// Subclasses may override this routine to provide different behavior. ExprResult RebuildDependentScopeDeclRefExpr( NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs) { CXXScopeSpec SS; SS.Adopt(QualifierLoc); - if (TemplateArgs) - return getSema().BuildQualifiedTemplateIdExpr(SS, NameInfo, - *TemplateArgs); + if (TemplateArgs || TemplateKWLoc.isValid()) + return getSema().BuildQualifiedTemplateIdExpr(SS, TemplateKWLoc, + NameInfo, TemplateArgs); return getSema().BuildQualifiedDeclarationNameExpr(SS, NameInfo); } @@ -2026,10 +2081,12 @@ public: /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. ExprResult RebuildTemplateIdExpr(const CXXScopeSpec &SS, - LookupResult &R, - bool RequiresADL, - const TemplateArgumentListInfo &TemplateArgs) { - return getSema().BuildTemplateIdExpr(SS, R, RequiresADL, TemplateArgs); + SourceLocation TemplateKWLoc, + LookupResult &R, + bool RequiresADL, + const TemplateArgumentListInfo *TemplateArgs) { + return getSema().BuildTemplateIdExpr(SS, TemplateKWLoc, R, RequiresADL, + TemplateArgs); } /// \brief Build a new object-construction expression. @@ -2094,6 +2151,7 @@ public: bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs) { @@ -2102,7 +2160,8 @@ public: return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType, OperatorLoc, IsArrow, - SS, FirstQualifierInScope, + SS, TemplateKWLoc, + FirstQualifierInScope, MemberNameInfo, TemplateArgs); } @@ -2111,20 +2170,21 @@ public: /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - ExprResult RebuildUnresolvedMemberExpr(Expr *BaseE, - QualType BaseType, - SourceLocation OperatorLoc, - bool IsArrow, - NestedNameSpecifierLoc QualifierLoc, - NamedDecl *FirstQualifierInScope, - LookupResult &R, + ExprResult RebuildUnresolvedMemberExpr(Expr *BaseE, QualType BaseType, + SourceLocation OperatorLoc, + bool IsArrow, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, + NamedDecl *FirstQualifierInScope, + LookupResult &R, const TemplateArgumentListInfo *TemplateArgs) { CXXScopeSpec SS; SS.Adopt(QualifierLoc); return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType, OperatorLoc, IsArrow, - SS, FirstQualifierInScope, + SS, TemplateKWLoc, + FirstQualifierInScope, R, TemplateArgs); } @@ -2150,7 +2210,35 @@ public: OperatorLoc, Pack, PackLoc, RParenLoc); } - + + /// \brief Build a new Objective-C array literal. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildObjCArrayLiteral(SourceRange Range, + Expr **Elements, unsigned NumElements) { + return getSema().BuildObjCArrayLiteral(Range, + MultiExprArg(Elements, NumElements)); + } + + ExprResult RebuildObjCSubscriptRefExpr(SourceLocation RB, + Expr *Base, Expr *Key, + ObjCMethodDecl *getterMethod, + ObjCMethodDecl *setterMethod) { + return getSema().BuildObjCSubscriptExpression(RB, Base, Key, + getterMethod, setterMethod); + } + + /// \brief Build a new Objective-C dictionary literal. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildObjCDictionaryLiteral(SourceRange Range, + ObjCDictionaryElement *Elements, + unsigned NumElements) { + return getSema().BuildObjCDictionaryLiteral(Range, Elements, NumElements); + } + /// \brief Build a new Objective-C @encode expression. /// /// By default, performs semantic analysis to build the new expression. @@ -2215,7 +2303,8 @@ public: return move(Result); return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(), - /*FIXME:*/IvarLoc, IsArrow, SS, + /*FIXME:*/IvarLoc, IsArrow, + SS, SourceLocation(), /*FirstQualifierInScope=*/0, R, /*TemplateArgs=*/0); @@ -2226,8 +2315,8 @@ public: /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. ExprResult RebuildObjCPropertyRefExpr(Expr *BaseArg, - ObjCPropertyDecl *Property, - SourceLocation PropertyLoc) { + ObjCPropertyDecl *Property, + SourceLocation PropertyLoc) { CXXScopeSpec SS; ExprResult Base = getSema().Owned(BaseArg); LookupResult R(getSema(), Property->getDeclName(), PropertyLoc, @@ -2244,7 +2333,7 @@ public: return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(), /*FIXME:*/PropertyLoc, IsArrow, - SS, + SS, SourceLocation(), /*FirstQualifierInScope=*/0, R, /*TemplateArgs=*/0); @@ -2286,7 +2375,8 @@ public: return move(Result); return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(), - /*FIXME:*/IsaLoc, IsArrow, SS, + /*FIXME:*/IsaLoc, IsArrow, + SS, SourceLocation(), /*FirstQualifierInScope=*/0, R, /*TemplateArgs=*/0); @@ -2309,7 +2399,8 @@ public: // Build a reference to the __builtin_shufflevector builtin FunctionDecl *Builtin = cast<FunctionDecl>(*Lookup.first); ExprResult Callee - = SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(Builtin, Builtin->getType(), + = SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(Builtin, false, + Builtin->getType(), VK_LValue, BuiltinLoc)); Callee = SemaRef.UsualUnaryConversions(Callee.take()); if (Callee.isInvalid()) @@ -2625,10 +2716,13 @@ TreeTransform<Derived>::TransformNestedNameSpecifierLoc( return NestedNameSpecifierLoc(); if (TL.getType()->isDependentType() || TL.getType()->isRecordType() || - (SemaRef.getLangOptions().CPlusPlus0x && + (SemaRef.getLangOpts().CPlusPlus0x && TL.getType()->isEnumeralType())) { assert(!TL.getType().hasLocalQualifiers() && "Can't get cv-qualifiers here"); + if (TL.getType()->isEnumeralType()) + SemaRef.Diag(TL.getBeginLoc(), + diag::warn_cxx98_compat_enum_nested_name_spec); SS.Extend(SemaRef.Context, /*FIXME:*/SourceLocation(), TL, Q.getLocalEndLoc()); break; @@ -2797,7 +2891,6 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS, // These should be getting filtered out before they reach the AST. llvm_unreachable("overloaded function decl survived to here"); - return TemplateName(); } template<typename Derived> @@ -2884,8 +2977,9 @@ bool TreeTransform<Derived>::TransformTemplateArgument( Expr *SourceExpr = Input.getSourceDeclExpression(); if (SourceExpr) { EnterExpressionEvaluationContext Unevaluated(getSema(), - Sema::Unevaluated); + Sema::ConstantEvaluated); ExprResult E = getDerived().TransformExpr(SourceExpr); + E = SemaRef.ActOnConstantExpression(E); SourceExpr = (E.isInvalid() ? 0 : E.take()); } @@ -2918,14 +3012,15 @@ bool TreeTransform<Derived>::TransformTemplateArgument( llvm_unreachable("Caller should expand pack expansions"); case TemplateArgument::Expression: { - // Template argument expressions are not potentially evaluated. + // Template argument expressions are constant expressions. EnterExpressionEvaluationContext Unevaluated(getSema(), - Sema::Unevaluated); + Sema::ConstantEvaluated); Expr *InputExpr = Input.getSourceExpression(); if (!InputExpr) InputExpr = Input.getArgument().getAsExpr(); ExprResult E = getDerived().TransformExpr(InputExpr); + E = SemaRef.ActOnConstantExpression(E); if (E.isInvalid()) return true; Output = TemplateArgumentLoc(TemplateArgument(E.take()), E.take()); return false; @@ -3168,6 +3263,9 @@ QualType TreeTransform<Derived>::TransformType(QualType T) { template<typename Derived> TypeSourceInfo *TreeTransform<Derived>::TransformType(TypeSourceInfo *DI) { + // Refine the base location to the type's location. + TemporaryBase Rebase(*this, DI->getTypeLoc().getBeginLoc(), + getDerived().getBaseEntity()); if (getDerived().AlreadyTransformed(DI->getType())) return DI; @@ -3195,7 +3293,6 @@ TreeTransform<Derived>::TransformType(TypeLocBuilder &TLB, TypeLoc T) { } llvm_unreachable("unhandled type loc!"); - return QualType(); } /// FIXME: By default, this routine adds type qualifiers only to types @@ -3294,7 +3391,7 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL, TemplateName Template = getDerived().RebuildTemplateName(SS, *SpecTL.getTypePtr()->getIdentifier(), - SpecTL.getNameLoc(), + SpecTL.getTemplateNameLoc(), ObjectType, UnqualLookup); if (Template.isNull()) return TypeLoc(); @@ -3351,7 +3448,7 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSInfo, TemplateName Template = getDerived().RebuildTemplateName(SS, *SpecTL.getTypePtr()->getIdentifier(), - SpecTL.getNameLoc(), + SpecTL.getTemplateNameLoc(), ObjectType, UnqualLookup); if (Template.isNull()) return 0; @@ -3574,15 +3671,21 @@ TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB, if (Result.isNull()) return QualType(); } - - ConstantArrayTypeLoc NewTL = TLB.push<ConstantArrayTypeLoc>(Result); + + // We might have either a ConstantArrayType or a VariableArrayType now: + // a ConstantArrayType is allowed to have an element type which is a + // VariableArrayType if the type is dependent. Fortunately, all array + // types have the same location layout. + ArrayTypeLoc NewTL = TLB.push<ArrayTypeLoc>(Result); NewTL.setLBracketLoc(TL.getLBracketLoc()); NewTL.setRBracketLoc(TL.getRBracketLoc()); Expr *Size = TL.getSizeExpr(); if (Size) { - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated(SemaRef, + Sema::ConstantEvaluated); Size = getDerived().TransformExpr(Size).template takeAs<Expr>(); + Size = SemaRef.ActOnConstantExpression(Size).take(); } NewTL.setSizeExpr(Size); @@ -3626,9 +3729,6 @@ TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB, if (ElementType.isNull()) return QualType(); - // Array bounds are not potentially evaluated contexts - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); - ExprResult SizeResult = getDerived().TransformExpr(T->getSizeExpr()); if (SizeResult.isInvalid()) @@ -3666,8 +3766,9 @@ TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB, if (ElementType.isNull()) return QualType(); - // Array bounds are not potentially evaluated contexts - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + // Array bounds are constant expressions. + EnterExpressionEvaluationContext Unevaluated(SemaRef, + Sema::ConstantEvaluated); // Prefer the expression from the TypeLoc; the other may have been uniqued. Expr *origSize = TL.getSizeExpr(); @@ -3675,6 +3776,7 @@ TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB, ExprResult sizeResult = getDerived().TransformExpr(origSize); + sizeResult = SemaRef.ActOnConstantExpression(sizeResult); if (sizeResult.isInvalid()) return QualType(); @@ -3714,10 +3816,12 @@ QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType( if (ElementType.isNull()) return QualType(); - // Vector sizes are not potentially evaluated contexts - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + // Vector sizes are constant expressions. + EnterExpressionEvaluationContext Unevaluated(SemaRef, + Sema::ConstantEvaluated); ExprResult Size = getDerived().TransformExpr(T->getSizeExpr()); + Size = SemaRef.ActOnConstantExpression(Size); if (Size.isInvalid()) return QualType(); @@ -3796,12 +3900,14 @@ template<typename Derived> ParmVarDecl * TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm, int indexAdjustment, - llvm::Optional<unsigned> NumExpansions) { + llvm::Optional<unsigned> NumExpansions, + bool ExpectParameterPack) { TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); TypeSourceInfo *NewDI = 0; if (NumExpansions && isa<PackExpansionType>(OldDI->getType())) { // If we're substituting into a pack expansion type and we know the + // length we want to expand to, just substitute for the pattern. TypeLoc OldTL = OldDI->getTypeLoc(); PackExpansionTypeLoc OldExpansionTL = cast<PackExpansionTypeLoc>(OldTL); @@ -3898,7 +4004,8 @@ bool TreeTransform<Derived>:: ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm, indexAdjustment++, - OrigNumExpansions); + OrigNumExpansions, + /*ExpectParameterPack=*/false); if (!NewParm) return true; @@ -3914,7 +4021,8 @@ bool TreeTransform<Derived>:: ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm, indexAdjustment++, - OrigNumExpansions); + OrigNumExpansions, + /*ExpectParameterPack=*/false); if (!NewParm) return true; @@ -3938,11 +4046,13 @@ bool TreeTransform<Derived>:: Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); NewParm = getDerived().TransformFunctionTypeParam(OldParm, indexAdjustment, - NumExpansions); + NumExpansions, + /*ExpectParameterPack=*/true); } else { NewParm = getDerived().TransformFunctionTypeParam(OldParm, indexAdjustment, - llvm::Optional<unsigned>()); + llvm::Optional<unsigned>(), + /*ExpectParameterPack=*/false); } if (!NewParm) @@ -4096,6 +4206,7 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB, ParamTypes.data(), ParamTypes.size(), T->isVariadic(), + T->hasTrailingReturn(), T->getTypeQuals(), T->getRefQualifier(), T->getExtInfo()); @@ -4192,6 +4303,10 @@ QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB, if (E.isInvalid()) return QualType(); + E = SemaRef.HandleExprEvaluationContextForTypeof(E.get()); + if (E.isInvalid()) + return QualType(); + QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || E.get() != TL.getUnderlyingExpr()) { @@ -4239,12 +4354,17 @@ QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB, const DecltypeType *T = TL.getTypePtr(); // decltype expressions are not potentially evaluated contexts - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated, 0, + /*IsDecltype=*/ true); ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr()); if (E.isInvalid()) return QualType(); + E = getSema().ActOnDecltypeExpression(E.take()); + if (E.isInvalid()) + return QualType(); + QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || E.get() != T->getUnderlyingExpr()) { @@ -4549,9 +4669,10 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType( if (isa<DependentTemplateSpecializationType>(Result)) { DependentTemplateSpecializationTypeLoc NewTL = TLB.push<DependentTemplateSpecializationTypeLoc>(Result); - NewTL.setKeywordLoc(TL.getTemplateNameLoc()); + NewTL.setElaboratedKeywordLoc(SourceLocation()); NewTL.setQualifierLoc(NestedNameSpecifierLoc()); - NewTL.setNameLoc(TL.getTemplateNameLoc()); + NewTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc()); + NewTL.setTemplateNameLoc(TL.getTemplateNameLoc()); NewTL.setLAngleLoc(TL.getLAngleLoc()); NewTL.setRAngleLoc(TL.getRAngleLoc()); for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i) @@ -4561,6 +4682,7 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType( TemplateSpecializationTypeLoc NewTL = TLB.push<TemplateSpecializationTypeLoc>(Result); + NewTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc()); NewTL.setTemplateNameLoc(TL.getTemplateNameLoc()); NewTL.setLAngleLoc(TL.getLAngleLoc()); NewTL.setRAngleLoc(TL.getRAngleLoc()); @@ -4599,10 +4721,10 @@ QualType TreeTransform<Derived>::TransformDependentTemplateSpecializationType( DependentTemplateSpecializationTypeLoc NewTL = TLB.push<DependentTemplateSpecializationTypeLoc>(Result); - NewTL.setKeywordLoc(TL.getKeywordLoc()); - + NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); NewTL.setQualifierLoc(SS.getWithLocInContext(SemaRef.Context)); - NewTL.setNameLoc(TL.getNameLoc()); + NewTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc()); + NewTL.setTemplateNameLoc(TL.getTemplateNameLoc()); NewTL.setLAngleLoc(TL.getLAngleLoc()); NewTL.setRAngleLoc(TL.getRAngleLoc()); for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i) @@ -4612,14 +4734,15 @@ QualType TreeTransform<Derived>::TransformDependentTemplateSpecializationType( QualType Result = getDerived().RebuildTemplateSpecializationType(Template, - TL.getNameLoc(), + TL.getTemplateNameLoc(), NewTemplateArgs); if (!Result.isNull()) { /// FIXME: Wrap this in an elaborated-type-specifier? TemplateSpecializationTypeLoc NewTL = TLB.push<TemplateSpecializationTypeLoc>(Result); - NewTL.setTemplateNameLoc(TL.getNameLoc()); + NewTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc()); + NewTL.setTemplateNameLoc(TL.getTemplateNameLoc()); NewTL.setLAngleLoc(TL.getLAngleLoc()); NewTL.setRAngleLoc(TL.getRAngleLoc()); for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i) @@ -4669,7 +4792,7 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB, if (getDerived().AlwaysRebuild() || QualifierLoc != TL.getQualifierLoc() || NamedT != T->getNamedType()) { - Result = getDerived().RebuildElaboratedType(TL.getKeywordLoc(), + Result = getDerived().RebuildElaboratedType(TL.getElaboratedKeywordLoc(), T->getKeyword(), QualifierLoc, NamedT); if (Result.isNull()) @@ -4677,7 +4800,7 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB, } ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); - NewTL.setKeywordLoc(TL.getKeywordLoc()); + NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); NewTL.setQualifierLoc(QualifierLoc); return Result; } @@ -4753,7 +4876,7 @@ QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB, QualType Result = getDerived().RebuildDependentNameType(T->getKeyword(), - TL.getKeywordLoc(), + TL.getElaboratedKeywordLoc(), QualifierLoc, T->getIdentifier(), TL.getNameLoc()); @@ -4765,11 +4888,11 @@ QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB, TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc()); ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); - NewTL.setKeywordLoc(TL.getKeywordLoc()); + NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); NewTL.setQualifierLoc(QualifierLoc); } else { DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result); - NewTL.setKeywordLoc(TL.getKeywordLoc()); + NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); NewTL.setQualifierLoc(QualifierLoc); NewTL.setNameLoc(TL.getNameLoc()); } @@ -4814,7 +4937,7 @@ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, = getDerived().RebuildDependentTemplateSpecializationType(T->getKeyword(), QualifierLoc, T->getIdentifier(), - TL.getNameLoc(), + TL.getTemplateNameLoc(), NewTemplateArgs); if (Result.isNull()) return QualType(); @@ -4825,7 +4948,8 @@ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, // Copy information relevant to the template specialization. TemplateSpecializationTypeLoc NamedTL = TLB.push<TemplateSpecializationTypeLoc>(NamedT); - NamedTL.setTemplateNameLoc(TL.getNameLoc()); + NamedTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc()); + NamedTL.setTemplateNameLoc(TL.getTemplateNameLoc()); NamedTL.setLAngleLoc(TL.getLAngleLoc()); NamedTL.setRAngleLoc(TL.getRAngleLoc()); for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I) @@ -4833,14 +4957,15 @@ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, // Copy information relevant to the elaborated type. ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); - NewTL.setKeywordLoc(TL.getKeywordLoc()); + NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); NewTL.setQualifierLoc(QualifierLoc); } else if (isa<DependentTemplateSpecializationType>(Result)) { DependentTemplateSpecializationTypeLoc SpecTL = TLB.push<DependentTemplateSpecializationTypeLoc>(Result); - SpecTL.setKeywordLoc(TL.getKeywordLoc()); + SpecTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); SpecTL.setQualifierLoc(QualifierLoc); - SpecTL.setNameLoc(TL.getNameLoc()); + SpecTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc()); + SpecTL.setTemplateNameLoc(TL.getTemplateNameLoc()); SpecTL.setLAngleLoc(TL.getLAngleLoc()); SpecTL.setRAngleLoc(TL.getRAngleLoc()); for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I) @@ -4848,7 +4973,8 @@ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, } else { TemplateSpecializationTypeLoc SpecTL = TLB.push<TemplateSpecializationTypeLoc>(Result); - SpecTL.setTemplateNameLoc(TL.getNameLoc()); + SpecTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc()); + SpecTL.setTemplateNameLoc(TL.getTemplateNameLoc()); SpecTL.setLAngleLoc(TL.getLAngleLoc()); SpecTL.setRAngleLoc(TL.getRAngleLoc()); for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I) @@ -4927,6 +5053,8 @@ template<typename Derived> StmtResult TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr) { + Sema::CompoundScopeRAII CompoundScope(getSema()); + bool SubStmtInvalid = false; bool SubStmtChanged = false; ASTOwningVector<Stmt*> Statements(getSema()); @@ -4966,16 +5094,18 @@ StmtResult TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) { ExprResult LHS, RHS; { - // The case value expressions are not potentially evaluated. - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated(SemaRef, + Sema::ConstantEvaluated); // Transform the left-hand case value. LHS = getDerived().TransformExpr(S->getLHS()); + LHS = SemaRef.ActOnConstantExpression(LHS); if (LHS.isInvalid()) return StmtError(); // Transform the right-hand case value (for the GNU case-range extension). RHS = getDerived().TransformExpr(S->getRHS()); + RHS = SemaRef.ActOnConstantExpression(RHS); if (RHS.isInvalid()) return StmtError(); } @@ -5284,6 +5414,7 @@ TreeTransform<Derived>::TransformIndirectGotoStmt(IndirectGotoStmt *S) { ExprResult Target = getDerived().TransformExpr(S->getTarget()); if (Target.isInvalid()) return StmtError(); + Target = SemaRef.MaybeCreateExprWithCleanups(Target.take()); if (!getDerived().AlwaysRebuild() && Target.get() == S->getTarget()) @@ -5696,10 +5827,18 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) { ExprResult Cond = getDerived().TransformExpr(S->getCond()); if (Cond.isInvalid()) return StmtError(); + if (Cond.get()) + Cond = SemaRef.CheckBooleanCondition(Cond.take(), S->getColonLoc()); + if (Cond.isInvalid()) + return StmtError(); + if (Cond.get()) + Cond = SemaRef.MaybeCreateExprWithCleanups(Cond.take()); ExprResult Inc = getDerived().TransformExpr(S->getInc()); if (Inc.isInvalid()) return StmtError(); + if (Inc.get()) + Inc = SemaRef.MaybeCreateExprWithCleanups(Inc.take()); StmtResult LoopVar = getDerived().TransformStmt(S->getLoopVarStmt()); if (LoopVar.isInvalid()) @@ -5739,6 +5878,75 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) { template<typename Derived> StmtResult +TreeTransform<Derived>::TransformMSDependentExistsStmt( + MSDependentExistsStmt *S) { + // Transform the nested-name-specifier, if any. + NestedNameSpecifierLoc QualifierLoc; + if (S->getQualifierLoc()) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(S->getQualifierLoc()); + if (!QualifierLoc) + return StmtError(); + } + + // Transform the declaration name. + DeclarationNameInfo NameInfo = S->getNameInfo(); + if (NameInfo.getName()) { + NameInfo = getDerived().TransformDeclarationNameInfo(NameInfo); + if (!NameInfo.getName()) + return StmtError(); + } + + // Check whether anything changed. + if (!getDerived().AlwaysRebuild() && + QualifierLoc == S->getQualifierLoc() && + NameInfo.getName() == S->getNameInfo().getName()) + return S; + + // Determine whether this name exists, if we can. + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + bool Dependent = false; + switch (getSema().CheckMicrosoftIfExistsSymbol(/*S=*/0, SS, NameInfo)) { + case Sema::IER_Exists: + if (S->isIfExists()) + break; + + return new (getSema().Context) NullStmt(S->getKeywordLoc()); + + case Sema::IER_DoesNotExist: + if (S->isIfNotExists()) + break; + + return new (getSema().Context) NullStmt(S->getKeywordLoc()); + + case Sema::IER_Dependent: + Dependent = true; + break; + + case Sema::IER_Error: + return StmtError(); + } + + // We need to continue with the instantiation, so do so now. + StmtResult SubStmt = getDerived().TransformCompoundStmt(S->getSubStmt()); + if (SubStmt.isInvalid()) + return StmtError(); + + // If we have resolved the name, just transform to the substatement. + if (!Dependent) + return SubStmt; + + // The name is still dependent, so build a dependent expression again. + return getDerived().RebuildMSDependentExistsStmt(S->getKeywordLoc(), + S->isIfExists(), + QualifierLoc, + NameInfo, + SubStmt.get()); +} + +template<typename Derived> +StmtResult TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) { StmtResult TryBlock; // = getDerived().TransformCompoundStmt(S->getTryBlock()); if(TryBlock.isInvalid()) return StmtError(); @@ -5829,7 +6037,7 @@ TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) { // Mark it referenced in the new context regardless. // FIXME: this is a bit instantiation-specific. - SemaRef.MarkDeclarationReferenced(E->getLocation(), ND); + SemaRef.MarkDeclRefReferenced(E); return SemaRef.Owned(E); } @@ -5881,6 +6089,12 @@ TreeTransform<Derived>::TransformCharacterLiteral(CharacterLiteral *E) { template<typename Derived> ExprResult +TreeTransform<Derived>::TransformUserDefinedLiteral(UserDefinedLiteral *E) { + return SemaRef.MaybeBindToTemporary(E); +} + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) { ExprResult ControllingExpr = getDerived().TransformExpr(E->getControllingExpr()); @@ -6020,6 +6234,28 @@ TreeTransform<Derived>::TransformOpaqueValueExpr(OpaqueValueExpr *E) { template<typename Derived> ExprResult +TreeTransform<Derived>::TransformPseudoObjectExpr(PseudoObjectExpr *E) { + // Rebuild the syntactic form. The original syntactic form has + // opaque-value expressions in it, so strip those away and rebuild + // the result. This is a really awful way of doing this, but the + // better solution (rebuilding the semantic expressions and + // rebinding OVEs as necessary) doesn't work; we'd need + // TreeTransform to not strip away implicit conversions. + Expr *newSyntacticForm = SemaRef.recreateSyntacticForm(E); + ExprResult result = getDerived().TransformExpr(newSyntacticForm); + if (result.isInvalid()) return ExprError(); + + // If that gives us a pseudo-object result back, the pseudo-object + // expression must have been an lvalue-to-rvalue conversion which we + // should reapply. + if (result.get()->hasPlaceholderType(BuiltinType::PseudoObject)) + result = SemaRef.checkPseudoObjectRValue(result.take()); + + return result; +} + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformUnaryExprOrTypeTraitExpr( UnaryExprOrTypeTraitExpr *E) { if (E->isArgumentType()) { @@ -6037,20 +6273,17 @@ TreeTransform<Derived>::TransformUnaryExprOrTypeTraitExpr( E->getSourceRange()); } - ExprResult SubExpr; - { - // C++0x [expr.sizeof]p1: - // The operand is either an expression, which is an unevaluated operand - // [...] - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + // C++0x [expr.sizeof]p1: + // The operand is either an expression, which is an unevaluated operand + // [...] + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); - SubExpr = getDerived().TransformExpr(E->getArgumentExpr()); - if (SubExpr.isInvalid()) - return ExprError(); + ExprResult SubExpr = getDerived().TransformExpr(E->getArgumentExpr()); + if (SubExpr.isInvalid()) + return ExprError(); - if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getArgumentExpr()) - return SemaRef.Owned(E); - } + if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getArgumentExpr()) + return SemaRef.Owned(E); return getDerived().RebuildUnaryExprOrTypeTrait(SubExpr.get(), E->getOperatorLoc(), @@ -6099,7 +6332,7 @@ TreeTransform<Derived>::TransformCallExpr(CallExpr *E) { if (!getDerived().AlwaysRebuild() && Callee.get() == E->getCallee() && !ArgChanged) - return SemaRef.Owned(E); + return SemaRef.MaybeBindToTemporary(E);; // FIXME: Wrong source location information for the '('. SourceLocation FakeLParenLoc @@ -6124,6 +6357,7 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) { if (!QualifierLoc) return ExprError(); } + SourceLocation TemplateKWLoc = E->getTemplateKeywordLoc(); ValueDecl *Member = cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getMemberLoc(), @@ -6150,7 +6384,8 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) { // Mark it referenced in the new context regardless. // FIXME: this is a bit instantiation-specific. - SemaRef.MarkDeclarationReferenced(E->getMemberLoc(), Member); + SemaRef.MarkMemberReferenced(E); + return SemaRef.Owned(E); } @@ -6177,6 +6412,7 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) { return getDerived().RebuildMemberExpr(Base.get(), FakeOperatorLoc, E->isArrow(), QualifierLoc, + TemplateKWLoc, E->getMemberNameInfo(), Member, FoundDecl, @@ -6312,7 +6548,7 @@ TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) { if (!getDerived().AlwaysRebuild() && OldT == NewT && Init.get() == E->getInitializer()) - return SemaRef.Owned(E); + return SemaRef.MaybeBindToTemporary(E); // Note: the expression type doesn't necessarily match the // type-as-written, but that's okay, because it should always be @@ -6500,14 +6736,20 @@ TreeTransform<Derived>::TransformAddrLabelExpr(AddrLabelExpr *E) { template<typename Derived> ExprResult TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E) { + SemaRef.ActOnStartStmtExpr(); StmtResult SubStmt = getDerived().TransformCompoundStmt(E->getSubStmt(), true); - if (SubStmt.isInvalid()) + if (SubStmt.isInvalid()) { + SemaRef.ActOnStmtExprError(); return ExprError(); + } if (!getDerived().AlwaysRebuild() && - SubStmt.get() == E->getSubStmt()) - return SemaRef.Owned(E); + SubStmt.get() == E->getSubStmt()) { + // Calling this an 'error' is unintuitive, but it does the right thing. + SemaRef.ActOnStmtExprError(); + return SemaRef.MaybeBindToTemporary(E); + } return getDerived().RebuildStmtExpr(E->getLParenLoc(), SubStmt.get(), @@ -6555,7 +6797,6 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { case OO_Array_New: case OO_Array_Delete: llvm_unreachable("new and delete operators cannot use CXXOperatorCallExpr"); - return ExprError(); case OO_Call: { // This is a call to an object's operator(). @@ -6592,12 +6833,10 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { case OO_Conditional: llvm_unreachable("conditional operator is not actually overloadable"); - return ExprError(); case OO_None: case NUM_OVERLOADED_OPERATORS: llvm_unreachable("not an overloaded operator?"); - return ExprError(); } ExprResult Callee = getDerived().TransformExpr(E->getCallee()); @@ -6619,7 +6858,7 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { Callee.get() == E->getCallee() && First.get() == E->getArg(0) && (E->getNumArgs() != 2 || Second.get() == E->getArg(1))) - return SemaRef.Owned(E); + return SemaRef.MaybeBindToTemporary(E); return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(), E->getOperatorLoc(), @@ -6657,7 +6896,7 @@ TreeTransform<Derived>::TransformCUDAKernelCallExpr(CUDAKernelCallExpr *E) { if (!getDerived().AlwaysRebuild() && Callee.get() == E->getCallee() && !ArgChanged) - return SemaRef.Owned(E); + return SemaRef.MaybeBindToTemporary(E); // FIXME: Wrong source location information for the '('. SourceLocation FakeLParenLoc @@ -6769,11 +7008,11 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) { E->getLocEnd()); } - // We don't know whether the expression is potentially evaluated until - // after we perform semantic analysis, so the expression is potentially + // We don't know whether the subexpression is potentially evaluated until + // after we perform semantic analysis. We speculatively assume it is + // unevaluated; it will get fixed later if the subexpression is in fact // potentially evaluated. - EnterExpressionEvaluationContext Unevaluated(SemaRef, - Sema::PotentiallyPotentiallyEvaluated); + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand()); if (SubExpr.isInvalid()) @@ -6808,9 +7047,6 @@ TreeTransform<Derived>::TransformCXXUuidofExpr(CXXUuidofExpr *E) { E->getLocEnd()); } - // We don't know whether the expression is potentially evaluated until - // after we perform semantic analysis, so the expression is potentially - // potentially evaluated. EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand()); @@ -6851,9 +7087,12 @@ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) { T = getSema().Context.getPointerType( getSema().Context.getRecordType(cast<CXXRecordDecl>(DC))); - if (!getDerived().AlwaysRebuild() && T == E->getType()) + if (!getDerived().AlwaysRebuild() && T == E->getType()) { + // Make sure that we capture 'this'. + getSema().CheckCXXThisCapture(E->getLocStart()); return SemaRef.Owned(E); - + } + return getDerived().RebuildCXXThisExpr(E->getLocStart(), T, E->isImplicit()); } @@ -6925,24 +7164,17 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { if (getDerived().TransformExprs(E->getPlacementArgs(), E->getNumPlacementArgs(), true, PlacementArgs, &ArgumentChanged)) - return ExprError(); - - // transform the constructor arguments (if any). - ASTOwningVector<Expr*> ConstructorArgs(SemaRef); - if (TransformExprs(E->getConstructorArgs(), E->getNumConstructorArgs(), true, - ConstructorArgs, &ArgumentChanged)) - return ExprError(); - - // Transform constructor, new operator, and delete operator. - CXXConstructorDecl *Constructor = 0; - if (E->getConstructor()) { - Constructor = cast_or_null<CXXConstructorDecl>( - getDerived().TransformDecl(E->getLocStart(), - E->getConstructor())); - if (!Constructor) - return ExprError(); - } + return ExprError(); + // Transform the initializer (if any). + Expr *OldInit = E->getInitializer(); + ExprResult NewInit; + if (OldInit) + NewInit = getDerived().TransformExpr(OldInit); + if (NewInit.isInvalid()) + return ExprError(); + + // Transform new operator and delete operator. FunctionDecl *OperatorNew = 0; if (E->getOperatorNew()) { OperatorNew = cast_or_null<FunctionDecl>( @@ -6964,31 +7196,28 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { if (!getDerived().AlwaysRebuild() && AllocTypeInfo == E->getAllocatedTypeSourceInfo() && ArraySize.get() == E->getArraySize() && - Constructor == E->getConstructor() && + NewInit.get() == OldInit && OperatorNew == E->getOperatorNew() && OperatorDelete == E->getOperatorDelete() && !ArgumentChanged) { // Mark any declarations we need as referenced. // FIXME: instantiation-specific. - if (Constructor) - SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor); if (OperatorNew) - SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorNew); + SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorNew); if (OperatorDelete) - SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorDelete); + SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorDelete); - if (E->isArray() && Constructor && - !E->getAllocatedType()->isDependentType()) { + if (E->isArray() && !E->getAllocatedType()->isDependentType()) { QualType ElementType = SemaRef.Context.getBaseElementType(E->getAllocatedType()); if (const RecordType *RecordT = ElementType->getAs<RecordType>()) { CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordT->getDecl()); if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(Record)) { - SemaRef.MarkDeclarationReferenced(E->getLocStart(), Destructor); + SemaRef.MarkFunctionReferenced(E->getLocStart(), Destructor); } } } - + return SemaRef.Owned(E); } @@ -7018,7 +7247,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { } } } - + return getDerived().RebuildCXXNewExpr(E->getLocStart(), E->isGlobalNew(), /*FIXME:*/E->getLocStart(), @@ -7028,13 +7257,8 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { AllocType, AllocTypeInfo, ArraySize.get(), - /*FIXME:*/E->hasInitializer() - ? E->getLocStart() - : SourceLocation(), - move_arg(ConstructorArgs), - /*FIXME:*/E->hasInitializer() - ? E->getLocEnd() - : SourceLocation()); + E->getDirectInitRange(), + NewInit.take()); } template<typename Derived> @@ -7060,15 +7284,15 @@ TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) { // Mark any declarations we need as referenced. // FIXME: instantiation-specific. if (OperatorDelete) - SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorDelete); + SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorDelete); if (!E->getArgument()->isTypeDependent()) { QualType Destroyed = SemaRef.Context.getBaseElementType( E->getDestroyedType()); if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) { CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl()); - SemaRef.MarkDeclarationReferenced(E->getLocStart(), - SemaRef.LookupDestructor(Record)); + SemaRef.MarkFunctionReferenced(E->getLocStart(), + SemaRef.LookupDestructor(Record)); } } @@ -7118,7 +7342,7 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr( if (!DestroyedTypeInfo) return ExprError(); Destroyed = DestroyedTypeInfo; - } else if (ObjectType->isDependentType()) { + } else if (!ObjectType.isNull() && ObjectType->isDependentType()) { // We aren't likely to be able to resolve the identifier down to a type // now anyway, so just retain the identifier. Destroyed = PseudoDestructorTypeStorage(E->getDestroyedTypeIdentifier(), @@ -7216,8 +7440,11 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr( R.setNamingClass(NamingClass); } - // If we have no template arguments, it's a normal declaration name. - if (!Old->hasExplicitTemplateArgs()) + SourceLocation TemplateKWLoc = Old->getTemplateKeywordLoc(); + + // If we have neither explicit template arguments, nor the template keyword, + // it's a normal declaration name. + if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL()); // If we have template arguments, rebuild them, then rebuild the @@ -7228,8 +7455,8 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr( TransArgs)) return ExprError(); - return getDerived().RebuildTemplateIdExpr(SS, R, Old->requiresADL(), - TransArgs); + return getDerived().RebuildTemplateIdExpr(SS, TemplateKWLoc, R, + Old->requiresADL(), &TransArgs); } template<typename Derived> @@ -7272,6 +7499,128 @@ TreeTransform<Derived>::TransformBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { template<typename Derived> ExprResult +TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) { + bool ArgChanged = false; + llvm::SmallVector<TypeSourceInfo *, 4> Args; + for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) { + TypeSourceInfo *From = E->getArg(I); + TypeLoc FromTL = From->getTypeLoc(); + if (!isa<PackExpansionTypeLoc>(FromTL)) { + TypeLocBuilder TLB; + TLB.reserve(FromTL.getFullDataSize()); + QualType To = getDerived().TransformType(TLB, FromTL); + if (To.isNull()) + return ExprError(); + + if (To == From->getType()) + Args.push_back(From); + else { + Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To)); + ArgChanged = true; + } + continue; + } + + ArgChanged = true; + + // We have a pack expansion. Instantiate it. + PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(FromTL); + TypeLoc PatternTL = ExpansionTL.getPatternLoc(); + SmallVector<UnexpandedParameterPack, 2> Unexpanded; + SemaRef.collectUnexpandedParameterPacks(PatternTL, Unexpanded); + + // Determine whether the set of unexpanded parameter packs can and should + // be expanded. + bool Expand = true; + bool RetainExpansion = false; + llvm::Optional<unsigned> OrigNumExpansions + = ExpansionTL.getTypePtr()->getNumExpansions(); + llvm::Optional<unsigned> NumExpansions = OrigNumExpansions; + if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(), + PatternTL.getSourceRange(), + Unexpanded, + Expand, RetainExpansion, + NumExpansions)) + return ExprError(); + + if (!Expand) { + // The transform has determined that we should perform a simple + // transformation on the pack expansion, producing another pack + // expansion. + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); + + TypeLocBuilder TLB; + TLB.reserve(From->getTypeLoc().getFullDataSize()); + + QualType To = getDerived().TransformType(TLB, PatternTL); + if (To.isNull()) + return ExprError(); + + To = getDerived().RebuildPackExpansionType(To, + PatternTL.getSourceRange(), + ExpansionTL.getEllipsisLoc(), + NumExpansions); + if (To.isNull()) + return ExprError(); + + PackExpansionTypeLoc ToExpansionTL + = TLB.push<PackExpansionTypeLoc>(To); + ToExpansionTL.setEllipsisLoc(ExpansionTL.getEllipsisLoc()); + Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To)); + continue; + } + + // Expand the pack expansion by substituting for each argument in the + // pack(s). + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I); + TypeLocBuilder TLB; + TLB.reserve(PatternTL.getFullDataSize()); + QualType To = getDerived().TransformType(TLB, PatternTL); + if (To.isNull()) + return ExprError(); + + Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To)); + } + + if (!RetainExpansion) + continue; + + // If we're supposed to retain a pack expansion, do so by temporarily + // forgetting the partially-substituted parameter pack. + ForgetPartiallySubstitutedPackRAII Forget(getDerived()); + + TypeLocBuilder TLB; + TLB.reserve(From->getTypeLoc().getFullDataSize()); + + QualType To = getDerived().TransformType(TLB, PatternTL); + if (To.isNull()) + return ExprError(); + + To = getDerived().RebuildPackExpansionType(To, + PatternTL.getSourceRange(), + ExpansionTL.getEllipsisLoc(), + NumExpansions); + if (To.isNull()) + return ExprError(); + + PackExpansionTypeLoc ToExpansionTL + = TLB.push<PackExpansionTypeLoc>(To); + ToExpansionTL.setEllipsisLoc(ExpansionTL.getEllipsisLoc()); + Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To)); + } + + if (!getDerived().AlwaysRebuild() && !ArgChanged) + return SemaRef.Owned(E); + + return getDerived().RebuildTypeTrait(E->getTrait(), + E->getLocStart(), + Args, + E->getLocEnd()); +} + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo()); if (!T) @@ -7325,6 +7674,7 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr( = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc()); if (!QualifierLoc) return ExprError(); + SourceLocation TemplateKWLoc = E->getTemplateKeywordLoc(); // TODO: If this is a conversion-function-id, verify that the // destination type name (if present) resolves the same way after @@ -7344,6 +7694,7 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr( return SemaRef.Owned(E); return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc, + TemplateKWLoc, NameInfo, /*TemplateArgs*/ 0); } @@ -7355,6 +7706,7 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr( return ExprError(); return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc, + TemplateKWLoc, NameInfo, &TransArgs); } @@ -7393,7 +7745,7 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) { !ArgumentChanged) { // Mark the constructor as referenced. // FIXME: Instantiation-specific - SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor); + SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor); return SemaRef.Owned(E); } @@ -7454,7 +7806,7 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr( Constructor == E->getConstructor() && !ArgumentChanged) { // FIXME: Instantiation-specific - SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor); + SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor); return SemaRef.MaybeBindToTemporary(E); } @@ -7466,6 +7818,158 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr( template<typename Derived> ExprResult +TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { + // Create the local class that will describe the lambda. + CXXRecordDecl *Class + = getSema().createLambdaClosureType(E->getIntroducerRange(), + /*KnownDependent=*/false); + getDerived().transformedLocalDecl(E->getLambdaClass(), Class); + + // Transform the type of the lambda parameters and start the definition of + // the lambda itself. + TypeSourceInfo *MethodTy + = TransformType(E->getCallOperator()->getTypeSourceInfo()); + if (!MethodTy) + return ExprError(); + + // Transform lambda parameters. + bool Invalid = false; + llvm::SmallVector<QualType, 4> ParamTypes; + llvm::SmallVector<ParmVarDecl *, 4> Params; + if (getDerived().TransformFunctionTypeParams(E->getLocStart(), + E->getCallOperator()->param_begin(), + E->getCallOperator()->param_size(), + 0, ParamTypes, &Params)) + Invalid = true; + + // Build the call operator. + // Note: Once a lambda mangling number and context declaration have been + // assigned, they never change. + unsigned ManglingNumber = E->getLambdaClass()->getLambdaManglingNumber(); + Decl *ContextDecl = E->getLambdaClass()->getLambdaContextDecl(); + CXXMethodDecl *CallOperator + = getSema().startLambdaDefinition(Class, E->getIntroducerRange(), + MethodTy, + E->getCallOperator()->getLocEnd(), + Params, ManglingNumber, ContextDecl); + getDerived().transformAttrs(E->getCallOperator(), CallOperator); + + // FIXME: Instantiation-specific. + CallOperator->setInstantiationOfMemberFunction(E->getCallOperator(), + TSK_ImplicitInstantiation); + + // Introduce the context of the call operator. + Sema::ContextRAII SavedContext(getSema(), CallOperator); + + // Enter the scope of the lambda. + sema::LambdaScopeInfo *LSI + = getSema().enterLambdaScope(CallOperator, E->getIntroducerRange(), + E->getCaptureDefault(), + E->hasExplicitParameters(), + E->hasExplicitResultType(), + E->isMutable()); + + // Transform captures. + bool FinishedExplicitCaptures = false; + for (LambdaExpr::capture_iterator C = E->capture_begin(), + CEnd = E->capture_end(); + C != CEnd; ++C) { + // When we hit the first implicit capture, tell Sema that we've finished + // the list of explicit captures. + if (!FinishedExplicitCaptures && C->isImplicit()) { + getSema().finishLambdaExplicitCaptures(LSI); + FinishedExplicitCaptures = true; + } + + // Capturing 'this' is trivial. + if (C->capturesThis()) { + getSema().CheckCXXThisCapture(C->getLocation(), C->isExplicit()); + continue; + } + + // Determine the capture kind for Sema. + Sema::TryCaptureKind Kind + = C->isImplicit()? Sema::TryCapture_Implicit + : C->getCaptureKind() == LCK_ByCopy + ? Sema::TryCapture_ExplicitByVal + : Sema::TryCapture_ExplicitByRef; + SourceLocation EllipsisLoc; + if (C->isPackExpansion()) { + UnexpandedParameterPack Unexpanded(C->getCapturedVar(), C->getLocation()); + bool ShouldExpand = false; + bool RetainExpansion = false; + llvm::Optional<unsigned> NumExpansions; + if (getDerived().TryExpandParameterPacks(C->getEllipsisLoc(), + C->getLocation(), + Unexpanded, + ShouldExpand, RetainExpansion, + NumExpansions)) + return ExprError(); + + if (ShouldExpand) { + // The transform has determined that we should perform an expansion; + // transform and capture each of the arguments. + // expansion of the pattern. Do so. + VarDecl *Pack = C->getCapturedVar(); + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I); + VarDecl *CapturedVar + = cast_or_null<VarDecl>(getDerived().TransformDecl(C->getLocation(), + Pack)); + if (!CapturedVar) { + Invalid = true; + continue; + } + + // Capture the transformed variable. + getSema().tryCaptureVariable(CapturedVar, C->getLocation(), Kind); + } + continue; + } + + EllipsisLoc = C->getEllipsisLoc(); + } + + // Transform the captured variable. + VarDecl *CapturedVar + = cast_or_null<VarDecl>(getDerived().TransformDecl(C->getLocation(), + C->getCapturedVar())); + if (!CapturedVar) { + Invalid = true; + continue; + } + + // Capture the transformed variable. + getSema().tryCaptureVariable(CapturedVar, C->getLocation(), Kind); + } + if (!FinishedExplicitCaptures) + getSema().finishLambdaExplicitCaptures(LSI); + + + // Enter a new evaluation context to insulate the lambda from any + // cleanups from the enclosing full-expression. + getSema().PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); + + if (Invalid) { + getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/0, + /*IsInstantiation=*/true); + return ExprError(); + } + + // Instantiate the body of the lambda expression. + StmtResult Body = getDerived().TransformStmt(E->getBody()); + if (Body.isInvalid()) { + getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/0, + /*IsInstantiation=*/true); + return ExprError(); + } + + return getSema().ActOnLambdaExpr(E->getLocStart(), Body.take(), + /*CurScope=*/0, /*IsInstantiation=*/true); +} + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr( CXXUnresolvedConstructExpr *E) { TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo()); @@ -7542,6 +8046,8 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr( return ExprError(); } + SourceLocation TemplateKWLoc = E->getTemplateKeywordLoc(); + // TODO: If this is a conversion-function-id, verify that the // destination type name (if present) resolves the same way after // instantiation as it did in the local scope. @@ -7567,6 +8073,7 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr( E->isArrow(), E->getOperatorLoc(), QualifierLoc, + TemplateKWLoc, FirstQualifierInScope, NameInfo, /*TemplateArgs*/ 0); @@ -7583,6 +8090,7 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr( E->isArrow(), E->getOperatorLoc(), QualifierLoc, + TemplateKWLoc, FirstQualifierInScope, NameInfo, &TransArgs); @@ -7598,7 +8106,11 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) Base = getDerived().TransformExpr(Old->getBase()); if (Base.isInvalid()) return ExprError(); - BaseType = ((Expr*) Base.get())->getType(); + Base = getSema().PerformMemberExprBaseConversion(Base.take(), + Old->isArrow()); + if (Base.isInvalid()) + return ExprError(); + BaseType = Base.get()->getType(); } else { BaseType = getDerived().TransformType(Old->getBaseType()); } @@ -7611,6 +8123,8 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) return ExprError(); } + SourceLocation TemplateKWLoc = Old->getTemplateKeywordLoc(); + LookupResult R(SemaRef, Old->getMemberNameInfo(), Sema::LookupOrdinaryName); @@ -7678,6 +8192,7 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) Old->getOperatorLoc(), Old->isArrow(), QualifierLoc, + TemplateKWLoc, FirstQualifierInScope, R, (Old->hasExplicitTemplateArgs() @@ -7778,11 +8293,163 @@ TreeTransform<Derived>::TransformMaterializeTemporaryExpr( template<typename Derived> ExprResult TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) { + return SemaRef.MaybeBindToTemporary(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformObjCBoolLiteralExpr(ObjCBoolLiteralExpr *E) { return SemaRef.Owned(E); } template<typename Derived> ExprResult +TreeTransform<Derived>::TransformObjCNumericLiteral(ObjCNumericLiteral *E) { + return SemaRef.MaybeBindToTemporary(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformObjCArrayLiteral(ObjCArrayLiteral *E) { + // Transform each of the elements. + llvm::SmallVector<Expr *, 8> Elements; + bool ArgChanged = false; + if (getDerived().TransformExprs(E->getElements(), E->getNumElements(), + /*IsCall=*/false, Elements, &ArgChanged)) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && !ArgChanged) + return SemaRef.MaybeBindToTemporary(E); + + return getDerived().RebuildObjCArrayLiteral(E->getSourceRange(), + Elements.data(), + Elements.size()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformObjCDictionaryLiteral( + ObjCDictionaryLiteral *E) { + // Transform each of the elements. + llvm::SmallVector<ObjCDictionaryElement, 8> Elements; + bool ArgChanged = false; + for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) { + ObjCDictionaryElement OrigElement = E->getKeyValueElement(I); + + if (OrigElement.isPackExpansion()) { + // This key/value element is a pack expansion. + SmallVector<UnexpandedParameterPack, 2> Unexpanded; + getSema().collectUnexpandedParameterPacks(OrigElement.Key, Unexpanded); + getSema().collectUnexpandedParameterPacks(OrigElement.Value, Unexpanded); + assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); + + // Determine whether the set of unexpanded parameter packs can + // and should be expanded. + bool Expand = true; + bool RetainExpansion = false; + llvm::Optional<unsigned> OrigNumExpansions = OrigElement.NumExpansions; + llvm::Optional<unsigned> NumExpansions = OrigNumExpansions; + SourceRange PatternRange(OrigElement.Key->getLocStart(), + OrigElement.Value->getLocEnd()); + if (getDerived().TryExpandParameterPacks(OrigElement.EllipsisLoc, + PatternRange, + Unexpanded, + Expand, RetainExpansion, + NumExpansions)) + return ExprError(); + + if (!Expand) { + // The transform has determined that we should perform a simple + // transformation on the pack expansion, producing another pack + // expansion. + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); + ExprResult Key = getDerived().TransformExpr(OrigElement.Key); + if (Key.isInvalid()) + return ExprError(); + + if (Key.get() != OrigElement.Key) + ArgChanged = true; + + ExprResult Value = getDerived().TransformExpr(OrigElement.Value); + if (Value.isInvalid()) + return ExprError(); + + if (Value.get() != OrigElement.Value) + ArgChanged = true; + + ObjCDictionaryElement Expansion = { + Key.get(), Value.get(), OrigElement.EllipsisLoc, NumExpansions + }; + Elements.push_back(Expansion); + continue; + } + + // Record right away that the argument was changed. This needs + // to happen even if the array expands to nothing. + ArgChanged = true; + + // The transform has determined that we should perform an elementwise + // expansion of the pattern. Do so. + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I); + ExprResult Key = getDerived().TransformExpr(OrigElement.Key); + if (Key.isInvalid()) + return ExprError(); + + ExprResult Value = getDerived().TransformExpr(OrigElement.Value); + if (Value.isInvalid()) + return ExprError(); + + ObjCDictionaryElement Element = { + Key.get(), Value.get(), SourceLocation(), NumExpansions + }; + + // If any unexpanded parameter packs remain, we still have a + // pack expansion. + if (Key.get()->containsUnexpandedParameterPack() || + Value.get()->containsUnexpandedParameterPack()) + Element.EllipsisLoc = OrigElement.EllipsisLoc; + + Elements.push_back(Element); + } + + // We've finished with this pack expansion. + continue; + } + + // Transform and check key. + ExprResult Key = getDerived().TransformExpr(OrigElement.Key); + if (Key.isInvalid()) + return ExprError(); + + if (Key.get() != OrigElement.Key) + ArgChanged = true; + + // Transform and check value. + ExprResult Value + = getDerived().TransformExpr(OrigElement.Value); + if (Value.isInvalid()) + return ExprError(); + + if (Value.get() != OrigElement.Value) + ArgChanged = true; + + ObjCDictionaryElement Element = { + Key.get(), Value.get(), SourceLocation(), llvm::Optional<unsigned>() + }; + Elements.push_back(Element); + } + + if (!getDerived().AlwaysRebuild() && !ArgChanged) + return SemaRef.MaybeBindToTemporary(E); + + return getDerived().RebuildObjCDictionaryLiteral(E->getSourceRange(), + Elements.data(), + Elements.size()); +} + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformObjCEncodeExpr(ObjCEncodeExpr *E) { TypeSourceInfo *EncodedTypeInfo = getDerived().TransformType(E->getEncodedTypeSourceInfo()); @@ -7856,7 +8523,7 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) { // If nothing changed, just retain the existing message send. if (!getDerived().AlwaysRebuild() && ReceiverTypeInfo == E->getClassReceiverTypeInfo() && !ArgChanged) - return SemaRef.Owned(E); + return SemaRef.MaybeBindToTemporary(E); // Build a new class message send. SmallVector<SourceLocation, 16> SelLocs; @@ -7881,7 +8548,7 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) { // If nothing changed, just retain the existing message send. if (!getDerived().AlwaysRebuild() && Receiver.get() == E->getInstanceReceiver() && !ArgChanged) - return SemaRef.Owned(E); + return SemaRef.MaybeBindToTemporary(E); // Build a new instance message send. SmallVector<SourceLocation, 16> SelLocs; @@ -7953,7 +8620,7 @@ TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { E->getLocation()); return getDerived().RebuildObjCPropertyRefExpr(Base.get(), - E->getType(), + SemaRef.Context.PseudoObjectTy, E->getImplicitPropertyGetter(), E->getImplicitPropertySetter(), E->getLocation()); @@ -7961,6 +8628,30 @@ TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { template<typename Derived> ExprResult +TreeTransform<Derived>::TransformObjCSubscriptRefExpr(ObjCSubscriptRefExpr *E) { + // Transform the base expression. + ExprResult Base = getDerived().TransformExpr(E->getBaseExpr()); + if (Base.isInvalid()) + return ExprError(); + + // Transform the key expression. + ExprResult Key = getDerived().TransformExpr(E->getKeyExpr()); + if (Key.isInvalid()) + return ExprError(); + + // If nothing changed, just retain the existing expression. + if (!getDerived().AlwaysRebuild() && + Key.get() == E->getKeyExpr() && Base.get() == E->getBaseExpr()) + return SemaRef.Owned(E); + + return getDerived().RebuildObjCSubscriptRefExpr(E->getRBracket(), + Base.get(), Key.get(), + E->getAtIndexMethodDecl(), + E->setAtIndexMethodDecl()); +} + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E) { // Transform the base expression. ExprResult Base = getDerived().TransformExpr(E->getBase()); @@ -8004,10 +8695,8 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { BlockScopeInfo *blockScope = SemaRef.getCurBlock(); blockScope->TheDecl->setIsVariadic(oldBlock->isVariadic()); - // We built a new blockScopeInfo in call to ActOnBlockStart - // in above, CapturesCXXThis need be set here from the block - // expression. - blockScope->CapturesCXXThis = oldBlock->capturesCXXThis(); + blockScope->TheDecl->setBlockMissingReturnType( + oldBlock->blockMissingReturnType()); SmallVector<ParmVarDecl*, 4> params; SmallVector<QualType, 4> paramTypes; @@ -8016,54 +8705,48 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { if (getDerived().TransformFunctionTypeParams(E->getCaretLocation(), oldBlock->param_begin(), oldBlock->param_size(), - 0, paramTypes, ¶ms)) - return true; + 0, paramTypes, ¶ms)) { + getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/0); + return ExprError(); + } const FunctionType *exprFunctionType = E->getFunctionType(); - QualType exprResultType = exprFunctionType->getResultType(); - if (!exprResultType.isNull()) { - if (!exprResultType->isDependentType()) - blockScope->ReturnType = exprResultType; - else if (exprResultType != getSema().Context.DependentTy) - blockScope->ReturnType = getDerived().TransformType(exprResultType); - } - - // If the return type has not been determined yet, leave it as a dependent - // type; it'll get set when we process the body. - if (blockScope->ReturnType.isNull()) - blockScope->ReturnType = getSema().Context.DependentTy; + QualType exprResultType = + getDerived().TransformType(exprFunctionType->getResultType()); // Don't allow returning a objc interface by value. - if (blockScope->ReturnType->isObjCObjectType()) { + if (exprResultType->isObjCObjectType()) { getSema().Diag(E->getCaretLocation(), diag::err_object_cannot_be_passed_returned_by_value) - << 0 << blockScope->ReturnType; + << 0 << exprResultType; + getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/0); return ExprError(); } QualType functionType = getDerived().RebuildFunctionProtoType( - blockScope->ReturnType, + exprResultType, paramTypes.data(), paramTypes.size(), oldBlock->isVariadic(), - 0, RQ_None, + false, 0, RQ_None, exprFunctionType->getExtInfo()); blockScope->FunctionType = functionType; // Set the parameters on the block decl. if (!params.empty()) blockScope->TheDecl->setParams(params); - - // If the return type wasn't explicitly set, it will have been marked as a - // dependent type (DependentTy); clear out the return type setting so - // we will deduce the return type when type-checking the block's body. - if (blockScope->ReturnType == getSema().Context.DependentTy) - blockScope->ReturnType = QualType(); + + if (!oldBlock->blockMissingReturnType()) { + blockScope->HasImplicitReturnType = false; + blockScope->ReturnType = exprResultType; + } // Transform the body StmtResult body = getDerived().TransformStmt(E->getBody()); - if (body.isInvalid()) + if (body.isInvalid()) { + getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/0); return ExprError(); + } #ifndef NDEBUG // In builds with assertions, make sure that we captured everything we @@ -8083,6 +8766,7 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { oldCapture)); assert(blockScope->CaptureMap.count(newCapture)); } + assert(oldBlock->capturesCXXThis() == blockScope->isCXXThisCaptured()); } #endif @@ -8092,29 +8776,6 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { template<typename Derived> ExprResult -TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { - ValueDecl *ND - = cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getLocation(), - E->getDecl())); - if (!ND) - return ExprError(); - - if (!getDerived().AlwaysRebuild() && - ND == E->getDecl()) { - // Mark it referenced in the new context regardless. - // FIXME: this is a bit instantiation-specific. - SemaRef.MarkDeclarationReferenced(E->getLocation(), ND); - - return SemaRef.Owned(E); - } - - DeclarationNameInfo NameInfo(E->getDecl()->getDeclName(), E->getLocation()); - return getDerived().RebuildDeclRefExpr(NestedNameSpecifierLoc(), - ND, NameInfo, 0); -} - -template<typename Derived> -ExprResult TreeTransform<Derived>::TransformAsTypeExpr(AsTypeExpr *E) { llvm_unreachable("Cannot transform asType expressions yet"); } @@ -8200,9 +8861,12 @@ TreeTransform<Derived>::RebuildArrayType(QualType ElementType, break; } - IntegerLiteral ArraySize(SemaRef.Context, *Size, SizeType, - /*FIXME*/BracketsRange.getBegin()); - return SemaRef.BuildArrayType(ElementType, SizeMod, &ArraySize, + // Note that we can return a VariableArrayType here in the case where + // the element type was a dependent VariableArrayType. + IntegerLiteral *ArraySize + = IntegerLiteral::Create(SemaRef.Context, *Size, SizeType, + /*FIXME*/BracketsRange.getBegin()); + return SemaRef.BuildArrayType(ElementType, SizeMod, ArraySize, IndexTypeQuals, BracketsRange, getDerived().getBaseEntity()); } @@ -8285,11 +8949,12 @@ QualType TreeTransform<Derived>::RebuildFunctionProtoType(QualType T, QualType *ParamTypes, unsigned NumParamTypes, bool Variadic, + bool HasTrailingReturn, unsigned Quals, RefQualifierKind RefQualifier, const FunctionType::ExtInfo &Info) { return SemaRef.BuildFunctionType(T, ParamTypes, NumParamTypes, Variadic, - Quals, RefQualifier, + HasTrailingReturn, Quals, RefQualifier, getDerived().getBaseLocation(), getDerived().getBaseEntity(), Info); @@ -8382,10 +9047,9 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS, UnqualifiedId TemplateName; TemplateName.setIdentifier(&Name, NameLoc); Sema::TemplateTy Template; + SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller. getSema().ActOnDependentTemplateName(/*Scope=*/0, - /*FIXME:*/SourceLocation(), - SS, - TemplateName, + SS, TemplateKWLoc, TemplateName, ParsedType::make(ObjectType), /*EnteringContext=*/false, Template); @@ -8400,13 +9064,12 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS, QualType ObjectType) { UnqualifiedId Name; // FIXME: Bogus location information. - SourceLocation SymbolLocations[3] = { NameLoc, NameLoc, NameLoc }; + SourceLocation SymbolLocations[3] = { NameLoc, NameLoc, NameLoc }; Name.setOperatorFunctionId(NameLoc, Operator, SymbolLocations); + SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller. Sema::TemplateTy Template; getSema().ActOnDependentTemplateName(/*Scope=*/0, - /*FIXME:*/SourceLocation(), - SS, - Name, + SS, TemplateKWLoc, Name, ParsedType::make(ObjectType), /*EnteringContext=*/false, Template); @@ -8543,9 +9206,11 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base, // FIXME: the ScopeType should be tacked onto SS. + SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller. return getSema().BuildMemberReferenceExpr(Base, BaseType, OperatorLoc, isArrow, - SS, /*FIXME: FirstQualifier*/ 0, + SS, TemplateKWLoc, + /*FIXME: FirstQualifier*/ 0, NameInfo, /*TemplateArgs*/ 0); } |