diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema')
43 files changed, 17597 insertions, 7967 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp index 1295339aa332..93e3ecfb2947 100644 --- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -25,6 +25,7 @@ #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtVisitor.h" #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" +#include "clang/Analysis/Analyses/Consumed.h" #include "clang/Analysis/Analyses/ReachableCode.h" #include "clang/Analysis/Analyses/ThreadSafety.h" #include "clang/Analysis/Analyses/UninitializedValues.h" @@ -438,22 +439,22 @@ static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) { << 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). - std::string Init = S.getFixItZeroInitializerForType(VariableTy); - if (Init.empty()) - return false; // Don't suggest a fixit inside macros. if (VD->getLocEnd().isMacroID()) return false; SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); - + + // Suggest possible initialization (if any). + std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc); + if (Init.empty()) + return false; + S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName() << FixItHint::CreateInsertion(Loc, Init); return true; @@ -492,6 +493,31 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, bool IsCapturedByBlock) { bool Diagnosed = false; + switch (Use.getKind()) { + case UninitUse::Always: + S.Diag(Use.getUser()->getLocStart(), diag::warn_uninit_var) + << VD->getDeclName() << IsCapturedByBlock + << Use.getUser()->getSourceRange(); + return; + + case UninitUse::AfterDecl: + case UninitUse::AfterCall: + S.Diag(VD->getLocation(), diag::warn_sometimes_uninit_var) + << VD->getDeclName() << IsCapturedByBlock + << (Use.getKind() == UninitUse::AfterDecl ? 4 : 5) + << const_cast<DeclContext*>(VD->getLexicalDeclContext()) + << VD->getSourceRange(); + S.Diag(Use.getUser()->getLocStart(), diag::note_uninit_var_use) + << IsCapturedByBlock << Use.getUser()->getSourceRange(); + return; + + case UninitUse::Maybe: + case UninitUse::Sometimes: + // Carry on to report sometimes-uninitialized branches, if possible, + // or a 'may be used uninitialized' diagnostic otherwise. + break; + } + // Diagnose each branch which leads to a sometimes-uninitialized use. for (UninitUse::branch_iterator I = Use.branch_begin(), E = Use.branch_end(); I != E; ++I) { @@ -514,14 +540,10 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, : (I->Output ? "1" : "0"); FixItHint Fixit1, Fixit2; - switch (Term->getStmtClass()) { + switch (Term ? Term->getStmtClass() : Stmt::DeclStmtClass) { default: // Don't know how to report this. Just fall back to 'may be used - // uninitialized'. This happens for range-based for, which the user - // can't explicitly fix. - // FIXME: This also happens if the first use of a variable is always - // uninitialized, eg "for (int n; n < 10; ++n)". We should report that - // with the 'is uninitialized' diagnostic. + // uninitialized'. FIXME: Can this happen? continue; // "condition is true / condition is false". @@ -582,6 +604,17 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, else Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); break; + case Stmt::CXXForRangeStmtClass: + if (I->Output == 1) { + // The use occurs if a range-based for loop's body never executes. + // That may be impossible, and there's no syntactic fix for this, + // so treat it as a 'may be uninitialized' case. + continue; + } + DiagKind = 1; + Str = "for"; + Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange(); + break; // "condition is true / loop is exited". case Stmt::DoStmtClass: @@ -618,9 +651,7 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, } if (!Diagnosed) - S.Diag(Use.getUser()->getLocStart(), - Use.getKind() == UninitUse::Always ? diag::warn_uninit_var - : diag::warn_maybe_uninit_var) + S.Diag(Use.getUser()->getLocStart(), diag::warn_maybe_uninit_var) << VD->getDeclName() << IsCapturedByBlock << Use.getUser()->getSourceRange(); } @@ -1123,7 +1154,7 @@ static void diagnoseRepeatedUseOfWeak(Sema &S, // Show the first time the object was read. S.Diag(FirstRead->getLocStart(), DiagKind) - << ObjectKind << D << FunctionKind + << int(ObjectKind) << D << int(FunctionKind) << FirstRead->getSourceRange(); // Print all the other accesses as notes. @@ -1154,7 +1185,7 @@ struct SLocSort { class UninitValsDiagReporter : public UninitVariablesHandler { Sema &S; typedef SmallVector<UninitUse, 2> UsesVec; - typedef std::pair<UsesVec*, bool> MappedType; + typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType; // Prefer using MapVector to DenseMap, so that iteration order will be // the same as insertion order. This is needed to obtain a deterministic // order of diagnostics when calling flushDiagnostics(). @@ -1172,19 +1203,18 @@ public: uses = new UsesMap(); MappedType &V = (*uses)[vd]; - UsesVec *&vec = V.first; - if (!vec) - vec = new UsesVec(); + if (!V.getPointer()) + V.setPointer(new UsesVec()); return V; } void handleUseOfUninitVariable(const VarDecl *vd, const UninitUse &use) { - getUses(vd).first->push_back(use); + getUses(vd).getPointer()->push_back(use); } void handleSelfInit(const VarDecl *vd) { - getUses(vd).second = true; + getUses(vd).setInt(true); } void flushDiagnostics() { @@ -1195,8 +1225,8 @@ public: const VarDecl *vd = i->first; const MappedType &V = i->second; - UsesVec *vec = V.first; - bool hasSelfInit = V.second; + UsesVec *vec = V.getPointer(); + bool hasSelfInit = V.getInt(); // Specially handle the case where we have uses of an uninitialized // variable, but the root cause is an idiomatic self-init. We want @@ -1233,7 +1263,9 @@ public: private: static bool hasAlwaysUninitializedUse(const UsesVec* vec) { for (UsesVec::const_iterator i = vec->begin(), e = vec->end(); i != e; ++i) { - if (i->getKind() == UninitUse::Always) { + if (i->getKind() == UninitUse::Always || + i->getKind() == UninitUse::AfterCall || + i->getKind() == UninitUse::AfterDecl) { return true; } } @@ -1242,12 +1274,8 @@ private: }; } - -//===----------------------------------------------------------------------===// -// -Wthread-safety -//===----------------------------------------------------------------------===// namespace clang { -namespace thread_safety { +namespace { typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes; typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag; typedef std::list<DelayedDiag> DiagList; @@ -1262,7 +1290,13 @@ struct SortDiagBySourceLocation { return SM.isBeforeInTranslationUnit(left.first.first, right.first.first); } }; +}} +//===----------------------------------------------------------------------===// +// -Wthread-safety +//===----------------------------------------------------------------------===// +namespace clang { +namespace thread_safety { namespace { class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler { Sema &S; @@ -1413,6 +1447,102 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler { } //===----------------------------------------------------------------------===// +// -Wconsumed +//===----------------------------------------------------------------------===// + +namespace clang { +namespace consumed { +namespace { +class ConsumedWarningsHandler : public ConsumedWarningsHandlerBase { + + Sema &S; + DiagList Warnings; + +public: + + ConsumedWarningsHandler(Sema &S) : S(S) {} + + void emitDiagnostics() { + Warnings.sort(SortDiagBySourceLocation(S.getSourceManager())); + + for (DiagList::iterator I = Warnings.begin(), E = Warnings.end(); + I != E; ++I) { + + const OptionalNotes &Notes = I->second; + S.Diag(I->first.first, I->first.second); + + for (unsigned NoteI = 0, NoteN = Notes.size(); NoteI != NoteN; ++NoteI) { + S.Diag(Notes[NoteI].first, Notes[NoteI].second); + } + } + } + + void warnLoopStateMismatch(SourceLocation Loc, StringRef VariableName) { + PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_loop_state_mismatch) << + VariableName); + + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); + } + + void warnParamReturnTypestateMismatch(SourceLocation Loc, + StringRef VariableName, + StringRef ExpectedState, + StringRef ObservedState) { + + PartialDiagnosticAt Warning(Loc, S.PDiag( + diag::warn_param_return_typestate_mismatch) << VariableName << + ExpectedState << ObservedState); + + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); + } + + void warnParamTypestateMismatch(SourceLocation Loc, StringRef ExpectedState, + StringRef ObservedState) { + + PartialDiagnosticAt Warning(Loc, S.PDiag( + diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState); + + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); + } + + void warnReturnTypestateForUnconsumableType(SourceLocation Loc, + StringRef TypeName) { + PartialDiagnosticAt Warning(Loc, S.PDiag( + diag::warn_return_typestate_for_unconsumable_type) << TypeName); + + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); + } + + void warnReturnTypestateMismatch(SourceLocation Loc, StringRef ExpectedState, + StringRef ObservedState) { + + PartialDiagnosticAt Warning(Loc, S.PDiag( + diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState); + + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); + } + + void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State, + SourceLocation Loc) { + + PartialDiagnosticAt Warning(Loc, S.PDiag( + diag::warn_use_of_temp_in_invalid_state) << MethodName << State); + + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); + } + + void warnUseInInvalidState(StringRef MethodName, StringRef VariableName, + StringRef State, SourceLocation Loc) { + + PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_use_in_invalid_state) << + MethodName << VariableName << State); + + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); + } +}; +}}} + +//===----------------------------------------------------------------------===// // AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based // warnings on a function, method, or block. //===----------------------------------------------------------------------===// @@ -1421,6 +1551,7 @@ clang::sema::AnalysisBasedWarnings::Policy::Policy() { enableCheckFallThrough = 1; enableCheckUnreachable = 0; enableThreadSafetyAnalysis = 0; + enableConsumedAnalysis = 0; } clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) @@ -1441,7 +1572,9 @@ clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) DefaultPolicy.enableThreadSafetyAnalysis = (unsigned) (D.getDiagnosticLevel(diag::warn_double_lock, SourceLocation()) != DiagnosticsEngine::Ignored); - + DefaultPolicy.enableConsumedAnalysis = (unsigned) + (D.getDiagnosticLevel(diag::warn_use_in_invalid_state, SourceLocation()) != + DiagnosticsEngine::Ignored); } static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) { @@ -1486,10 +1619,11 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, const Stmt *Body = D->getBody(); assert(Body); + // Construct the analysis context with the specified CFG build options. AnalysisDeclContext AC(/* AnalysisDeclContextManager */ 0, D); // 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. + // explosion for destructors that can result and the compile time hit. AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true; AC.getCFGBuildOptions().AddEHEdges = false; AC.getCFGBuildOptions().AddInitializers = true; @@ -1502,7 +1636,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 || P.enableThreadSafetyAnalysis) { + if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis || + P.enableConsumedAnalysis) { // Unreachable code analysis and thread safety require a linearized CFG. AC.getCFGBuildOptions().setAllAlwaysAdd(); } @@ -1518,8 +1653,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, .setAlwaysAdd(Stmt::AttributedStmtClass); } - // Construct the analysis context with the specified CFG build options. - + // Emit delayed diagnostics. if (!fscope->PossiblyUnreachableDiags.empty()) { bool analyzed = false; @@ -1606,6 +1740,13 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, Reporter.emitDiagnostics(); } + // Check for violations of consumed properties. + if (P.enableConsumedAnalysis) { + consumed::ConsumedWarningsHandler WarningHandler(S); + consumed::ConsumedAnalyzer Analyzer(WarningHandler); + Analyzer.run(AC); + } + if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart()) != DiagnosticsEngine::Ignored || Diags.getDiagnosticLevel(diag::warn_sometimes_uninit_var,D->getLocStart()) diff --git a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp index 9ac4c63e191e..c9807723f064 100644 --- a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp @@ -19,13 +19,21 @@ #include "llvm/ADT/StringSwitch.h" using namespace clang; +IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc, + IdentifierInfo *Ident) { + IdentifierLoc *Result = new (Ctx) IdentifierLoc; + Result->Loc = Loc; + Result->Ident = Ident; + return Result; +} + size_t AttributeList::allocated_size() const { if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; else if (IsTypeTagForDatatype) return AttributeFactory::TypeTagForDatatypeAllocSize; else if (IsProperty) return AttributeFactory::PropertyAllocSize; - return (sizeof(AttributeList) + NumArgs * sizeof(Expr*)); + return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion)); } AttributeFactory::AttributeFactory() { @@ -98,10 +106,9 @@ void AttributePool::takePool(AttributeList *pool) { AttributeList * AttributePool::createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, SourceLocation TokLoc, int Arg) { - Expr *IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg), + ArgsUnion IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg), C.IntTy, TokLoc); - return create(Name, TokLoc, 0, TokLoc, 0, TokLoc, &IArg, 1, - AttributeList::AS_GNU); + return create(Name, TokLoc, 0, TokLoc, &IArg, 1, AttributeList::AS_GNU); } #include "clang/Sema/AttrParsedAttrKinds.inc" @@ -138,3 +145,28 @@ unsigned AttributeList::getAttributeSpellingListIndex() const { } +struct ParsedAttrInfo { + unsigned NumArgs : 4; + unsigned OptArgs : 4; + unsigned HasCustomParsing : 1; +}; + +namespace { + #include "clang/Sema/AttrParsedAttrImpl.inc" +} + +static const ParsedAttrInfo &getInfo(const AttributeList &A) { + return AttrInfoMap[A.getKind()]; +} + +unsigned AttributeList::getMinArgs() const { + return getInfo(*this).NumArgs; +} + +unsigned AttributeList::getMaxArgs() const { + return getMinArgs() + getInfo(*this).OptArgs; +} + +bool AttributeList::hasCustomParsing() const { + return getInfo(*this).HasCustomParsing; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp index 3b3ab2c27b4a..c2f16157b8eb 100644 --- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp @@ -13,6 +13,7 @@ #include "clang/Sema/DeclSpec.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TypeLoc.h" @@ -325,6 +326,19 @@ bool Declarator::isDeclarationOfFunction() const { llvm_unreachable("Invalid TypeSpecType!"); } +bool Declarator::isStaticMember() { + assert(getContext() == MemberContext); + return getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static || + CXXMethodDecl::isStaticOverloadedOperator( + getName().OperatorFunctionId.Operator); +} + +bool DeclSpec::hasTagDefinition() const { + if (!TypeSpecOwned) + return false; + return cast<TagDecl>(getRepAsDecl())->isCompleteDefinition(); +} + /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this /// declaration specifier includes. /// @@ -341,7 +355,7 @@ unsigned DeclSpec::getParsedSpecifiers() const { Res |= PQ_TypeSpecifier; if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified || - FS_noreturn_specified) + FS_noreturn_specified || FS_forceinline_specified) Res |= PQ_FunctionSpecifier; return Res; } @@ -651,7 +665,7 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc, DeclRep = Rep; TSTLoc = TagKwLoc; TSTNameLoc = TagNameLoc; - TypeSpecOwned = Owned; + TypeSpecOwned = Owned && Rep != 0; return false; } @@ -707,6 +721,20 @@ bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc, return false; } +bool DeclSpec::SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID) { + if (!TypeAltiVecVector || TypeAltiVecBool || + (TypeSpecType != TST_unspecified)) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_vector_bool_decl_spec; + return true; + } + TypeAltiVecBool = isAltiVecBool; + TSTLoc = Loc; + TSTNameLoc = Loc; + return false; +} + bool DeclSpec::SetTypeSpecError() { TypeSpecType = TST_error; TypeSpecOwned = false; @@ -717,9 +745,10 @@ bool DeclSpec::SetTypeSpecError() { bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const LangOptions &Lang) { - // Duplicates are permitted in C99, but are not permitted in C++. However, - // since this is likely not what the user intended, we will always warn. We - // do not need to set the qualifier's location since we already have it. + // Duplicates are permitted in C99 onwards, but are not permitted in C89 or + // C++. However, since this is likely not what the user intended, we will + // always warn. We do not need to set the qualifier's location since we + // already have it. if (TypeQualifiers & T) { bool IsExtension = true; if (Lang.C99) @@ -739,29 +768,72 @@ bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, llvm_unreachable("Unknown type qualifier!"); } -bool DeclSpec::setFunctionSpecInline(SourceLocation Loc) { - // 'inline inline' is ok. +bool DeclSpec::setFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + // 'inline inline' is ok. However, since this is likely not what the user + // intended, we will always warn, similar to duplicates of type qualifiers. + if (FS_inline_specified) { + DiagID = diag::warn_duplicate_declspec; + PrevSpec = "inline"; + return true; + } FS_inline_specified = true; FS_inlineLoc = Loc; return false; } -bool DeclSpec::setFunctionSpecVirtual(SourceLocation Loc) { - // 'virtual virtual' is ok. +bool DeclSpec::setFunctionSpecForceInline(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + if (FS_forceinline_specified) { + DiagID = diag::warn_duplicate_declspec; + PrevSpec = "__forceinline"; + return true; + } + FS_forceinline_specified = true; + FS_forceinlineLoc = Loc; + return false; +} + +bool DeclSpec::setFunctionSpecVirtual(SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + // 'virtual virtual' is ok, but warn as this is likely not what the user + // intended. + if (FS_virtual_specified) { + DiagID = diag::warn_duplicate_declspec; + PrevSpec = "virtual"; + return true; + } FS_virtual_specified = true; FS_virtualLoc = Loc; return false; } -bool DeclSpec::setFunctionSpecExplicit(SourceLocation Loc) { - // 'explicit explicit' is ok. +bool DeclSpec::setFunctionSpecExplicit(SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + // 'explicit explicit' is ok, but warn as this is likely not what the user + // intended. + if (FS_explicit_specified) { + DiagID = diag::warn_duplicate_declspec; + PrevSpec = "explicit"; + return true; + } FS_explicit_specified = true; FS_explicitLoc = Loc; return false; } -bool DeclSpec::setFunctionSpecNoreturn(SourceLocation Loc) { - // '_Noreturn _Noreturn' is ok. +bool DeclSpec::setFunctionSpecNoreturn(SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + // '_Noreturn _Noreturn' is ok, but warn as this is likely not what the user + // intended. + if (FS_noreturn_specified) { + DiagID = diag::warn_duplicate_declspec; + PrevSpec = "_Noreturn"; + return true; + } FS_noreturn_specified = true; FS_noreturnLoc = Loc; return false; @@ -1096,6 +1168,7 @@ bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc, switch (VS) { default: llvm_unreachable("Unknown specifier!"); case VS_Override: VS_overrideLoc = Loc; break; + case VS_Sealed: case VS_Final: VS_finalLoc = Loc; break; } @@ -1107,5 +1180,6 @@ const char *VirtSpecifiers::getSpecifierName(Specifier VS) { default: llvm_unreachable("Unknown specifier"); case VS_Override: return "override"; case VS_Final: return "final"; + case VS_Sealed: return "sealed"; } } diff --git a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp index d44c1fb926f5..6e354b9060e3 100644 --- a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp @@ -78,19 +78,6 @@ void IdentifierResolver::IdDeclInfo::RemoveDecl(NamedDecl *D) { llvm_unreachable("Didn't find this decl on its identifier's chain!"); } -bool -IdentifierResolver::IdDeclInfo::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { - for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) { - if (Old == *(I-1)) { - *(I - 1) = New; - return true; - } - } - - return false; -} - - //===----------------------------------------------------------------------===// // IdentifierResolver Implementation //===----------------------------------------------------------------------===// @@ -113,8 +100,7 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S, if (Ctx->isFunctionOrMethod() || S->isFunctionPrototypeScope()) { // Ignore the scopes associated within transparent declaration contexts. - while (S->getEntity() && - ((DeclContext *)S->getEntity())->isTransparentContext()) + while (S->getEntity() && S->getEntity()->isTransparentContext()) S = S->getParent(); if (S->isDeclScope(D)) @@ -235,30 +221,6 @@ void IdentifierResolver::RemoveDecl(NamedDecl *D) { return toIdDeclInfo(Ptr)->RemoveDecl(D); } -bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { - assert(Old->getDeclName() == New->getDeclName() && - "Cannot replace a decl with another decl of a different name"); - - DeclarationName Name = Old->getDeclName(); - if (IdentifierInfo *II = Name.getAsIdentifierInfo()) - updatingIdentifier(*II); - - void *Ptr = Name.getFETokenInfo<void>(); - - if (!Ptr) - return false; - - if (isDeclPtr(Ptr)) { - if (Ptr == Old) { - Name.setFETokenInfo(New); - return true; - } - return false; - } - - return toIdDeclInfo(Ptr)->ReplaceDecl(Old, New); -} - /// begin - Returns an iterator for decls with name 'Name'. IdentifierResolver::iterator IdentifierResolver::begin(DeclarationName Name) { diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp index 5f92cfffc6b0..d3de1732766e 100644 --- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp @@ -175,8 +175,9 @@ static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) { const MaterializeTemporaryExpr *M = NULL; Init = Init->findMaterializedTemporary(M); + SmallVector<const Expr *, 2> CommaLHSs; SmallVector<SubobjectAdjustment, 2> Adjustments; - Init = Init->skipRValueSubobjectAdjustments(Adjustments); + Init = Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); QualType QT = Init->getType(); if (QT.isNull()) @@ -198,7 +199,11 @@ static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) { if (const CXXConstructExpr *cce = dyn_cast<CXXConstructExpr>(Init)) { const CXXConstructorDecl *ctor = cce->getConstructor(); - if (ctor->isTrivial() && ctor->isDefaultConstructor()) { + // For a variable declared without an initializer, we will have + // call-style initialization and the initializer will be the + // CXXConstructExpr with no intervening nodes. + if (ctor->isTrivial() && ctor->isDefaultConstructor() && + VD->getInit() == Init && VD->getInitStyle() == VarDecl::CallInit) { if (OutDiag) InDiag = diag::note_protected_by_variable_nontriv_destructor; else if (!Record->isPOD()) diff --git a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp index d85624ba6f64..ad7627a45715 100644 --- a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp @@ -267,3 +267,34 @@ void MultiplexExternalSemaSource::ReadPendingInstantiations( for(size_t i = 0; i < Sources.size(); ++i) Sources[i]->ReadPendingInstantiations(Pending); } + +void MultiplexExternalSemaSource::ReadLateParsedTemplates( + llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap) { + for (size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ReadLateParsedTemplates(LPTMap); +} + +TypoCorrection MultiplexExternalSemaSource::CorrectTypo( + const DeclarationNameInfo &Typo, + int LookupKind, Scope *S, CXXScopeSpec *SS, + CorrectionCandidateCallback &CCC, + DeclContext *MemberContext, + bool EnteringContext, + const ObjCObjectPointerType *OPT) { + for (size_t I = 0, E = Sources.size(); I < E; ++I) { + if (TypoCorrection C = Sources[I]->CorrectTypo(Typo, LookupKind, S, SS, CCC, + MemberContext, + EnteringContext, OPT)) + return C; + } + return TypoCorrection(); +} + +bool MultiplexExternalSemaSource::MaybeDiagnoseMissingCompleteType( + SourceLocation Loc, QualType T) { + for (size_t I = 0, E = Sources.size(); I < E; ++I) { + if (Sources[I]->MaybeDiagnoseMissingCompleteType(Loc, T)) + return true; + } + return false; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp index 2f48bec123bf..8b3493ebfef8 100644 --- a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp @@ -184,6 +184,21 @@ void FunctionScopeInfo::markSafeWeakUse(const Expr *E) { ThisUse->markSafe(); } +void LambdaScopeInfo::getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E) { + assert(Idx < getNumPotentialVariableCaptures() && + "Index of potential capture must be within 0 to less than the " + "number of captures!"); + E = PotentiallyCapturingExprs[Idx]; + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) + VD = dyn_cast<VarDecl>(DRE->getFoundDecl()); + else if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) + VD = dyn_cast<VarDecl>(ME->getMemberDecl()); + else + llvm_unreachable("Only DeclRefExprs or MemberExprs should be added for " + "potential captures"); + assert(VD); +} + FunctionScopeInfo::~FunctionScopeInfo() { } BlockScopeInfo::~BlockScopeInfo() { } LambdaScopeInfo::~LambdaScopeInfo() { } diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp index e718be2f8bd5..4d01fb0a6be6 100644 --- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp @@ -89,8 +89,10 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, NumSFINAEErrors(0), InFunctionDeclarator(0), AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1), - CurrentInstantiationScope(0), TyposCorrected(0), - AnalysisWarnings(*this), CurScope(0), Ident_super(0) + CurrentInstantiationScope(0), DisableTypoCorrection(false), + TyposCorrected(0), AnalysisWarnings(*this), + VarDataSharingAttributesStack(0), CurScope(0), + Ident_super(0), Ident___float128(0) { TUScope = 0; @@ -113,6 +115,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, false, 0, false)); FunctionScopes.push_back(new FunctionScopeInfo(Diags)); + + // Initilization of data sharing attributes stack for OpenMP + InitDataSharingAttributesStack(); } void Sema::Initialize() { @@ -173,6 +178,10 @@ void Sema::Initialize() { } Sema::~Sema() { + for (LateParsedTemplateMapT::iterator I = LateParsedTemplateMap.begin(), + E = LateParsedTemplateMap.end(); + I != E; ++I) + delete I->second; if (PackContext) FreePackedContext(); if (VisContext) FreeVisContext(); delete TheTargetAttributesSema; @@ -195,6 +204,9 @@ Sema::~Sema() { // If Sema's ExternalSource is the multiplexer - we own it. if (isMultiplexExternalSource) delete ExternalSource; + + // Destroys data sharing attributes stack for OpenMP + DestroyDataSharingAttributesStack(); } /// makeUnavailableInSystemHeader - There is an error in the current @@ -284,9 +296,6 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, if (ExprTy == TypeTy) return Owned(E); - if (getLangOpts().ObjCAutoRefCount) - CheckObjCARCConversion(SourceRange(), Ty, E, CCK); - // If this is a derived-to-base cast to a through a virtual base, we // need a vtable. if (Kind == CK_DerivedToBase && @@ -332,7 +341,7 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { if (D->getMostRecentDecl()->isUsed()) return true; - if (D->hasExternalLinkage()) + if (D->isExternallyVisible()) return true; if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { @@ -350,6 +359,15 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { } if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + // If a variable usable in constant expressions is referenced, + // don't warn if it isn't used: if the value of a variable is required + // for the computation of a constant expression, it doesn't make sense to + // warn even if the variable isn't odr-used. (isReferenced doesn't + // precisely reflect that, but it's a decent approximation.) + if (VD->isReferenced() && + VD->isUsableInConstantExpressions(SemaRef->Context)) + return true; + // UnusedFileScopedDecls stores the first declaration. // The declaration may have become definition so check again. const VarDecl *DeclToCheck = VD->getDefinition(); @@ -402,13 +420,13 @@ void Sema::getUndefinedButUsed( if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { if (FD->isDefined()) continue; - if (FD->hasExternalLinkage() && + if (FD->isExternallyVisible() && !FD->getMostRecentDecl()->isInlined()) continue; } else { if (cast<VarDecl>(ND)->hasDefinition() != VarDecl::DeclarationOnly) continue; - if (ND->hasExternalLinkage()) + if (ND->isExternallyVisible()) continue; } @@ -435,7 +453,7 @@ static void checkUndefinedButUsed(Sema &S) { I = Undefined.begin(), E = Undefined.end(); I != E; ++I) { NamedDecl *ND = I->first; - if (ND->getLinkage() != ExternalLinkage) { + if (!ND->isExternallyVisible()) { S.Diag(ND->getLocation(), diag::warn_undefined_internal) << isa<VarDecl>(ND) << ND; } else { @@ -551,9 +569,9 @@ void Sema::ActOnEndOfTranslationUnit() { if (PP.isCodeCompletionEnabled()) return; - // Only complete translation units define vtables and perform implicit - // instantiations. - if (TUKind == TU_Complete) { + // Complete translation units and modules define vtables and perform implicit + // instantiations. PCH files do not. + if (TUKind != TU_Prefix) { DiagnoseUseOfUnimplementedSelectors(); // If any dynamic classes have their key function defined within @@ -582,13 +600,18 @@ void Sema::ActOnEndOfTranslationUnit() { // carefully keep track of the point of instantiation (C++ [temp.point]). // This means that name lookup that occurs within the template // instantiation will always happen at the end of the translation unit, - // so it will find some names that should not be found. Although this is - // common behavior for C++ compilers, it is technically wrong. In the - // future, we either need to be able to filter the results of name lookup - // or we need to perform template instantiations earlier. + // so it will find some names that are not required to be found. This is + // valid, but we could do better by diagnosing if an instantiation uses a + // name that was not visible at its first point of instantiation. PerformPendingInstantiations(); + CheckDelayedMemberExceptionSpecs(); } + // All delayed member exception specs should be checked or we end up accepting + // incompatible declarations. + assert(DelayedDefaultedMemberExceptionSpecs.empty()); + assert(DelayedDestructorExceptionSpecChecks.empty()); + // Remove file scoped decls that turned out to be used. UnusedFileScopedDecls.erase( std::remove_if(UnusedFileScopedDecls.begin(0, true), @@ -630,14 +653,14 @@ void Sema::ActOnEndOfTranslationUnit() { SmallVector<Module *, 2> Stack; Stack.push_back(CurrentModule); while (!Stack.empty()) { - Module *Mod = Stack.back(); - Stack.pop_back(); + Module *Mod = Stack.pop_back_val(); // Resolve the exported declarations and conflicts. // FIXME: Actually complain, once we figure out how to teach the // diagnostic client to deal with complaints in the module map at this // point. ModMap.resolveExports(Mod, /*Complain=*/false); + ModMap.resolveUses(Mod, /*Complain=*/false); ModMap.resolveConflicts(Mod, /*Complain=*/false); // Queue the submodules, so their exports will also be resolved. @@ -681,13 +704,6 @@ void Sema::ActOnEndOfTranslationUnit() { if (const IncompleteArrayType *ArrayT = Context.getAsIncompleteArrayType(VD->getType())) { - if (RequireCompleteType(VD->getLocation(), - ArrayT->getElementType(), - diag::err_tentative_def_incomplete_type_arr)) { - VD->setInvalidDecl(); - continue; - } - // Set the length of the array to 1 (C99 6.9.2p5). Diag(VD->getLocation(), diag::warn_tentative_incomplete_array); llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true); @@ -729,7 +745,7 @@ void Sema::ActOnEndOfTranslationUnit() { else { if (FD->getStorageClass() == SC_Static && !FD->isInlineSpecified() && - !SourceMgr.isFromMainFile( + !SourceMgr.isInMainFile( SourceMgr.getExpansionLoc(FD->getLocation()))) Diag(DiagD->getLocation(), diag::warn_unneeded_static_internal_decl) << DiagD->getDeclName(); @@ -750,11 +766,10 @@ void Sema::ActOnEndOfTranslationUnit() { if (DiagD->isReferenced()) { Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl) << /*variable*/1 << DiagD->getDeclName(); - } else if (getSourceManager().isFromMainFile(DiagD->getLocation())) { - // If the declaration is in a header which is included into multiple - // TUs, it will declare one variable per TU, and one of the other - // variables may be used. So, only warn if the declaration is in the - // main file. + } else if (DiagD->getType().isConstQualified()) { + Diag(DiagD->getLocation(), diag::warn_unused_const_variable) + << DiagD->getDeclName(); + } else { Diag(DiagD->getLocation(), diag::warn_unused_variable) << DiagD->getDeclName(); } @@ -824,6 +839,8 @@ FunctionDecl *Sema::getCurFunctionDecl() { ObjCMethodDecl *Sema::getCurMethodDecl() { DeclContext *DC = getFunctionLevelDeclContext(); + while (isa<RecordDecl>(DC)) + DC = DC->getParent(); return dyn_cast<ObjCMethodDecl>(DC); } @@ -986,7 +1003,7 @@ Scope *Sema::getScopeForContext(DeclContext *Ctx) { // Ignore scopes that cannot have declarations. This is important for // out-of-line definitions of static class members. if (S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) - if (DeclContext *Entity = static_cast<DeclContext *> (S->getEntity())) + if (DeclContext *Entity = S->getEntity()) if (Ctx == Entity->getPrimaryContext()) return S; } @@ -1012,10 +1029,19 @@ void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) { BlockScope, Block)); } -void Sema::PushLambdaScope(CXXRecordDecl *Lambda, - CXXMethodDecl *CallOperator) { - FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda, - CallOperator)); +LambdaScopeInfo *Sema::PushLambdaScope() { + LambdaScopeInfo *const LSI = new LambdaScopeInfo(getDiagnostics()); + FunctionScopes.push_back(LSI); + return LSI; +} + +void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) { + if (LambdaScopeInfo *const LSI = getCurLambda()) { + LSI->AutoTemplateParameterDepth = Depth; + return; + } + llvm_unreachable( + "Remove assertion if intentionally called in a non-lambda context."); } void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP, @@ -1071,6 +1097,16 @@ LambdaScopeInfo *Sema::getCurLambda() { return dyn_cast<LambdaScopeInfo>(FunctionScopes.back()); } +// We have a generic lambda if we parsed auto parameters, or we have +// an associated template parameter list. +LambdaScopeInfo *Sema::getCurGenericLambda() { + if (LambdaScopeInfo *LSI = getCurLambda()) { + return (LSI->AutoTemplateParams.size() || + LSI->GLTemplateParameterList) ? LSI : 0; + } + return 0; +} + void Sema::ActOnComment(SourceRange Comment) { if (!LangOpts.RetainCommentsFromSystemHeaders && @@ -1141,33 +1177,68 @@ void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const { /// call; otherwise, it is set to an empty QualType. /// \param OverloadSet - If the expression is an overloaded function /// name, this parameter is populated with the decls of the various overloads. -bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy, - UnresolvedSetImpl &OverloadSet) { +bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy, + UnresolvedSetImpl &OverloadSet) { ZeroArgCallReturnTy = QualType(); OverloadSet.clear(); + const OverloadExpr *Overloads = NULL; + bool IsMemExpr = false; if (E.getType() == Context.OverloadTy) { OverloadExpr::FindResult FR = OverloadExpr::find(const_cast<Expr*>(&E)); - const OverloadExpr *Overloads = FR.Expression; + // Ignore overloads that are pointer-to-member constants. + if (FR.HasFormOfMemberPointer) + return false; + + Overloads = FR.Expression; + } else if (E.getType() == Context.BoundMemberTy) { + Overloads = dyn_cast<UnresolvedMemberExpr>(E.IgnoreParens()); + IsMemExpr = true; + } + + bool Ambiguous = false; + + if (Overloads) { for (OverloadExpr::decls_iterator it = Overloads->decls_begin(), DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) { OverloadSet.addDecl(*it); - // Check whether the function is a non-template which takes no + // Check whether the function is a non-template, non-member which takes no // arguments. + if (IsMemExpr) + continue; if (const FunctionDecl *OverloadDecl = dyn_cast<FunctionDecl>((*it)->getUnderlyingDecl())) { - if (OverloadDecl->getMinRequiredArguments() == 0) - ZeroArgCallReturnTy = OverloadDecl->getResultType(); + if (OverloadDecl->getMinRequiredArguments() == 0) { + if (!ZeroArgCallReturnTy.isNull() && !Ambiguous) { + ZeroArgCallReturnTy = QualType(); + Ambiguous = true; + } else + ZeroArgCallReturnTy = OverloadDecl->getResultType(); + } } } - // Ignore overloads that are pointer-to-member constants. - if (FR.HasFormOfMemberPointer) - return false; + // If it's not a member, use better machinery to try to resolve the call + if (!IsMemExpr) + return !ZeroArgCallReturnTy.isNull(); + } - return true; + // Attempt to call the member with no arguments - this will correctly handle + // member templates with defaults/deduction of template arguments, overloads + // with default arguments, etc. + if (IsMemExpr && !E.isTypeDependent()) { + bool Suppress = getDiagnostics().getSuppressAllDiagnostics(); + getDiagnostics().setSuppressAllDiagnostics(true); + ExprResult R = BuildCallToMemberFunction(NULL, &E, SourceLocation(), None, + SourceLocation()); + getDiagnostics().setSuppressAllDiagnostics(Suppress); + if (R.isUsable()) { + ZeroArgCallReturnTy = R.get()->getType(); + return true; + } + return false; } if (const DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E.IgnoreParens())) { @@ -1187,14 +1258,6 @@ bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy, FunTy = PointeeTy->getAs<FunctionType>(); if (!FunTy) FunTy = ExprTy->getAs<FunctionType>(); - if (!FunTy && ExprTy == Context.BoundMemberTy) { - // Look for the bound-member type. If it's still overloaded, give up, - // although we probably should have fallen into the OverloadExpr case above - // if we actually have an overloaded bound member. - QualType BoundMemberTy = Expr::findBoundMemberType(&E); - if (!BoundMemberTy.isNull()) - FunTy = BoundMemberTy->castAs<FunctionType>(); - } if (const FunctionProtoType *FPT = dyn_cast_or_null<FunctionProtoType>(FunTy)) { @@ -1207,7 +1270,7 @@ bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy, /// \brief Give notes for a set of overloads. /// -/// A companion to isExprCallable. In cases when the name that the programmer +/// A companion to tryExprAsCall. In cases when the name that the programmer /// wrote was an overloaded function, we may be able to make some guesses about /// plausible overloads based on their return types; such guesses can be handed /// off to this method to be emitted as notes. @@ -1277,15 +1340,14 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, QualType ZeroArgCallTy; UnresolvedSet<4> Overloads; - if (isExprCallable(*E.get(), ZeroArgCallTy, Overloads) && + if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) && !ZeroArgCallTy.isNull() && (!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) { // At this point, we know E is potentially callable with 0 // arguments and that it returns something of a reasonable type, // so we can emit a fixit and carry on pretending that E was // actually a CallExpr. - SourceLocation ParenInsertionLoc = - PP.getLocForEndOfToken(Range.getEnd()); + SourceLocation ParenInsertionLoc = PP.getLocForEndOfToken(Range.getEnd()); Diag(Loc, PD) << /*zero-arg*/ 1 << Range << (IsCallableWithAppend(E.get()) @@ -1295,8 +1357,8 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, // FIXME: Try this before emitting the fixit, and suppress diagnostics // while doing so. - E = ActOnCallExpr(0, E.take(), ParenInsertionLoc, - None, ParenInsertionLoc.getLocWithOffset(1)); + E = ActOnCallExpr(0, E.take(), Range.getEnd(), None, + Range.getEnd().getLocWithOffset(1)); return true; } @@ -1314,6 +1376,12 @@ IdentifierInfo *Sema::getSuperIdentifier() const { return Ident_super; } +IdentifierInfo *Sema::getFloat128Identifier() const { + if (!Ident___float128) + Ident___float128 = &Context.Idents.get("__float128"); + return Ident___float128; +} + void Sema::PushCapturedRegionScope(Scope *S, CapturedDecl *CD, RecordDecl *RD, CapturedRegionKind K) { CapturingScopeInfo *CSI = new CapturedRegionScopeInfo(getDiagnostics(), S, CD, RD, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp index 3ef1fdebaac7..61dc157f8589 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp @@ -315,8 +315,7 @@ static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived, if (Queue.empty()) break; - Derived = Queue.back(); - Queue.pop_back(); + Derived = Queue.pop_back_val(); } return OnFailure; @@ -1484,7 +1483,9 @@ void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *D) { DeclContext *DC = D->getDeclContext(); if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) { - if (!DC->isFunctionOrMethod()) + if (D->getLexicalDeclContext()->isFunctionOrMethod()) + DC = D->getLexicalDeclContext(); + else DC = FN; } else if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) { DC = cast<DeclContext>(TD->getTemplatedDecl()); @@ -1649,9 +1650,9 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, } case InitializedEntity::EK_LambdaCapture: { - const VarDecl *Var = Entity.getCapturedVar(); + StringRef VarName = Entity.getCapturedVarName(); PD = PDiag(diag::err_access_lambda_capture); - PD << Var->getName() << Entity.getType() << getSpecialMember(Constructor); + PD << VarName << Entity.getType() << getSpecialMember(Constructor); break; } @@ -1710,6 +1711,21 @@ Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, return CheckAccess(*this, OpLoc, Entity); } +/// \brief Checks access to a member. +Sema::AccessResult Sema::CheckMemberAccess(SourceLocation UseLoc, + CXXRecordDecl *NamingClass, + DeclAccessPair Found) { + if (!getLangOpts().AccessControl || + !NamingClass || + Found.getAccess() == AS_public) + return AR_accessible; + + AccessTarget Entity(Context, AccessTarget::Member, NamingClass, + Found, QualType()); + + return CheckAccess(*this, UseLoc, Entity); +} + /// Checks access to an overloaded member operator, including /// conversion operators. Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, @@ -1872,9 +1888,7 @@ bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) { 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; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp index e12bbde0d0dd..8f9ab32517d6 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" +#include "clang/AST/ASTConsumer.h" #include "clang/AST/Attr.h" #include "clang/AST/Expr.h" #include "clang/Basic/TargetInfo.h" @@ -263,6 +264,30 @@ void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) { MSStructPragmaOn = (Kind == PMSST_ON); } +void Sema::ActOnPragmaMSComment(PragmaMSCommentKind Kind, StringRef Arg) { + // FIXME: Serialize this. + switch (Kind) { + case PCK_Unknown: + llvm_unreachable("unexpected pragma comment kind"); + case PCK_Linker: + Consumer.HandleLinkerOptionPragma(Arg); + return; + case PCK_Lib: + Consumer.HandleDependentLibrary(Arg); + return; + case PCK_Compiler: + case PCK_ExeStr: + case PCK_User: + return; // We ignore all of these. + } + llvm_unreachable("invalid pragma comment kind"); +} + +void Sema::ActOnPragmaDetectMismatch(StringRef Name, StringRef Value) { + // FIXME: Serialize this. + Consumer.HandleDetectMismatch(Name, Value); +} + void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope, SourceLocation PragmaLoc) { @@ -343,21 +368,12 @@ void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType, SourceLocation PragmaLoc) { if (VisType) { // Compute visibility to use. - VisibilityAttr::VisibilityType type; - if (VisType->isStr("default")) - type = VisibilityAttr::Default; - else if (VisType->isStr("hidden")) - type = VisibilityAttr::Hidden; - else if (VisType->isStr("internal")) - type = VisibilityAttr::Hidden; // FIXME - else if (VisType->isStr("protected")) - type = VisibilityAttr::Protected; - else { - Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << - VisType->getName(); + VisibilityAttr::VisibilityType T; + if (!VisibilityAttr::ConvertStrToVisibilityType(VisType->getName(), T)) { + Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << VisType; return; } - PushPragmaVisibility(*this, type, PragmaLoc); + PushPragmaVisibility(*this, T, PragmaLoc); } else { PopPragmaVisibility(false, PragmaLoc); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp index 01ac8f7fb62d..554a114bae60 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -160,16 +160,6 @@ bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) { return SS.getScopeRep()->isDependent(); } -// \brief Determine whether this C++ scope specifier refers to an -// unknown specialization, i.e., a dependent type that is not the -// current instantiation. -bool Sema::isUnknownSpecialization(const CXXScopeSpec &SS) { - if (!isDependentScopeSpecifier(SS)) - return false; - - return getCurrentInstantiationOf(SS.getScopeRep()) == 0; -} - /// \brief If the given nested name specifier refers to the current /// instantiation, return the declaration that corresponds to that /// current instantiation (C++0x [temp.dep.type]p1). @@ -494,32 +484,30 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, // FIXME: Deal with ambiguities cleanly. - if (Found.empty() && !ErrorRecoveryLookup) { + if (Found.empty() && !ErrorRecoveryLookup && !getLangOpts().MicrosoftMode) { // 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, 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() - << FixItHint::CreateReplacement(Corrected.getCorrectionRange(), - CorrectedStr); - else - Diag(Found.getNameLoc(), diag::err_undeclared_var_use_suggest) - << Name << CorrectedQuotedStr - << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr); - - if (NamedDecl *ND = Corrected.getCorrectionDecl()) { - Diag(ND->getLocation(), diag::note_previous_decl) << CorrectedQuotedStr; + if (TypoCorrection Corrected = + CorrectTypo(Found.getLookupNameInfo(), Found.getLookupKind(), S, + &SS, Validator, LookupCtx, EnteringContext)) { + if (LookupCtx) { + bool DroppedSpecifier = + Corrected.WillReplaceSpecifier() && + Name.getAsString() == Corrected.getAsString(getLangOpts()); + if (DroppedSpecifier) + SS.clear(); + diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest) + << Name << LookupCtx << DroppedSpecifier + << SS.getRange()); + } else + diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest) + << Name); + + if (NamedDecl *ND = Corrected.getCorrectionDecl()) Found.addDecl(ND); - } Found.setLookupName(Corrected.getCorrection()); } else { Found.setLookupName(&Identifier); @@ -658,7 +646,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, // public: // void foo() { D::foo2(); } // }; - if (getLangOpts().MicrosoftExt) { + if (getLangOpts().MicrosoftMode) { DeclContext *DC = LookupCtx ? LookupCtx : CurContext; if (DC->isDependentContext() && DC->isFunctionOrMethod()) { SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp index eb11a577cb0a..ba00b712aad5 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp @@ -200,8 +200,9 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, unsigned &msg, CastKind &Kind, CXXCastPath &BasePath, bool ListInitialization); -static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, - bool CStyle, unsigned &msg); +static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr, + QualType DestType, bool CStyle, + unsigned &msg); static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, @@ -242,7 +243,9 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, // If the type is dependent, we won't do the semantic analysis now. // FIXME: should we check this in a more fine-grained manner? - bool TypeDependent = DestType->isDependentType() || Ex.get()->isTypeDependent(); + bool TypeDependent = DestType->isDependentType() || + Ex.get()->isTypeDependent() || + Ex.get()->isValueDependent(); CastOperation Op(*this, DestType, E); Op.OpRange = SourceRange(OpLoc, Parens.getEnd()); @@ -383,11 +386,6 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT, static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType, 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, listInitialization)) @@ -515,8 +513,8 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType, QualType SrcConstruct = Self.Context.VoidTy; QualType DestConstruct = Self.Context.VoidTy; ASTContext &Context = Self.Context; - for (SmallVector<Qualifiers, 8>::reverse_iterator i1 = cv1.rbegin(), - i2 = cv2.rbegin(); + for (SmallVectorImpl<Qualifiers>::reverse_iterator i1 = cv1.rbegin(), + i2 = cv2.rbegin(); i1 != cv1.rend(); ++i1, ++i2) { SrcConstruct = Context.getPointerType(Context.getQualifiedType(SrcConstruct, *i1)); @@ -558,6 +556,7 @@ void CastOperation::CheckDynamicCast() { } else { Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr) << this->DestType << DestRange; + SrcExpr = ExprError(); return; } @@ -567,11 +566,14 @@ void CastOperation::CheckDynamicCast() { } else if (DestRecord) { if (Self.RequireCompleteType(OpRange.getBegin(), DestPointee, diag::err_bad_dynamic_cast_incomplete, - DestRange)) + DestRange)) { + SrcExpr = ExprError(); return; + } } else { Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class) << DestPointee.getUnqualifiedType() << DestRange; + SrcExpr = ExprError(); return; } @@ -587,6 +589,7 @@ void CastOperation::CheckDynamicCast() { } else { Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ptr) << OrigSrcType << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); return; } } else if (DestReference->isLValueReferenceType()) { @@ -603,11 +606,14 @@ void CastOperation::CheckDynamicCast() { if (SrcRecord) { if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee, diag::err_bad_dynamic_cast_incomplete, - SrcExpr.get())) + SrcExpr.get())) { + SrcExpr = ExprError(); return; + } } else { Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class) << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); return; } @@ -621,6 +627,7 @@ void CastOperation::CheckDynamicCast() { if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) { Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_qualifiers_away) << CT_Dynamic << OrigSrcType << this->DestType << OpRange; + SrcExpr = ExprError(); return; } @@ -636,8 +643,10 @@ void CastOperation::CheckDynamicCast() { if (DestRecord && Self.IsDerivedFrom(SrcPointee, DestPointee)) { if (Self.CheckDerivedToBaseConversion(SrcPointee, DestPointee, OpRange.getBegin(), OpRange, - &BasePath)) - return; + &BasePath)) { + SrcExpr = ExprError(); + return; + } Kind = CK_DerivedToBase; @@ -655,10 +664,20 @@ void CastOperation::CheckDynamicCast() { if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) { Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic) << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); } Self.MarkVTableUsed(OpRange.getBegin(), cast<CXXRecordDecl>(SrcRecord->getDecl())); + // dynamic_cast is not available with -fno-rtti. + // As an exception, dynamic_cast to void* is available because it doesn't + // use RTTI. + if (!Self.getLangOpts().RTTI && !DestPointee->isVoidType()) { + Self.Diag(OpRange.getBegin(), diag::err_no_dynamic_cast_with_fno_rtti); + SrcExpr = ExprError(); + return; + } + // Done. Everything else is run-time checks. Kind = CK_Dynamic; } @@ -677,10 +696,12 @@ void CastOperation::CheckConstCast() { return; unsigned msg = diag::err_bad_cxx_cast_generic; - if (TryConstCast(Self, SrcExpr.get(), DestType, /*CStyle*/false, msg) != TC_Success - && msg != 0) + if (TryConstCast(Self, SrcExpr, DestType, /*CStyle*/false, msg) != TC_Success + && msg != 0) { Self.Diag(OpRange.getBegin(), msg) << CT_Const << SrcExpr.get()->getType() << DestType << OpRange; + SrcExpr = ExprError(); + } } /// Check that a reinterpret_cast\<DestType\>(SrcExpr) is not used as upcast @@ -758,6 +779,7 @@ static void DiagnoseReinterpretUpDownCast(Sema &Self, const Expr *SrcExpr, VirtualBase = VirtualBase && IsVirtual; } + (void) NonZeroOffset; // Silence set but not used warning. assert((VirtualBase || NonZeroOffset) && "Should have returned if has non-virtual base with zero offset"); @@ -768,10 +790,10 @@ static void DiagnoseReinterpretUpDownCast(Sema &Self, const Expr *SrcExpr, SourceLocation BeginLoc = OpRange.getBegin(); Self.Diag(BeginLoc, diag::warn_reinterpret_different_from_static) - << DerivedType << BaseType << !VirtualBase << ReinterpretKind + << DerivedType << BaseType << !VirtualBase << int(ReinterpretKind) << OpRange; Self.Diag(BeginLoc, diag::note_reinterpret_updowncast_use_static) - << ReinterpretKind + << int(ReinterpretKind) << FixItHint::CreateReplacement(BeginLoc, "static_cast"); } @@ -807,6 +829,7 @@ void CastOperation::CheckReinterpretCast() { diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(), DestType, /*listInitialization=*/false); } + SrcExpr = ExprError(); } else if (tcr == TC_Success) { if (Self.getLangOpts().ObjCAutoRefCount) checkObjCARCConversion(Sema::CCK_OtherCast); @@ -868,6 +891,7 @@ void CastOperation::CheckStaticCast() { diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType, /*listInitialization=*/false); } + SrcExpr = ExprError(); } else if (tcr == TC_Success) { if (Kind == CK_BitCast) checkCastAlign(); @@ -1447,12 +1471,26 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, /// TryConstCast - See if a const_cast from source to destination is allowed, /// and perform it if it is. -static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, - bool CStyle, unsigned &msg) { +static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr, + QualType DestType, bool CStyle, + unsigned &msg) { DestType = Self.Context.getCanonicalType(DestType); - QualType SrcType = SrcExpr->getType(); + QualType SrcType = SrcExpr.get()->getType(); + bool NeedToMaterializeTemporary = false; + if (const ReferenceType *DestTypeTmp =DestType->getAs<ReferenceType>()) { - if (isa<LValueReferenceType>(DestTypeTmp) && !SrcExpr->isLValue()) { + // C++11 5.2.11p4: + // if a pointer to T1 can be explicitly converted to the type "pointer to + // T2" using a const_cast, then the following conversions can also be + // made: + // -- an lvalue of type T1 can be explicitly converted to an lvalue of + // type T2 using the cast const_cast<T2&>; + // -- a glvalue of type T1 can be explicitly converted to an xvalue of + // type T2 using the cast const_cast<T2&&>; and + // -- if T1 is a class type, a prvalue of type T1 can be explicitly + // converted to an xvalue of type T2 using the cast const_cast<T2&&>. + + if (isa<LValueReferenceType>(DestTypeTmp) && !SrcExpr.get()->isLValue()) { // Cannot const_cast non-lvalue to lvalue reference type. But if this // is C-style, static_cast might find a way, so we simply suggest a // message and tell the parent to keep searching. @@ -1460,18 +1498,29 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, return TC_NotApplicable; } + if (isa<RValueReferenceType>(DestTypeTmp) && SrcExpr.get()->isRValue()) { + if (!SrcType->isRecordType()) { + // Cannot const_cast non-class prvalue to rvalue reference type. But if + // this is C-style, static_cast can do this. + msg = diag::err_bad_cxx_cast_rvalue; + return TC_NotApplicable; + } + + // Materialize the class prvalue so that the const_cast can bind a + // reference to it. + NeedToMaterializeTemporary = true; + } + // It's not completely clear under the standard whether we can // const_cast bit-field gl-values. Doing so would not be // intrinsically complicated, but for now, we say no for // consistency with other compilers and await the word of the // committee. - if (SrcExpr->refersToBitField()) { + if (SrcExpr.get()->refersToBitField()) { msg = diag::err_bad_cxx_cast_bitfield; return TC_NotApplicable; } - // C++ 5.2.11p4: An lvalue of type T1 can be [cast] to an lvalue of type T2 - // [...] if a pointer to T1 can be [cast] to the type pointer to T2. DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); SrcType = Self.Context.getPointerType(SrcType); } @@ -1525,6 +1574,13 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, if (SrcType != DestType) return TC_NotApplicable; + if (NeedToMaterializeTemporary) + // This is a const_cast from a class prvalue to an rvalue reference type. + // Materialize a temporary to store the result of the conversion. + SrcExpr = new (Self.Context) MaterializeTemporaryExpr( + SrcType, SrcExpr.take(), /*IsLValueReference*/ false, + /*ExtendingDecl*/ 0); + return TC_Success; } @@ -1614,8 +1670,18 @@ static void checkIntToPointerCast(bool CStyle, SourceLocation Loc, && !SrcType->isBooleanType() && !SrcType->isEnumeralType() && !SrcExpr->isIntegerConstantExpr(Self.Context) - && Self.Context.getTypeSize(DestType) > Self.Context.getTypeSize(SrcType)) - Self.Diag(Loc, diag::warn_int_to_pointer_cast) << SrcType << DestType; + && Self.Context.getTypeSize(DestType) > + Self.Context.getTypeSize(SrcType)) { + // Separate between casts to void* and non-void* pointers. + // Some APIs use (abuse) void* for something like a user context, + // and often that value is an integer even if it isn't a pointer itself. + // Having a separate warning flag allows users to control the warning + // for their workflow. + unsigned Diag = DestType->isVoidPointerType() ? + diag::warn_int_to_void_pointer_cast + : diag::warn_int_to_pointer_cast; + Self.Diag(Loc, Diag) << SrcType << DestType; + } } static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, @@ -1803,10 +1869,12 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, assert(srcIsPtr && "One type must be a pointer"); // C++ 5.2.10p4: A pointer can be explicitly converted to any integral // type large enough to hold it; except in Microsoft mode, where the - // integral type size doesn't matter. + // integral type size doesn't matter (except we don't allow bool). + bool MicrosoftException = Self.getLangOpts().MicrosoftExt && + !DestType->isBooleanType(); if ((Self.Context.getTypeSize(SrcType) > Self.Context.getTypeSize(DestType)) && - !Self.getLangOpts().MicrosoftExt) { + !MicrosoftException) { msg = diag::err_bad_reinterpret_cast_small_int; return TC_Failed; } @@ -1940,14 +2008,12 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, } SrcExpr = Self.IgnoredValueConversions(SrcExpr.take()); - if (SrcExpr.isInvalid()) - return; - return; } // If the type is dependent, we won't do any other semantic analysis now. - if (DestType->isDependentType() || SrcExpr.get()->isTypeDependent()) { + if (DestType->isDependentType() || SrcExpr.get()->isTypeDependent() || + SrcExpr.get()->isValueDependent()) { assert(Kind == CK_Dependent); return; } @@ -1980,8 +2046,10 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, // even if a cast resulting from that interpretation is ill-formed. // In plain language, this means trying a const_cast ... unsigned msg = diag::err_bad_cxx_cast_generic; - TryCastResult tcr = TryConstCast(Self, SrcExpr.get(), DestType, + TryCastResult tcr = TryConstCast(Self, SrcExpr, DestType, /*CStyle*/true, msg); + if (SrcExpr.isInvalid()) + return; if (tcr == TC_Success) Kind = CK_NoOp; @@ -2298,9 +2366,9 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo, return ExprError(); if (CXXConstructExpr *ConstructExpr = dyn_cast<CXXConstructExpr>(Op.SrcExpr.get())) - ConstructExpr->setParenRange(SourceRange(LPLoc, RPLoc)); + ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc)); return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType, - Op.ValueKind, CastTypeInfo, Op.DestRange.getBegin(), - Op.Kind, Op.SrcExpr.take(), &Op.BasePath, RPLoc)); + Op.ValueKind, CastTypeInfo, Op.Kind, + Op.SrcExpr.take(), &Op.BasePath, LPLoc, RPLoc)); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp index 7b5f4f0705bc..0530a043953f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp @@ -32,9 +32,9 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/raw_ostream.h" #include <limits> @@ -95,6 +95,22 @@ static bool SemaBuiltinAnnotation(Sema &S, CallExpr *TheCall) { return false; } +/// Check that the argument to __builtin_addressof is a glvalue, and set the +/// result type to the corresponding pointer type. +static bool SemaBuiltinAddressof(Sema &S, CallExpr *TheCall) { + if (checkArgCount(S, TheCall, 1)) + return true; + + ExprResult Arg(S.Owned(TheCall->getArg(0))); + QualType ResultType = S.CheckAddressOfOperand(Arg, TheCall->getLocStart()); + if (ResultType.isNull()) + return true; + + TheCall->setArg(0, Arg.take()); + TheCall->setType(ResultType); + return false; +} + ExprResult Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { ExprResult TheCallResult(Owned(TheCall)); @@ -275,6 +291,10 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (SemaBuiltinAnnotation(*this, TheCall)) return ExprError(); break; + case Builtin::BI__builtin_addressof: + if (SemaBuiltinAddressof(*this, TheCall)) + return ExprError(); + break; } // Since the target specific builtins for each arch overlap, only check those @@ -286,6 +306,10 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (CheckARMBuiltinFunctionCall(BuiltinID, TheCall)) return ExprError(); break; + case llvm::Triple::aarch64: + if (CheckAArch64BuiltinFunctionCall(BuiltinID, TheCall)) + return ExprError(); + break; case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::mips64: @@ -315,6 +339,7 @@ static unsigned RFT(unsigned t, bool shift = false) { case NeonTypeFlags::Int32: return shift ? 31 : (2 << IsQuad) - 1; case NeonTypeFlags::Int64: + case NeonTypeFlags::Poly64: return shift ? 63 : (1 << IsQuad) - 1; case NeonTypeFlags::Float16: assert(!shift && "cannot shift float types!"); @@ -322,6 +347,9 @@ static unsigned RFT(unsigned t, bool shift = false) { case NeonTypeFlags::Float32: assert(!shift && "cannot shift float types!"); return (2 << IsQuad) - 1; + case NeonTypeFlags::Float64: + assert(!shift && "cannot shift float types!"); + return (1 << IsQuad) - 1; } llvm_unreachable("Invalid NeonTypeFlag!"); } @@ -329,7 +357,8 @@ static unsigned RFT(unsigned t, bool shift = false) { /// 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) { +static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context, + bool IsAArch64) { switch (Flags.getEltType()) { case NeonTypeFlags::Int8: return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy; @@ -340,20 +369,213 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context) { case NeonTypeFlags::Int64: return Flags.isUnsigned() ? Context.UnsignedLongLongTy : Context.LongLongTy; case NeonTypeFlags::Poly8: - return Context.SignedCharTy; + return IsAArch64 ? Context.UnsignedCharTy : Context.SignedCharTy; case NeonTypeFlags::Poly16: - return Context.ShortTy; + return IsAArch64 ? Context.UnsignedShortTy : Context.ShortTy; + case NeonTypeFlags::Poly64: + return Context.UnsignedLongLongTy; case NeonTypeFlags::Float16: - return Context.UnsignedShortTy; + return Context.HalfTy; case NeonTypeFlags::Float32: return Context.FloatTy; + case NeonTypeFlags::Float64: + return Context.DoubleTy; } llvm_unreachable("Invalid NeonTypeFlag!"); } +bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, + CallExpr *TheCall) { + + llvm::APSInt Result; + + uint64_t mask = 0; + unsigned TV = 0; + int PtrArgNum = -1; + bool HasConstPtr = false; + switch (BuiltinID) { +#define GET_NEON_AARCH64_OVERLOAD_CHECK +#include "clang/Basic/arm_neon.inc" +#undef GET_NEON_AARCH64_OVERLOAD_CHECK + } + + // For NEON intrinsics which are overloaded on vector element type, validate + // the immediate which specifies which variant to emit. + unsigned ImmArg = TheCall->getNumArgs() - 1; + if (mask) { + if (SemaBuiltinConstantArg(TheCall, ImmArg, Result)) + return true; + + TV = Result.getLimitedValue(64); + if ((TV > 63) || (mask & (1ULL << TV)) == 0) + return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code) + << TheCall->getArg(ImmArg)->getSourceRange(); + } + + if (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, true); + if (HasConstPtr) + EltTy = EltTy.withConst(); + QualType LHSTy = Context.getPointerType(EltTy); + AssignConvertType ConvTy; + ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS); + if (RHS.isInvalid()) + return true; + if (DiagnoseAssignmentResult(ConvTy, Arg->getLocStart(), LHSTy, RHSTy, + RHS.get(), AA_Assigning)) + return true; + } + + // For NEON intrinsics which take an immediate value as part of the + // instruction, range check them here. + unsigned i = 0, l = 0, u = 0; + switch (BuiltinID) { + default: + return false; +#define GET_NEON_AARCH64_IMMEDIATE_CHECK +#include "clang/Basic/arm_neon.inc" +#undef GET_NEON_AARCH64_IMMEDIATE_CHECK + } + ; + + // We can't check the value of a dependent argument. + if (TheCall->getArg(i)->isTypeDependent() || + TheCall->getArg(i)->isValueDependent()) + return false; + + // Check that the immediate argument is actually a constant. + if (SemaBuiltinConstantArg(TheCall, i, Result)) + return true; + + // Range check against the upper/lower values for this isntruction. + unsigned Val = Result.getZExtValue(); + if (Val < l || Val > (u + l)) + return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) + << l << u + l << TheCall->getArg(i)->getSourceRange(); + + return false; +} + +bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall) { + assert((BuiltinID == ARM::BI__builtin_arm_ldrex || + BuiltinID == ARM::BI__builtin_arm_strex) && + "unexpected ARM builtin"); + bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex; + + DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts()); + + // Ensure that we have the proper number of arguments. + if (checkArgCount(*this, TheCall, IsLdrex ? 1 : 2)) + return true; + + // Inspect the pointer argument of the atomic builtin. This should always be + // a pointer type, whose element is an integral scalar or pointer type. + // Because it is a pointer type, we don't have to worry about any implicit + // casts here. + Expr *PointerArg = TheCall->getArg(IsLdrex ? 0 : 1); + ExprResult PointerArgRes = DefaultFunctionArrayLvalueConversion(PointerArg); + if (PointerArgRes.isInvalid()) + return true; + PointerArg = PointerArgRes.take(); + + const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>(); + if (!pointerType) { + Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer) + << PointerArg->getType() << PointerArg->getSourceRange(); + return true; + } + + // ldrex takes a "const volatile T*" and strex takes a "volatile T*". Our next + // task is to insert the appropriate casts into the AST. First work out just + // what the appropriate type is. + QualType ValType = pointerType->getPointeeType(); + QualType AddrType = ValType.getUnqualifiedType().withVolatile(); + if (IsLdrex) + AddrType.addConst(); + + // Issue a warning if the cast is dodgy. + CastKind CastNeeded = CK_NoOp; + if (!AddrType.isAtLeastAsQualifiedAs(ValType)) { + CastNeeded = CK_BitCast; + Diag(DRE->getLocStart(), diag::ext_typecheck_convert_discards_qualifiers) + << PointerArg->getType() + << Context.getPointerType(AddrType) + << AA_Passing << PointerArg->getSourceRange(); + } + + // Finally, do the cast and replace the argument with the corrected version. + AddrType = Context.getPointerType(AddrType); + PointerArgRes = ImpCastExprToType(PointerArg, AddrType, CastNeeded); + if (PointerArgRes.isInvalid()) + return true; + PointerArg = PointerArgRes.take(); + + TheCall->setArg(IsLdrex ? 0 : 1, PointerArg); + + // In general, we allow ints, floats and pointers to be loaded and stored. + if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && + !ValType->isBlockPointerType() && !ValType->isFloatingType()) { + Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer_intfltptr) + << PointerArg->getType() << PointerArg->getSourceRange(); + return true; + } + + // But ARM doesn't have instructions to deal with 128-bit versions. + if (Context.getTypeSize(ValType) > 64) { + Diag(DRE->getLocStart(), diag::err_atomic_exclusive_builtin_pointer_size) + << PointerArg->getType() << PointerArg->getSourceRange(); + return true; + } + + switch (ValType.getObjCLifetime()) { + case Qualifiers::OCL_None: + case Qualifiers::OCL_ExplicitNone: + // okay + break; + + case Qualifiers::OCL_Weak: + case Qualifiers::OCL_Strong: + case Qualifiers::OCL_Autoreleasing: + Diag(DRE->getLocStart(), diag::err_arc_atomic_ownership) + << ValType << PointerArg->getSourceRange(); + return true; + } + + + if (IsLdrex) { + TheCall->setType(ValType); + return false; + } + + // Initialize the argument to be stored. + ExprResult ValArg = TheCall->getArg(0); + InitializedEntity Entity = InitializedEntity::InitializeParameter( + Context, ValType, /*consume*/ false); + ValArg = PerformCopyInitialization(Entity, SourceLocation(), ValArg); + if (ValArg.isInvalid()) + return true; + TheCall->setArg(0, ValArg.get()); + + // __builtin_arm_strex always returns an int. It's marked as such in the .def, + // but the custom checker bypasses all default analysis. + TheCall->setType(Context.IntTy); + return false; +} + bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { llvm::APSInt Result; + if (BuiltinID == ARM::BI__builtin_arm_ldrex || + BuiltinID == ARM::BI__builtin_arm_strex) { + return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall); + } + uint64_t mask = 0; unsigned TV = 0; int PtrArgNum = -1; @@ -384,7 +606,7 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { Arg = ICE->getSubExpr(); ExprResult RHS = DefaultFunctionArrayLvalueConversion(Arg); QualType RHSTy = RHS.get()->getType(); - QualType EltTy = getNeonEltType(NeonTypeFlags(TV), Context); + QualType EltTy = getNeonEltType(NeonTypeFlags(TV), Context, false); if (HasConstPtr) EltTy = EltTy.withConst(); QualType LHSTy = Context.getPointerType(EltTy); @@ -406,6 +628,8 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case ARM::BI__builtin_arm_usat: i = 1; u = 31; break; case ARM::BI__builtin_arm_vcvtr_f: case ARM::BI__builtin_arm_vcvtr_d: i = 1; u = 1; break; + case ARM::BI__builtin_arm_dmb: + case ARM::BI__builtin_arm_dsb: l = 0; u = 15; break; #define GET_NEON_IMMEDIATE_CHECK #include "clang/Basic/arm_neon.inc" #undef GET_NEON_IMMEDIATE_CHECK @@ -494,36 +718,50 @@ void Sema::checkCall(NamedDecl *FDecl, SourceLocation Loc, SourceRange Range, VariadicCallType CallType) { + // FIXME: We should check as much as we can in the template definition. if (CurContext->isDependentContext()) return; // Printf and scanf checking. - bool HandledFormatString = false; - for (specific_attr_iterator<FormatAttr> - I = FDecl->specific_attr_begin<FormatAttr>(), - E = FDecl->specific_attr_end<FormatAttr>(); I != E ; ++I) - if (CheckFormatArguments(*I, Args, IsMemberFunction, CallType, Loc, Range)) - HandledFormatString = true; + llvm::SmallBitVector CheckedVarArgs; + if (FDecl) { + for (specific_attr_iterator<FormatAttr> + I = FDecl->specific_attr_begin<FormatAttr>(), + E = FDecl->specific_attr_end<FormatAttr>(); + I != E; ++I) { + // Only create vector if there are format attributes. + CheckedVarArgs.resize(Args.size()); + + CheckFormatArguments(*I, Args, IsMemberFunction, CallType, Loc, Range, + CheckedVarArgs); + } + } // Refuse POD arguments that weren't caught by the format string // checks above. - if (!HandledFormatString && CallType != VariadicDoesNotApply) + if (CallType != VariadicDoesNotApply) { for (unsigned ArgIdx = NumProtoArgs; ArgIdx < Args.size(); ++ArgIdx) { // Args[ArgIdx] can be null in malformed code. - if (const Expr *Arg = Args[ArgIdx]) - variadicArgumentPODCheck(Arg, CallType); + if (const Expr *Arg = Args[ArgIdx]) { + if (CheckedVarArgs.empty() || !CheckedVarArgs[ArgIdx]) + checkVariadicArgument(Arg, CallType); + } } + } - for (specific_attr_iterator<NonNullAttr> - I = FDecl->specific_attr_begin<NonNullAttr>(), - E = FDecl->specific_attr_end<NonNullAttr>(); I != E; ++I) - CheckNonNullArguments(*I, Args.data(), Loc); + if (FDecl) { + for (specific_attr_iterator<NonNullAttr> + I = FDecl->specific_attr_begin<NonNullAttr>(), + E = FDecl->specific_attr_end<NonNullAttr>(); I != E; ++I) + CheckNonNullArguments(*I, Args.data(), Loc); - // Type safety checking. - for (specific_attr_iterator<ArgumentWithTypeTagAttr> - i = FDecl->specific_attr_begin<ArgumentWithTypeTagAttr>(), - e = FDecl->specific_attr_end<ArgumentWithTypeTagAttr>(); i != e; ++i) { - CheckArgumentWithTypeTag(*i, Args.data()); + // Type safety checking. + for (specific_attr_iterator<ArgumentWithTypeTagAttr> + i = FDecl->specific_attr_begin<ArgumentWithTypeTagAttr>(), + e = FDecl->specific_attr_end<ArgumentWithTypeTagAttr>(); + i != e; ++i) { + CheckArgumentWithTypeTag(*i, Args.data()); + } } } @@ -597,18 +835,24 @@ bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac, return false; } -bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall, - const FunctionProtoType *Proto) { +bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, + const FunctionProtoType *Proto) { const VarDecl *V = dyn_cast<VarDecl>(NDecl); if (!V) return false; QualType Ty = V->getType(); - if (!Ty->isBlockPointerType()) + if (!Ty->isBlockPointerType() && !Ty->isFunctionPointerType()) return false; - VariadicCallType CallType = - Proto && Proto->isVariadic() ? VariadicBlock : VariadicDoesNotApply ; + VariadicCallType CallType; + if (!Proto || !Proto->isVariadic()) { + CallType = VariadicDoesNotApply; + } else if (Ty->isBlockPointerType()) { + CallType = VariadicBlock; + } else { // Ty->isFunctionPointerType() + CallType = VariadicFunction; + } unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0; checkCall(NDecl, @@ -621,6 +865,23 @@ bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall, return false; } +/// Checks function calls when a FunctionDecl or a NamedDecl is not available, +/// such as function pointers returned from functions. +bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) { + VariadicCallType CallType = getVariadicCallType(/*FDecl=*/0, Proto, + TheCall->getCallee()); + unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0; + + checkCall(/*FDecl=*/0, + llvm::makeArrayRef<const Expr *>(TheCall->getArgs(), + TheCall->getNumArgs()), + NumProtoArgs, /*IsMemberFunction=*/false, + TheCall->getRParenLoc(), + TheCall->getCallee()->getSourceRange(), CallType); + + return false; +} + ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, AtomicExpr::AtomicOp Op) { CallExpr *TheCall = cast<CallExpr>(TheCallResult.get()); @@ -786,7 +1047,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, return ExprError(); } - if (!IsC11 && !AtomTy.isTriviallyCopyableType(Context)) { + if (!IsC11 && !AtomTy.isTriviallyCopyableType(Context) && + !AtomTy->isScalarType()) { // For GNU atomics, require a trivially-copyable type. This is not part of // the GNU atomics specification, but we enforce it for sanity. Diag(DRE->getLocStart(), diag::err_atomic_op_needs_trivial_copy) @@ -908,10 +1170,18 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, SubExprs.push_back(TheCall->getArg(3)); // Weak break; } + + AtomicExpr *AE = new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(), + SubExprs, ResultType, Op, + TheCall->getRParenLoc()); + + if ((Op == AtomicExpr::AO__c11_atomic_load || + (Op == AtomicExpr::AO__c11_atomic_store)) && + Context.AtomicUsesUnsupportedLibcall(AE)) + Diag(AE->getLocStart(), diag::err_atomic_load_store_uses_lib) << + ((Op == AtomicExpr::AO__c11_atomic_load) ? 0 : 1); - return Owned(new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(), - SubExprs, ResultType, Op, - TheCall->getRParenLoc())); + return Owned(AE); } @@ -1355,6 +1625,11 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) { bool SecondArgIsLastNamedArgument = false; const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts(); + // These are valid if SecondArgIsLastNamedArgument is false after the next + // block. + QualType Type; + SourceLocation ParamLoc; + if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) { if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) { // FIXME: This isn't correct for methods (results in bogus warning). @@ -1367,12 +1642,22 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) { else LastArg = *(getCurMethodDecl()->param_end()-1); SecondArgIsLastNamedArgument = PV == LastArg; + + Type = PV->getType(); + ParamLoc = PV->getLocation(); } } if (!SecondArgIsLastNamedArgument) Diag(TheCall->getArg(1)->getLocStart(), diag::warn_second_parameter_of_va_start_not_last_named_argument); + else if (Type->isReferenceType()) { + Diag(Arg->getLocStart(), + diag::warn_va_start_of_reference_type_is_undefined); + Diag(ParamLoc, diag::note_parameter_type) << Type; + } + + TheCall->setType(Context.VoidTy); return false; } @@ -1464,8 +1749,8 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { if (TheCall->getNumArgs() < 2) return ExprError(Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << 2 << TheCall->getNumArgs() - << TheCall->getSourceRange()); + << 0 /*function call*/ << 2 << TheCall->getNumArgs() + << TheCall->getSourceRange()); // Determine which of the following types of shufflevector we're checking: // 1) unary, vector mask: (lhs, mask) @@ -1473,19 +1758,18 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { // 3) binary, scalar mask: (lhs, rhs, index, ..., index) QualType resType = TheCall->getArg(0)->getType(); unsigned numElements = 0; - + if (!TheCall->getArg(0)->isTypeDependent() && !TheCall->getArg(1)->isTypeDependent()) { QualType LHSType = TheCall->getArg(0)->getType(); QualType RHSType = TheCall->getArg(1)->getType(); - - if (!LHSType->isVectorType() || !RHSType->isVectorType()) { - Diag(TheCall->getLocStart(), diag::err_shufflevector_non_vector) - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd()); - return ExprError(); - } - + + if (!LHSType->isVectorType() || !RHSType->isVectorType()) + return ExprError(Diag(TheCall->getLocStart(), + diag::err_shufflevector_non_vector) + << SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd())); + numElements = LHSType->getAs<VectorType>()->getNumElements(); unsigned numResElements = TheCall->getNumArgs() - 2; @@ -1493,18 +1777,17 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { // with mask. If so, verify that RHS is an integer vector type with the // same number of elts as lhs. if (TheCall->getNumArgs() == 2) { - if (!RHSType->hasIntegerRepresentation() || + if (!RHSType->hasIntegerRepresentation() || RHSType->getAs<VectorType>()->getNumElements() != numElements) - Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector) - << SourceRange(TheCall->getArg(1)->getLocStart(), - TheCall->getArg(1)->getLocEnd()); - numResElements = numElements; - } - else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) { - Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector) - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd()); - return ExprError(); + return ExprError(Diag(TheCall->getLocStart(), + diag::err_shufflevector_incompatible_vector) + << SourceRange(TheCall->getArg(1)->getLocStart(), + TheCall->getArg(1)->getLocEnd())); + } else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) { + return ExprError(Diag(TheCall->getLocStart(), + diag::err_shufflevector_incompatible_vector) + << SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd())); } else if (numElements != numResElements) { QualType eltType = LHSType->getAs<VectorType>()->getElementType(); resType = Context.getVectorType(eltType, numResElements, @@ -1520,13 +1803,17 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { llvm::APSInt Result(32); if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) return ExprError(Diag(TheCall->getLocStart(), - diag::err_shufflevector_nonconstant_argument) - << TheCall->getArg(i)->getSourceRange()); + diag::err_shufflevector_nonconstant_argument) + << TheCall->getArg(i)->getSourceRange()); + + // Allow -1 which will be translated to undef in the IR. + if (Result.isSigned() && Result.isAllOnesValue()) + continue; if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2) return ExprError(Diag(TheCall->getLocStart(), - diag::err_shufflevector_argument_too_large) - << TheCall->getArg(i)->getSourceRange()); + diag::err_shufflevector_argument_too_large) + << TheCall->getArg(i)->getSourceRange()); } SmallVector<Expr*, 32> exprs; @@ -1541,6 +1828,37 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { TheCall->getRParenLoc())); } +/// SemaConvertVectorExpr - Handle __builtin_convertvector +ExprResult Sema::SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo, + SourceLocation BuiltinLoc, + SourceLocation RParenLoc) { + ExprValueKind VK = VK_RValue; + ExprObjectKind OK = OK_Ordinary; + QualType DstTy = TInfo->getType(); + QualType SrcTy = E->getType(); + + if (!SrcTy->isVectorType() && !SrcTy->isDependentType()) + return ExprError(Diag(BuiltinLoc, + diag::err_convertvector_non_vector) + << E->getSourceRange()); + if (!DstTy->isVectorType() && !DstTy->isDependentType()) + return ExprError(Diag(BuiltinLoc, + diag::err_convertvector_non_vector_type)); + + if (!SrcTy->isDependentType() && !DstTy->isDependentType()) { + unsigned SrcElts = SrcTy->getAs<VectorType>()->getNumElements(); + unsigned DstElts = DstTy->getAs<VectorType>()->getNumElements(); + if (SrcElts != DstElts) + return ExprError(Diag(BuiltinLoc, + diag::err_convertvector_incompatible_vector) + << E->getSourceRange()); + } + + return Owned(new (Context) ConvertVectorExpr(E, TInfo, DstTy, VK, OK, + BuiltinLoc, RParenLoc)); + +} + /// SemaBuiltinPrefetch - Handle __builtin_prefetch. // This is declared to take (const void*, ...) and can take two // optional constant int args. @@ -1642,28 +1960,36 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) { return false; } +namespace { +enum StringLiteralCheckType { + SLCT_NotALiteral, + SLCT_UncheckedLiteral, + SLCT_CheckedLiteral +}; +} + // Determine if an expression is a string literal or constant string. // If this function returns false on the arguments to a function expecting a // format string, we will usually need to emit a warning. // True string literals are then checked by CheckFormatString. -Sema::StringLiteralCheckType -Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args, - bool HasVAListArg, - unsigned format_idx, unsigned firstDataArg, - FormatStringType Type, VariadicCallType CallType, - bool inFunctionCall) { +static StringLiteralCheckType +checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, + bool HasVAListArg, unsigned format_idx, + unsigned firstDataArg, Sema::FormatStringType Type, + Sema::VariadicCallType CallType, bool InFunctionCall, + llvm::SmallBitVector &CheckedVarArgs) { tryAgain: if (E->isTypeDependent() || E->isValueDependent()) return SLCT_NotALiteral; E = E->IgnoreParenCasts(); - if (E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) + if (E->isNullPointerConstant(S.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 SLCT_CheckedLiteral; + return SLCT_UncheckedLiteral; switch (E->getStmtClass()) { case Stmt::BinaryConditionalOperatorClass: @@ -1673,15 +1999,15 @@ Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args, const AbstractConditionalOperator *C = cast<AbstractConditionalOperator>(E); StringLiteralCheckType Left = - checkFormatStringExpr(C->getTrueExpr(), Args, + checkFormatStringExpr(S, C->getTrueExpr(), Args, HasVAListArg, format_idx, firstDataArg, - Type, CallType, inFunctionCall); + Type, CallType, InFunctionCall, CheckedVarArgs); if (Left == SLCT_NotALiteral) return SLCT_NotALiteral; StringLiteralCheckType Right = - checkFormatStringExpr(C->getFalseExpr(), Args, + checkFormatStringExpr(S, C->getFalseExpr(), Args, HasVAListArg, format_idx, firstDataArg, - Type, CallType, inFunctionCall); + Type, CallType, InFunctionCall, CheckedVarArgs); return Left < Right ? Left : Right; } @@ -1712,15 +2038,15 @@ Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args, bool isConstant = false; QualType T = DR->getType(); - if (const ArrayType *AT = Context.getAsArrayType(T)) { - isConstant = AT->getElementType().isConstant(Context); + if (const ArrayType *AT = S.Context.getAsArrayType(T)) { + isConstant = AT->getElementType().isConstant(S.Context); } else if (const PointerType *PT = T->getAs<PointerType>()) { - isConstant = T.isConstant(Context) && - PT->getPointeeType().isConstant(Context); + isConstant = T.isConstant(S.Context) && + PT->getPointeeType().isConstant(S.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); + isConstant = T.isConstant(S.Context); } if (isConstant) { @@ -1730,10 +2056,10 @@ Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args, if (InitList->isStringLiteralInit()) Init = InitList->getInit(0)->IgnoreParenImpCasts(); } - return checkFormatStringExpr(Init, Args, + return checkFormatStringExpr(S, Init, Args, HasVAListArg, format_idx, firstDataArg, Type, CallType, - /*inFunctionCall*/false); + /*InFunctionCall*/false, CheckedVarArgs); } } @@ -1750,7 +2076,7 @@ Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args, // va_start(ap, fmt); // vprintf(fmt, ap); // Do NOT emit a warning about "fmt". // ... - // + // } if (HasVAListArg) { if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(VD)) { if (const NamedDecl *ND = dyn_cast<NamedDecl>(PV->getDeclContext())) { @@ -1766,7 +2092,7 @@ Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args, // 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)) + Type == S.GetFormatStringType(PVFormat)) return SLCT_UncheckedLiteral; } } @@ -1788,24 +2114,46 @@ Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args, --ArgIndex; const Expr *Arg = CE->getArg(ArgIndex - 1); - return checkFormatStringExpr(Arg, Args, + return checkFormatStringExpr(S, Arg, Args, HasVAListArg, format_idx, firstDataArg, - Type, CallType, inFunctionCall); + Type, CallType, InFunctionCall, + CheckedVarArgs); } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { unsigned BuiltinID = FD->getBuiltinID(); if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString || BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString) { const Expr *Arg = CE->getArg(0); - return checkFormatStringExpr(Arg, Args, + return checkFormatStringExpr(S, Arg, Args, HasVAListArg, format_idx, firstDataArg, Type, CallType, - inFunctionCall); + InFunctionCall, CheckedVarArgs); } } } return SLCT_NotALiteral; } + + case Stmt::ObjCMessageExprClass: { + const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(E); + if (const ObjCMethodDecl *MDecl = ME->getMethodDecl()) { + if (const NamedDecl *ND = dyn_cast<NamedDecl>(MDecl)) { + if (const FormatArgAttr *FA = ND->getAttr<FormatArgAttr>()) { + unsigned ArgIndex = FA->getFormatIdx(); + if (ArgIndex <= ME->getNumArgs()) { + const Expr *Arg = ME->getArg(ArgIndex-1); + return checkFormatStringExpr(S, Arg, Args, + HasVAListArg, format_idx, + firstDataArg, Type, CallType, + InFunctionCall, CheckedVarArgs); + } + } + } + } + + return SLCT_NotALiteral; + } + case Stmt::ObjCStringLiteralClass: case Stmt::StringLiteralClass: { const StringLiteral *StrE = NULL; @@ -1816,8 +2164,8 @@ Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args, StrE = cast<StringLiteral>(E); if (StrE) { - CheckFormatString(StrE, E, Args, HasVAListArg, format_idx, - firstDataArg, Type, inFunctionCall, CallType); + S.CheckFormatString(StrE, E, Args, HasVAListArg, format_idx, firstDataArg, + Type, InFunctionCall, CallType, CheckedVarArgs); return SLCT_CheckedLiteral; } @@ -1856,7 +2204,7 @@ Sema::CheckNonNullArguments(const NonNullAttr *NonNull, } Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) { - return llvm::StringSwitch<FormatStringType>(Format->getType()) + return llvm::StringSwitch<FormatStringType>(Format->getType()->getName()) .Case("scanf", FST_Scanf) .Cases("printf", "printf0", FST_Printf) .Cases("NSString", "CFString", FST_NSString) @@ -1873,12 +2221,13 @@ bool Sema::CheckFormatArguments(const FormatAttr *Format, ArrayRef<const Expr *> Args, bool IsCXXMember, VariadicCallType CallType, - SourceLocation Loc, SourceRange Range) { + SourceLocation Loc, SourceRange Range, + llvm::SmallBitVector &CheckedVarArgs) { FormatStringInfo FSI; if (getFormatStringInfo(Format, IsCXXMember, &FSI)) return CheckFormatArguments(Args, FSI.HasVAListArg, FSI.FormatIdx, FSI.FirstDataArg, GetFormatStringType(Format), - CallType, Loc, Range); + CallType, Loc, Range, CheckedVarArgs); return false; } @@ -1886,7 +2235,8 @@ bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, FormatStringType Type, VariadicCallType CallType, - SourceLocation Loc, SourceRange Range) { + SourceLocation Loc, SourceRange Range, + llvm::SmallBitVector &CheckedVarArgs) { // CHECK: printf/scanf-like function is called with no format string. if (format_idx >= Args.size()) { Diag(Loc, diag::warn_missing_format_string) << Range; @@ -1908,8 +2258,9 @@ bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args, // 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. StringLiteralCheckType CT = - checkFormatStringExpr(OrigFormatExpr, Args, HasVAListArg, - format_idx, firstDataArg, Type, CallType); + checkFormatStringExpr(*this, OrigFormatExpr, Args, HasVAListArg, + format_idx, firstDataArg, Type, CallType, + /*IsFunctionCall*/true, CheckedVarArgs); if (CT != SLCT_NotALiteral) // Literal format string found, check done! return CT == SLCT_CheckedLiteral; @@ -1929,7 +2280,7 @@ bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args, // If there are no arguments specified, warn with -Wformat-security, otherwise // warn only with -Wformat-nonliteral. - if (Args.size() == format_idx+1) + if (Args.size() == firstDataArg) Diag(Args[format_idx]->getLocStart(), diag::warn_format_nonliteral_noargs) << OrigFormatExpr->getSourceRange(); @@ -1952,27 +2303,30 @@ protected: const bool HasVAListArg; ArrayRef<const Expr *> Args; unsigned FormatIdx; - llvm::BitVector CoveredArgs; + llvm::SmallBitVector CoveredArgs; bool usesPositionalArgs; bool atFirstArg; bool inFunctionCall; Sema::VariadicCallType CallType; + llvm::SmallBitVector &CheckedVarArgs; public: CheckFormatHandler(Sema &s, const StringLiteral *fexpr, const Expr *origFormatExpr, unsigned firstDataArg, unsigned numDataArgs, const char *beg, bool hasVAListArg, ArrayRef<const Expr *> Args, unsigned formatIdx, bool inFunctionCall, - Sema::VariadicCallType callType) + Sema::VariadicCallType callType, + llvm::SmallBitVector &CheckedVarArgs) : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), FirstDataArg(firstDataArg), NumDataArgs(numDataArgs), Beg(beg), HasVAListArg(hasVAListArg), Args(Args), FormatIdx(formatIdx), usesPositionalArgs(false), atFirstArg(true), - inFunctionCall(inFunctionCall), CallType(callType) { - CoveredArgs.resize(numDataArgs); - CoveredArgs.reset(); - } + inFunctionCall(inFunctionCall), CallType(callType), + CheckedVarArgs(CheckedVarArgs) { + CoveredArgs.resize(numDataArgs); + CoveredArgs.reset(); + } void DoneProcessing(); @@ -2361,10 +2715,12 @@ public: const char *beg, bool hasVAListArg, ArrayRef<const Expr *> Args, unsigned formatIdx, bool inFunctionCall, - Sema::VariadicCallType CallType) - : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, - numDataArgs, beg, hasVAListArg, Args, - formatIdx, inFunctionCall, CallType), ObjCContext(isObjC) + Sema::VariadicCallType CallType, + llvm::SmallBitVector &CheckedVarArgs) + : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, + numDataArgs, beg, hasVAListArg, Args, + formatIdx, inFunctionCall, CallType, CheckedVarArgs), + ObjCContext(isObjC) {} @@ -2824,7 +3180,15 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // 'unichar' is defined as a typedef of unsigned short, but we should // prefer using the typedef if it is visible. IntendedTy = S.Context.UnsignedShortTy; - + + // While we are here, check if the value is an IntegerLiteral that happens + // to be within the valid range. + if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(E)) { + const llvm::APInt &V = IL->getValue(); + if (V.getActiveBits() <= S.Context.getTypeSize(IntendedTy)) + return true; + } + LookupResult Result(S, &S.Context.Idents.get("unichar"), E->getLocStart(), Sema::LookupOrdinaryName); if (S.LookupName(Result, S.getCurScope())) { @@ -2952,15 +3316,20 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // Since the warning for passing non-POD types to variadic functions // was deferred until now, we emit a warning for non-POD // arguments here. - if (S.isValidVarArgType(ExprTy) == Sema::VAK_Invalid) { - unsigned DiagKind; - if (ExprTy->isObjCObjectType()) - DiagKind = diag::err_cannot_pass_objc_interface_to_vararg_format; - else - DiagKind = diag::warn_non_pod_vararg_with_format_string; + switch (S.isValidVarArgType(ExprTy)) { + case Sema::VAK_Valid: + case Sema::VAK_ValidInCXX11: + EmitFormatDiagnostic( + S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) + << AT.getRepresentativeTypeName(S.Context) << ExprTy + << CSR + << E->getSourceRange(), + E->getLocStart(), /*IsStringLocation*/false, CSR); + break; + case Sema::VAK_Undefined: EmitFormatDiagnostic( - S.PDiag(DiagKind) + S.PDiag(diag::warn_non_pod_vararg_with_format_string) << S.getLangOpts().CPlusPlus11 << ExprTy << CallType @@ -2968,15 +3337,33 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, << CSR << E->getSourceRange(), E->getLocStart(), /*IsStringLocation*/false, CSR); - checkForCStrMembers(AT, E, CSR); - } else - EmitFormatDiagnostic( - S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << ExprTy - << CSR - << E->getSourceRange(), - E->getLocStart(), /*IsStringLocation*/false, CSR); + break; + + case Sema::VAK_Invalid: + if (ExprTy->isObjCObjectType()) + EmitFormatDiagnostic( + S.PDiag(diag::err_cannot_pass_objc_interface_to_vararg_format) + << S.getLangOpts().CPlusPlus11 + << ExprTy + << CallType + << AT.getRepresentativeTypeName(S.Context) + << CSR + << E->getSourceRange(), + E->getLocStart(), /*IsStringLocation*/false, CSR); + else + // FIXME: If this is an initializer list, suggest removing the braces + // or inserting a cast to the target type. + S.Diag(E->getLocStart(), diag::err_cannot_pass_to_vararg_format) + << isa<InitListExpr>(E) << ExprTy << CallType + << AT.getRepresentativeTypeName(S.Context) + << E->getSourceRange(); + break; + } + + assert(FirstDataArg + FS.getArgIndex() < CheckedVarArgs.size() && + "format string specifier index out of range"); + CheckedVarArgs[FirstDataArg + FS.getArgIndex()] = true; } return true; @@ -2992,10 +3379,12 @@ public: unsigned numDataArgs, const char *beg, bool hasVAListArg, ArrayRef<const Expr *> Args, unsigned formatIdx, bool inFunctionCall, - Sema::VariadicCallType CallType) - : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, - numDataArgs, beg, hasVAListArg, - Args, formatIdx, inFunctionCall, CallType) + Sema::VariadicCallType CallType, + llvm::SmallBitVector &CheckedVarArgs) + : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, + numDataArgs, beg, hasVAListArg, + Args, formatIdx, inFunctionCall, CallType, + CheckedVarArgs) {} bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS, @@ -3150,7 +3539,8 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, ArrayRef<const Expr *> Args, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, FormatStringType Type, - bool inFunctionCall, VariadicCallType CallType) { + bool inFunctionCall, VariadicCallType CallType, + llvm::SmallBitVector &CheckedVarArgs) { // CHECK: is the format string a wide literal? if (!FExpr->isAscii() && !FExpr->isUTF8()) { @@ -3180,7 +3570,7 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs, (Type == FST_NSString), Str, HasVAListArg, Args, format_idx, - inFunctionCall, CallType); + inFunctionCall, CallType, CheckedVarArgs); if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen, getLangOpts(), @@ -3189,7 +3579,7 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, } else if (Type == FST_Scanf) { CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs, Str, HasVAListArg, Args, format_idx, - inFunctionCall, CallType); + inFunctionCall, CallType, CheckedVarArgs); if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen, getLangOpts(), @@ -3688,7 +4078,7 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars, Decl *ParentDecl) { if (E->isTypeDependent()) - return NULL; + return NULL; // We should only be called for evaluating pointer expressions. assert((E->getType()->isAnyPointerType() || @@ -4130,6 +4520,13 @@ static IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty, return IntRange(MaxWidth, Ty->isUnsignedIntegerOrEnumerationType()); } +static QualType GetExprType(Expr *E) { + QualType Ty = E->getType(); + if (const AtomicType *AtomicRHS = Ty->getAs<AtomicType>()) + Ty = AtomicRHS->getValueType(); + return Ty; +} + /// Pseudo-evaluate the given integer expression, estimating the /// range of values it might take. /// @@ -4140,7 +4537,7 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { // Try a full evaluation first. Expr::EvalResult result; if (E->EvaluateAsRValue(result, C)) - return GetValueRange(C, result.Val, E->getType(), MaxWidth); + return GetValueRange(C, result.Val, GetExprType(E), 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 @@ -4149,7 +4546,7 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { if (CE->getCastKind() == CK_NoOp || CE->getCastKind() == CK_LValueToRValue) return GetExprRange(C, CE->getSubExpr(), MaxWidth); - IntRange OutputTypeRange = IntRange::forValueOfType(C, CE->getType()); + IntRange OutputTypeRange = IntRange::forValueOfType(C, GetExprType(CE)); bool isIntegerCast = (CE->getCastKind() == CK_IntegralCast); @@ -4209,7 +4606,7 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { case BO_XorAssign: case BO_OrAssign: // TODO: bitfields? - return IntRange::forValueOfType(C, E->getType()); + return IntRange::forValueOfType(C, GetExprType(E)); // Simple assignments just pass through the RHS, which will have // been coerced to the LHS type. @@ -4220,7 +4617,7 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { // Operations with opaque sources are black-listed. case BO_PtrMemD: case BO_PtrMemI: - return IntRange::forValueOfType(C, E->getType()); + return IntRange::forValueOfType(C, GetExprType(E)); // Bitwise-and uses the *infinum* of the two source ranges. case BO_And: @@ -4235,14 +4632,14 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { if (IntegerLiteral *I = dyn_cast<IntegerLiteral>(BO->getLHS()->IgnoreParenCasts())) { if (I->getValue() == 1) { - IntRange R = IntRange::forValueOfType(C, E->getType()); + IntRange R = IntRange::forValueOfType(C, GetExprType(E)); return IntRange(R.Width, /*NonNegative*/ true); } } // fallthrough case BO_ShlAssign: - return IntRange::forValueOfType(C, E->getType()); + return IntRange::forValueOfType(C, GetExprType(E)); // Right shift by a constant can narrow its left argument. case BO_Shr: @@ -4271,14 +4668,14 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { // Black-list pointer subtractions. case BO_Sub: if (BO->getLHS()->getType()->isPointerType()) - return IntRange::forValueOfType(C, E->getType()); + return IntRange::forValueOfType(C, GetExprType(E)); break; // The width of a division result is mostly determined by the size // of the LHS. case BO_Div: { // Don't 'pre-truncate' the operands. - unsigned opWidth = C.getIntWidth(E->getType()); + unsigned opWidth = C.getIntWidth(GetExprType(E)); IntRange L = GetExprRange(C, BO->getLHS(), opWidth); // If the divisor is constant, use that. @@ -4301,7 +4698,7 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { // either side. case BO_Rem: { // Don't 'pre-truncate' the operands. - unsigned opWidth = C.getIntWidth(E->getType()); + unsigned opWidth = C.getIntWidth(GetExprType(E)); IntRange L = GetExprRange(C, BO->getLHS(), opWidth); IntRange R = GetExprRange(C, BO->getRHS(), opWidth); @@ -4334,26 +4731,25 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { // Operations with opaque sources are black-listed. case UO_Deref: case UO_AddrOf: // should be impossible - return IntRange::forValueOfType(C, E->getType()); + return IntRange::forValueOfType(C, GetExprType(E)); default: return GetExprRange(C, UO->getSubExpr(), MaxWidth); } } - - if (dyn_cast<OffsetOfExpr>(E)) { - IntRange::forValueOfType(C, E->getType()); - } + + if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) + return GetExprRange(C, OVE->getSourceExpr(), MaxWidth); if (FieldDecl *BitField = E->getSourceBitField()) return IntRange(BitField->getBitWidthValue(C), BitField->getType()->isUnsignedIntegerOrEnumerationType()); - return IntRange::forValueOfType(C, E->getType()); + return IntRange::forValueOfType(C, GetExprType(E)); } static IntRange GetExprRange(ASTContext &C, Expr *E) { - return GetExprRange(C, E, C.getIntWidth(E->getType())); + return GetExprRange(C, E, C.getIntWidth(GetExprType(E))); } /// Checks whether the given value, which currently has the given @@ -4424,6 +4820,10 @@ static bool HasEnumType(Expr *E) { } static void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) { + // Disable warning in template instantiations. + if (!S.ActiveTemplateInstantiations.empty()) + return; + BinaryOperatorKind op = E->getOpcode(); if (E->isValueDependent()) return; @@ -4451,6 +4851,10 @@ static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant, Expr *Other, llvm::APSInt Value, bool RhsConstant) { + // Disable warning in template instantiations. + if (!S.ActiveTemplateInstantiations.empty()) + return; + // 0 values are handled later by CheckTrivialUnsignedComparison(). if (Value == 0) return; @@ -4770,8 +5174,16 @@ void DiagnoseFloatingLiteralImpCast(Sema &S, FloatingLiteral *FL, QualType T, == llvm::APFloat::opOK && isExact) return; + // FIXME: Force the precision of the source value down so we don't print + // digits which are usually useless (we don't really care here if we + // truncate a digit by accident in edge cases). Ideally, APFloat::toString + // would automatically print the shortest representation, but it's a bit + // tricky to implement. SmallString<16> PrettySourceValue; - Value.toString(PrettySourceValue); + unsigned precision = llvm::APFloat::semanticsPrecision(Value.getSemantics()); + precision = (precision * 59 + 195) / 196; + Value.toString(PrettySourceValue, precision); + SmallString<16> PrettyTargetValue; if (T->isSpecificBuiltinType(BuiltinType::Bool)) PrettyTargetValue = IntegerValue == 0 ? "false" : "true"; @@ -4877,7 +5289,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, << FixItHint::CreateInsertion(E->getExprLoc(), "&"); QualType ReturnType; UnresolvedSet<4> NonTemplateOverloads; - S.isExprCallable(*E, ReturnType, NonTemplateOverloads); + S.tryExprAsCall(*E, ReturnType, NonTemplateOverloads); if (!ReturnType.isNull() && ReturnType->isSpecificBuiltinType(BuiltinType::Bool)) S.Diag(E->getExprLoc(), diag::note_function_to_bool_call) @@ -5000,7 +5412,8 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (!Loc.isMacroID() || CC.isMacroID()) S.Diag(Loc, diag::warn_impcast_null_pointer_to_integer) << T << clang::SourceRange(CC) - << FixItHint::CreateReplacement(Loc, S.getFixItZeroLiteralForType(T)); + << FixItHint::CreateReplacement(Loc, + S.getFixItZeroLiteralForType(T, Loc)); } if (!Source->isIntegerType() || !Target->isIntegerType()) @@ -5167,7 +5580,15 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { CheckImplicitConversion(S, E, T, CC); // Now continue drilling into this expression. - + + if (PseudoObjectExpr * POE = dyn_cast<PseudoObjectExpr>(E)) { + if (POE->getResultExpr()) + E = POE->getResultExpr(); + } + + if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) + return AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC); + // Skip past explicit casts. if (isa<ExplicitCastExpr>(E)) { E = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreParenImpCasts(); @@ -5240,16 +5661,16 @@ void Sema::CheckImplicitConversions(Expr *E, SourceLocation CC) { /// Diagnose when expression is an integer constant expression and its evaluation /// results in integer overflow void Sema::CheckForIntOverflow (Expr *E) { - if (isa<BinaryOperator>(E->IgnoreParens())) { - llvm::SmallVector<PartialDiagnosticAt, 4> Diags; - E->EvaluateForOverflow(Context, &Diags); - } + if (isa<BinaryOperator>(E->IgnoreParens())) + E->EvaluateForOverflow(Context); } namespace { /// \brief Visitor for expressions which looks for unsequenced operations on the /// same object. class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { + typedef EvaluatedExprVisitor<SequenceChecker> Base; + /// \brief A tree of sequenced regions within an expression. Two regions are /// unsequenced if one is an ancestor or a descendent of the other. When we /// finish processing an expression with sequencing, such as a comma @@ -5261,7 +5682,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { unsigned Parent : 31; bool Merged : 1; }; - llvm::SmallVector<Value, 8> Values; + SmallVector<Value, 8> Values; public: /// \brief A region within an expression which may be sequenced with respect @@ -5323,7 +5744,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { /// A read of an object. Multiple unsequenced reads are OK. UK_Use, /// A modification of an object which is sequenced before the value - /// computation of the expression, such as ++n. + /// computation of the expression, such as ++n in C++. UK_ModAsValue, /// A modification of an object which is not sequenced before the value /// computation of the expression, such as n++. @@ -5355,10 +5776,10 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { SequenceTree::Seq Region; /// Filled in with declarations which were modified as a side-effect /// (that is, post-increment operations). - llvm::SmallVectorImpl<std::pair<Object, Usage> > *ModAsSideEffect; + SmallVectorImpl<std::pair<Object, Usage> > *ModAsSideEffect; /// Expressions to check later. We defer checking these to reduce /// stack usage. - llvm::SmallVectorImpl<Expr*> &WorkList; + SmallVectorImpl<Expr *> &WorkList; /// RAII object wrapping the visitation of a sequenced subexpression of an /// expression. At the end of this process, the side-effects of the evaluation @@ -5381,10 +5802,39 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { } SequenceChecker &Self; - llvm::SmallVector<std::pair<Object, Usage>, 4> ModAsSideEffect; - llvm::SmallVectorImpl<std::pair<Object, Usage> > *OldModAsSideEffect; + SmallVector<std::pair<Object, Usage>, 4> ModAsSideEffect; + SmallVectorImpl<std::pair<Object, Usage> > *OldModAsSideEffect; }; + /// RAII object wrapping the visitation of a subexpression which we might + /// choose to evaluate as a constant. If any subexpression is evaluated and + /// found to be non-constant, this allows us to suppress the evaluation of + /// the outer expression. + class EvaluationTracker { + public: + EvaluationTracker(SequenceChecker &Self) + : Self(Self), Prev(Self.EvalTracker), EvalOK(true) { + Self.EvalTracker = this; + } + ~EvaluationTracker() { + Self.EvalTracker = Prev; + if (Prev) + Prev->EvalOK &= EvalOK; + } + + bool evaluate(const Expr *E, bool &Result) { + if (!EvalOK || E->isValueDependent()) + return false; + EvalOK = E->EvaluateAsBooleanCondition(Result, Self.SemaRef.Context); + return EvalOK; + } + + private: + SequenceChecker &Self; + EvaluationTracker *Prev; + bool EvalOK; + } *EvalTracker; + /// \brief Find the object which is produced by the specified expression, /// if any. Object getObject(Expr *E, bool Mod) const { @@ -5463,10 +5913,9 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { } public: - SequenceChecker(Sema &S, Expr *E, - llvm::SmallVectorImpl<Expr*> &WorkList) - : EvaluatedExprVisitor<SequenceChecker>(S.Context), SemaRef(S), - Region(Tree.root()), ModAsSideEffect(0), WorkList(WorkList) { + SequenceChecker(Sema &S, Expr *E, SmallVectorImpl<Expr *> &WorkList) + : Base(S.Context), SemaRef(S), Region(Tree.root()), ModAsSideEffect(0), + WorkList(WorkList), EvalTracker(0) { Visit(E); } @@ -5476,7 +5925,7 @@ public: void VisitExpr(Expr *E) { // By default, just recurse to evaluated subexpressions. - EvaluatedExprVisitor<SequenceChecker>::VisitStmt(E); + Base::VisitStmt(E); } void VisitCastExpr(CastExpr *E) { @@ -5543,7 +5992,12 @@ public: Visit(BO->getRHS()); - notePostMod(O, BO, UK_ModAsValue); + // C++11 [expr.ass]p1: + // the assignment is sequenced [...] before the value computation of the + // assignment expression. + // C11 6.5.16/3 has no such rule. + notePostMod(O, BO, SemaRef.getLangOpts().CPlusPlus ? UK_ModAsValue + : UK_ModAsSideEffect); } void VisitCompoundAssignOperator(CompoundAssignOperator *CAO) { VisitBinAssign(CAO); @@ -5558,7 +6012,10 @@ public: notePreMod(O, UO); Visit(UO->getSubExpr()); - notePostMod(O, UO, UK_ModAsValue); + // C++11 [expr.pre.incr]p1: + // the expression ++x is equivalent to x+=1 + notePostMod(O, UO, SemaRef.getLangOpts().CPlusPlus ? UK_ModAsValue + : UK_ModAsSideEffect); } void VisitUnaryPostInc(UnaryOperator *UO) { VisitUnaryPostIncDec(UO); } @@ -5579,14 +6036,14 @@ public: // value computation of the RHS, and hence before the value computation // of the '&&' itself, unless the LHS evaluates to zero. We treat them // as if they were unconditionally sequenced. + EvaluationTracker Eval(*this); { SequencedSubexpression Sequenced(*this); Visit(BO->getLHS()); } bool Result; - if (!BO->getLHS()->isValueDependent() && - BO->getLHS()->EvaluateAsBooleanCondition(Result, SemaRef.Context)) { + if (Eval.evaluate(BO->getLHS(), Result)) { if (!Result) Visit(BO->getRHS()); } else { @@ -5600,14 +6057,14 @@ public: } } void VisitBinLAnd(BinaryOperator *BO) { + EvaluationTracker Eval(*this); { SequencedSubexpression Sequenced(*this); Visit(BO->getLHS()); } bool Result; - if (!BO->getLHS()->isValueDependent() && - BO->getLHS()->EvaluateAsBooleanCondition(Result, SemaRef.Context)) { + if (Eval.evaluate(BO->getLHS(), Result)) { if (Result) Visit(BO->getRHS()); } else { @@ -5618,12 +6075,14 @@ public: // Only visit the condition, unless we can be sure which subexpression will // be chosen. void VisitAbstractConditionalOperator(AbstractConditionalOperator *CO) { - SequencedSubexpression Sequenced(*this); - Visit(CO->getCond()); + EvaluationTracker Eval(*this); + { + SequencedSubexpression Sequenced(*this); + Visit(CO->getCond()); + } bool Result; - if (!CO->getCond()->isValueDependent() && - CO->getCond()->EvaluateAsBooleanCondition(Result, SemaRef.Context)) + if (Eval.evaluate(CO->getCond(), Result)) Visit(Result ? CO->getTrueExpr() : CO->getFalseExpr()); else { WorkList.push_back(CO->getTrueExpr()); @@ -5631,12 +6090,28 @@ public: } } + void VisitCallExpr(CallExpr *CE) { + // C++11 [intro.execution]p15: + // When calling a function [...], every value computation and side effect + // associated with any argument expression, or with the postfix expression + // designating the called function, is sequenced before execution of every + // expression or statement in the body of the function [and thus before + // the value computation of its result]. + SequencedSubexpression Sequenced(*this); + Base::VisitCallExpr(CE); + + // FIXME: CXXNewExpr and CXXDeleteExpr implicitly call functions. + } + void VisitCXXConstructExpr(CXXConstructExpr *CCE) { + // This is a call, so all subexpressions are sequenced before the result. + SequencedSubexpression Sequenced(*this); + if (!CCE->isListInitialization()) return VisitExpr(CCE); // In C++11, list initializations are sequenced. - llvm::SmallVector<SequenceTree::Seq, 32> Elts; + SmallVector<SequenceTree::Seq, 32> Elts; SequenceTree::Seq Parent = Region; for (CXXConstructExpr::arg_iterator I = CCE->arg_begin(), E = CCE->arg_end(); @@ -5657,7 +6132,7 @@ public: return VisitExpr(ILE); // In C++11, list initializations are sequenced. - llvm::SmallVector<SequenceTree::Seq, 32> Elts; + SmallVector<SequenceTree::Seq, 32> Elts; SequenceTree::Seq Parent = Region; for (unsigned I = 0; I < ILE->getNumInits(); ++I) { Expr *E = ILE->getInit(I); @@ -5676,11 +6151,10 @@ public: } void Sema::CheckUnsequencedOperations(Expr *E) { - llvm::SmallVector<Expr*, 8> WorkList; + SmallVector<Expr *, 8> WorkList; WorkList.push_back(E); while (!WorkList.empty()) { - Expr *Item = WorkList.back(); - WorkList.pop_back(); + Expr *Item = WorkList.pop_back_val(); SequenceChecker(*this, Item, WorkList); } } @@ -5704,7 +6178,8 @@ void Sema::CheckBitFieldInitialization(SourceLocation InitLoc, /// takes care of any checks that cannot be performed on the /// declaration itself, e.g., that the types of each of the function /// parameters are complete. -bool Sema::CheckParmsForFunctionDef(ParmVarDecl **P, ParmVarDecl **PEnd, +bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P, + ParmVarDecl *const *PEnd, bool CheckParameterNames) { bool HasInvalidParm = false; for (; P != PEnd; ++P) { @@ -5745,6 +6220,15 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl **P, ParmVarDecl **PEnd, } PType= AT->getElementType(); } + + // MSVC destroys objects passed by value in the callee. Therefore a + // function definition which takes such a parameter must be able to call the + // object's destructor. + if (getLangOpts().CPlusPlus && + Context.getTargetInfo().getCXXABI().isArgumentDestroyedByCallee()) { + if (const RecordType *RT = Param->getType()->getAs<RecordType>()) + FinalizeVarWithDestructor(Param, RT); + } } return HasInvalidParm; @@ -5926,7 +6410,7 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, if (SourceMgr.isInSystemHeader(RBracketLoc)) { SourceLocation IndexLoc = SourceMgr.getSpellingLoc( IndexExpr->getLocStart()); - if (SourceMgr.isFromSameFile(RBracketLoc, IndexLoc)) + if (SourceMgr.isWrittenInSameFile(RBracketLoc, IndexLoc)) return; } } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp index fd2ce1749fe8..7a1b36b2d7ee 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp @@ -464,9 +464,8 @@ getRequiredQualification(ASTContext &Context, NestedNameSpecifier *Result = 0; while (!TargetParents.empty()) { - const DeclContext *Parent = TargetParents.back(); - TargetParents.pop_back(); - + const DeclContext *Parent = TargetParents.pop_back_val(); + if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) { if (!Namespace->getIdentifier()) continue; @@ -716,8 +715,8 @@ unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) { return CCP_Unlikely; // Context-based decisions. - const DeclContext *DC = ND->getDeclContext()->getRedeclContext(); - if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC)) { + const DeclContext *LexicalDC = ND->getLexicalDeclContext(); + if (LexicalDC->isFunctionOrMethod()) { // _cmd is relatively rare if (const ImplicitParamDecl *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND)) @@ -727,6 +726,8 @@ unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) { return CCP_LocalDeclaration; } + + const DeclContext *DC = ND->getDeclContext()->getRedeclContext(); if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) return CCP_MemberDeclaration; @@ -877,8 +878,8 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { for (; I != IEnd; ++I) { // A tag declaration does not hide a non-tag declaration. if (I->first->hasTagIdentifierNamespace() && - (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | - Decl::IDNS_ObjCProtocol))) + (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | + Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol))) continue; // Protocols are in distinct namespaces from everything else. @@ -1039,7 +1040,9 @@ void ResultBuilder::ExitScope() { bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const { ND = cast<NamedDecl>(ND->getUnderlyingDecl()); - unsigned IDNS = Decl::IDNS_Ordinary; + // If name lookup finds a local extern declaration, then we are in a + // context where it behaves like an ordinary name. + unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; if (SemaRef.getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; else if (SemaRef.getLangOpts().ObjC1) { @@ -1057,7 +1060,7 @@ bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const { if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) return false; - unsigned IDNS = Decl::IDNS_Ordinary; + unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; if (SemaRef.getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; else if (SemaRef.getLangOpts().ObjC1) { @@ -1084,7 +1087,7 @@ bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const { bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const { ND = cast<NamedDecl>(ND->getUnderlyingDecl()); - unsigned IDNS = Decl::IDNS_Ordinary; + unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; if (SemaRef.getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace; @@ -3183,12 +3186,12 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, Builder.getAllocator().CopyString(Modules[I]->Name)); Results.AddResult(Result(Builder.TakeString(), CCP_Declaration, - CXCursor_NotImplemented, + CXCursor_ModuleImportDecl, Modules[I]->isAvailable() ? CXAvailability_Available : CXAvailability_NotAvailable)); } - } else { + } else if (getLangOpts().Modules) { // Load the named module. Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible, @@ -3203,7 +3206,7 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, Builder.getAllocator().CopyString((*Sub)->Name)); Results.AddResult(Result(Builder.TakeString(), CCP_Declaration, - CXCursor_NotImplemented, + CXCursor_ModuleImportDecl, (*Sub)->isAvailable() ? CXAvailability_Available : CXAvailability_NotAvailable)); @@ -3303,8 +3306,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, ParsedType Receiver, - IdentifierInfo **SelIdents, - unsigned NumSelIdents, + ArrayRef<IdentifierInfo *> SelIdents, bool AtArgumentExpression, bool IsSuper, ResultBuilder &Results); @@ -3360,7 +3362,7 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, Scope::AtCatchScope)) == 0) { ParsedType T = DS.getRepAsType(); if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType()) - AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results); + AddClassMessageCompletions(*this, S, T, None, false, false, Results); } // Note that we intentionally suppress macro results here, since we do not @@ -3436,7 +3438,7 @@ void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) { if (E.isInvalid()) CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction); else if (getLangOpts().ObjC1) - CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false); + CodeCompleteObjCInstanceMessage(S, E.take(), None, false); } /// \brief The set of properties that have already been added, referenced by @@ -3611,7 +3613,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, bool IsDependent = BaseType->isDependentType(); if (!IsDependent) { for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent()) - if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) { + if (DeclContext *Ctx = DepScope->getEntity()) { IsDependent = Ctx->isDependentContext(); break; } @@ -3847,7 +3849,7 @@ namespace { }; } -static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) { +static bool anyNullArguments(ArrayRef<Expr *> Args) { if (Args.size() && !Args.data()) return true; @@ -3858,8 +3860,7 @@ static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) { return false; } -void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, - llvm::ArrayRef<Expr *> Args) { +void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) { if (!CodeCompleter) return; @@ -4150,7 +4151,7 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { if (!CodeCompleter) return; - DeclContext *Ctx = (DeclContext *)S->getEntity(); + DeclContext *Ctx = S->getEntity(); if (!S->getParent()) Ctx = Context.getTranslationUnitDecl(); @@ -4242,9 +4243,9 @@ void Sema::CodeCompleteOperatorName(Scope *S) { Results.data(),Results.size()); } -void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, - CXXCtorInitializer** Initializers, - unsigned NumInitializers) { +void Sema::CodeCompleteConstructorInitializer( + Decl *ConstructorD, + ArrayRef <CXXCtorInitializer *> Initializers) { PrintingPolicy Policy = getCompletionPrintingPolicy(*this); CXXConstructorDecl *Constructor = static_cast<CXXConstructorDecl *>(ConstructorD); @@ -4259,7 +4260,7 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, // Fill in any already-initialized fields or base classes. llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields; llvm::SmallPtrSet<CanQualType, 4> InitializedBases; - for (unsigned I = 0; I != NumInitializers; ++I) { + for (unsigned I = 0, E = Initializers.size(); I != E; ++I) { if (Initializers[I]->isBaseInitializer()) InitializedBases.insert( Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0))); @@ -4271,17 +4272,17 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, // Add completions for base classes. CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); - bool SawLastInitializer = (NumInitializers == 0); + bool SawLastInitializer = Initializers.empty(); CXXRecordDecl *ClassDecl = Constructor->getParent(); for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), BaseEnd = ClassDecl->bases_end(); Base != BaseEnd; ++Base) { if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) { SawLastInitializer - = NumInitializers > 0 && - Initializers[NumInitializers - 1]->isBaseInitializer() && + = !Initializers.empty() && + Initializers.back()->isBaseInitializer() && Context.hasSameUnqualifiedType(Base->getType(), - QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0)); + QualType(Initializers.back()->getBaseClass(), 0)); continue; } @@ -4303,10 +4304,10 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, Base != BaseEnd; ++Base) { if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) { SawLastInitializer - = NumInitializers > 0 && - Initializers[NumInitializers - 1]->isBaseInitializer() && + = !Initializers.empty() && + Initializers.back()->isBaseInitializer() && Context.hasSameUnqualifiedType(Base->getType(), - QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0)); + QualType(Initializers.back()->getBaseClass(), 0)); continue; } @@ -4328,9 +4329,9 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, Field != FieldEnd; ++Field) { if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) { SawLastInitializer - = NumInitializers > 0 && - Initializers[NumInitializers - 1]->isAnyMemberInitializer() && - Initializers[NumInitializers - 1]->getAnyMember() == *Field; + = !Initializers.empty() && + Initializers.back()->isAnyMemberInitializer() && + Initializers.back()->getAnyMember() == *Field; continue; } @@ -4358,7 +4359,7 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, /// \brief Determine whether this scope denotes a namespace. static bool isNamespaceScope(Scope *S) { - DeclContext *DC = static_cast<DeclContext *>(S->getEntity()); + DeclContext *DC = S->getEntity(); if (!DC) return false; @@ -4786,9 +4787,9 @@ enum ObjCMethodKind { static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind, - IdentifierInfo **SelIdents, - unsigned NumSelIdents, + ArrayRef<IdentifierInfo *> SelIdents, bool AllowSameLength = true) { + unsigned NumSelIdents = SelIdents.size(); if (NumSelIdents > Sel.getNumArgs()) return false; @@ -4810,11 +4811,10 @@ static bool isAcceptableObjCSelector(Selector Sel, static bool isAcceptableObjCMethod(ObjCMethodDecl *Method, ObjCMethodKind WantKind, - IdentifierInfo **SelIdents, - unsigned NumSelIdents, + ArrayRef<IdentifierInfo *> SelIdents, bool AllowSameLength = true) { return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents, - NumSelIdents, AllowSameLength); + AllowSameLength); } namespace { @@ -4846,8 +4846,7 @@ namespace { static void AddObjCMethods(ObjCContainerDecl *Container, bool WantInstanceMethods, ObjCMethodKind WantKind, - IdentifierInfo **SelIdents, - unsigned NumSelIdents, + ArrayRef<IdentifierInfo *> SelIdents, DeclContext *CurContext, VisitedSelectorSet &Selectors, bool AllowSameLength, @@ -4866,15 +4865,14 @@ static void AddObjCMethods(ObjCContainerDecl *Container, (isRootClass && !WantInstanceMethods)) { // Check whether the selector identifiers we've been given are a // subset of the identifiers for this particular method. - if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents, - AllowSameLength)) + if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, AllowSameLength)) continue; if (!Selectors.insert(M->getSelector())) continue; Result R = Result(*M, Results.getBasePriority(*M), 0); - R.StartParameter = NumSelIdents; + R.StartParameter = SelIdents.size(); R.AllParametersAreInformative = (WantKind != MK_Any); if (!InOriginalClass) R.Priority += CCD_InBaseClass; @@ -4891,8 +4889,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container, E = Protocols.end(); I != E; ++I) AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, - NumSelIdents, CurContext, Selectors, AllowSameLength, - Results, false); + CurContext, Selectors, AllowSameLength, Results, false); } } @@ -4903,7 +4900,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container, for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(), E = IFace->protocol_end(); I != E; ++I) - AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents, + AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext, Selectors, AllowSameLength, Results, false); // Add methods in categories. @@ -4914,7 +4911,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container, ObjCCategoryDecl *CatDecl = *Cat; AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, - NumSelIdents, CurContext, Selectors, AllowSameLength, + CurContext, Selectors, AllowSameLength, Results, InOriginalClass); // Add a categories protocol methods. @@ -4924,26 +4921,26 @@ static void AddObjCMethods(ObjCContainerDecl *Container, E = Protocols.end(); I != E; ++I) AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, - NumSelIdents, CurContext, Selectors, AllowSameLength, + CurContext, Selectors, AllowSameLength, Results, false); // Add methods in category implementations. if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation()) AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, - NumSelIdents, CurContext, Selectors, AllowSameLength, + CurContext, Selectors, AllowSameLength, Results, InOriginalClass); } // Add methods in superclass. if (IFace->getSuperClass()) AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind, - SelIdents, NumSelIdents, CurContext, Selectors, + SelIdents, CurContext, Selectors, AllowSameLength, Results, false); // Add methods in our implementation, if any. if (ObjCImplementationDecl *Impl = IFace->getImplementation()) AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, - NumSelIdents, CurContext, Selectors, AllowSameLength, + CurContext, Selectors, AllowSameLength, Results, InOriginalClass); } @@ -4967,7 +4964,7 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S) { Results.EnterNewScope(); VisitedSelectorSet Selectors; - AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors, + AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors, /*AllowSameLength=*/true, Results); Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, @@ -4995,7 +4992,7 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S) { Results.EnterNewScope(); VisitedSelectorSet Selectors; - AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext, + AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors, /*AllowSameLength=*/true, Results); Results.ExitScope(); @@ -5159,16 +5156,14 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { /// \param SelIdents The identifiers in the selector that have already been /// provided as arguments for a send to "super". /// -/// \param NumSelIdents The number of identifiers in \p SelIdents. -/// /// \param Results The set of results to augment. /// /// \returns the Objective-C method declaration that would be invoked by /// this "super" completion. If NULL, no completion was added. -static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword, - IdentifierInfo **SelIdents, - unsigned NumSelIdents, - ResultBuilder &Results) { +static ObjCMethodDecl *AddSuperSendCompletion( + Sema &S, bool NeedSuperKeyword, + ArrayRef<IdentifierInfo *> SelIdents, + ResultBuilder &Results) { ObjCMethodDecl *CurMethod = S.getCurMethodDecl(); if (!CurMethod) return 0; @@ -5244,14 +5239,14 @@ static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword, } else { ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(); for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) { - if (I > NumSelIdents) + if (I > SelIdents.size()) Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); - if (I < NumSelIdents) + if (I < SelIdents.size()) Builder.AddInformativeChunk( Builder.getAllocator().CopyString( Sel.getNameForSlot(I) + ":")); - else if (NeedSuperKeyword || I > NumSelIdents) { + else if (NeedSuperKeyword || I > SelIdents.size()) { Builder.AddTextChunk( Builder.getAllocator().CopyString( Sel.getNameForSlot(I) + ":")); @@ -5293,7 +5288,7 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { if (Iface->getSuperClass()) { Results.AddResult(Result("super")); - AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results); + AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results); } if (getLangOpts().CPlusPlus11) @@ -5309,8 +5304,7 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { } void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, - IdentifierInfo **SelIdents, - unsigned NumSelIdents, + ArrayRef<IdentifierInfo *> SelIdents, bool AtArgumentExpression) { ObjCInterfaceDecl *CDecl = 0; if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { @@ -5328,8 +5322,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, // We are inside an instance method, which means that the message // send [super ...] is actually calling an instance method on the // current object. - return CodeCompleteObjCInstanceMessage(S, 0, - SelIdents, NumSelIdents, + return CodeCompleteObjCInstanceMessage(S, 0, SelIdents, AtArgumentExpression, CDecl); } @@ -5358,7 +5351,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id, false, false); return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(), - SelIdents, NumSelIdents, + SelIdents, AtArgumentExpression); } @@ -5369,7 +5362,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, if (CDecl) Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl)); return CodeCompleteObjCClassMessage(S, Receiver, SelIdents, - NumSelIdents, AtArgumentExpression, + AtArgumentExpression, /*IsSuper=*/true); } @@ -5409,8 +5402,7 @@ static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results, static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, ParsedType Receiver, - IdentifierInfo **SelIdents, - unsigned NumSelIdents, + ArrayRef<IdentifierInfo *> SelIdents, bool AtArgumentExpression, bool IsSuper, ResultBuilder &Results) { @@ -5434,8 +5426,7 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, // completion. if (IsSuper) { if (ObjCMethodDecl *SuperMethod - = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents, - Results)) + = AddSuperSendCompletion(SemaRef, false, SelIdents, Results)) Results.Ignore(SuperMethod); } @@ -5446,7 +5437,7 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, VisitedSelectorSet Selectors; if (CDecl) - AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents, + AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext, Selectors, AtArgumentExpression, Results); else { @@ -5472,12 +5463,11 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, for (ObjCMethodList *MethList = &M->second.second; MethList && MethList->Method; MethList = MethList->getNext()) { - if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, - NumSelIdents)) + if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents)) continue; Result R(MethList->Method, Results.getBasePriority(MethList->Method),0); - R.StartParameter = NumSelIdents; + R.StartParameter = SelIdents.size(); R.AllParametersAreInformative = false; Results.MaybeAddResult(R, SemaRef.CurContext); } @@ -5488,8 +5478,7 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, } void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, - IdentifierInfo **SelIdents, - unsigned NumSelIdents, + ArrayRef<IdentifierInfo *> SelIdents, bool AtArgumentExpression, bool IsSuper) { @@ -5498,9 +5487,9 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, - T, SelIdents, NumSelIdents)); + T, SelIdents)); - AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents, + AddClassMessageCompletions(*this, S, Receiver, SelIdents, AtArgumentExpression, IsSuper, Results); // If we're actually at the argument expression (rather than prior to the @@ -5510,7 +5499,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, // our preferred type, improving completion results. if (AtArgumentExpression) { QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, - NumSelIdents); + SelIdents.size()); if (PreferredType.isNull()) CodeCompleteOrdinaryName(S, PCC_Expression); else @@ -5524,8 +5513,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, } void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, - IdentifierInfo **SelIdents, - unsigned NumSelIdents, + ArrayRef<IdentifierInfo *> SelIdents, bool AtArgumentExpression, ObjCInterfaceDecl *Super) { typedef CodeCompletionResult Result; @@ -5553,7 +5541,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, if (ReceiverType->isObjCClassType()) return CodeCompleteObjCClassMessage(S, ParsedType::make(Context.getObjCInterfaceType(IFace)), - SelIdents, NumSelIdents, + SelIdents, AtArgumentExpression, Super); ReceiverType = Context.getObjCObjectPointerType( @@ -5564,7 +5552,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage, - ReceiverType, SelIdents, NumSelIdents)); + ReceiverType, SelIdents)); Results.EnterNewScope(); @@ -5572,8 +5560,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, // completion. if (Super) { if (ObjCMethodDecl *SuperMethod - = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents, - Results)) + = AddSuperSendCompletion(*this, false, SelIdents, Results)) Results.Ignore(SuperMethod); } @@ -5592,7 +5579,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, ReceiverType->isObjCQualifiedClassType()) { if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface()) - AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents, + AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext, Selectors, AtArgumentExpression, Results); } } @@ -5603,7 +5590,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(), E = QualID->qual_end(); I != E; ++I) - AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext, + AddObjCMethods(*I, true, MK_Any, SelIdents, CurContext, Selectors, AtArgumentExpression, Results); } // Handle messages to a pointer to interface type. @@ -5611,14 +5598,14 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, = ReceiverType->getAsObjCInterfacePointerType()) { // Search the class, its superclasses, etc., for instance methods. AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents, - NumSelIdents, CurContext, Selectors, AtArgumentExpression, + CurContext, Selectors, AtArgumentExpression, Results); // Search protocols for instance methods. for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(), E = IFacePtr->qual_end(); I != E; ++I) - AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext, + AddObjCMethods(*I, true, MK_Any, SelIdents, CurContext, Selectors, AtArgumentExpression, Results); } // Handle messages to "id". @@ -5645,15 +5632,14 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, for (ObjCMethodList *MethList = &M->second.first; MethList && MethList->Method; MethList = MethList->getNext()) { - if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, - NumSelIdents)) + if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents)) continue; if (!Selectors.insert(MethList->Method->getSelector())) continue; Result R(MethList->Method, Results.getBasePriority(MethList->Method),0); - R.StartParameter = NumSelIdents; + R.StartParameter = SelIdents.size(); R.AllParametersAreInformative = false; Results.MaybeAddResult(R, CurContext); } @@ -5669,7 +5655,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, // our preferred type, improving completion results. if (AtArgumentExpression) { QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, - NumSelIdents); + SelIdents.size()); if (PreferredType.isNull()) CodeCompleteOrdinaryName(S, PCC_Expression); else @@ -5688,7 +5674,7 @@ void Sema::CodeCompleteObjCForCollection(Scope *S, Data.ObjCCollection = true; if (IterationVar.getAsOpaquePtr()) { - DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>(); + DeclGroupRef DG = IterationVar.get(); for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) { if (*I) Data.IgnoreDecls.push_back(*I); @@ -5698,8 +5684,8 @@ void Sema::CodeCompleteObjCForCollection(Scope *S, CodeCompleteExpression(S, Data); } -void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents, - unsigned NumSelIdents) { +void Sema::CodeCompleteObjCSelector(Scope *S, + ArrayRef<IdentifierInfo *> SelIdents) { // If we have an external source, load the entire class method // pool from the AST file. if (ExternalSource) { @@ -5722,7 +5708,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents, M != MEnd; ++M) { Selector Sel = M->first; - if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents)) + if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents)) continue; CodeCompletionBuilder Builder(Results.getAllocator(), @@ -5736,7 +5722,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents, std::string Accumulator; for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) { - if (I == NumSelIdents) { + if (I == SelIdents.size()) { if (!Accumulator.empty()) { Builder.AddInformativeChunk(Builder.getAllocator().CopyString( Accumulator)); @@ -6128,8 +6114,8 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, // Mapping from selectors to the methods that implement that selector, along // with the "in original class" flag. -typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> > - KnownMethodsMap; +typedef llvm::DenseMap< + Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap; /// \brief Find all of the methods that reside in the given container /// (and its superclasses, protocols, etc.) that meet the given @@ -6218,7 +6204,8 @@ static void FindImplementableMethods(ASTContext &Context, !Context.hasSameUnqualifiedType(ReturnType, M->getResultType())) continue; - KnownMethods[M->getSelector()] = std::make_pair(*M, InOriginalClass); + KnownMethods[M->getSelector()] = + KnownMethodsMap::mapped_type(*M, InOriginalClass); } } } @@ -6906,7 +6893,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, } if (!SearchDecl && S) { - if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity())) + if (DeclContext *DC = S->getEntity()) SearchDecl = dyn_cast<ObjCContainerDecl>(DC); } @@ -6932,7 +6919,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, for (KnownMethodsMap::iterator M = KnownMethods.begin(), MEnd = KnownMethods.end(); M != MEnd; ++M) { - ObjCMethodDecl *Method = M->second.first; + ObjCMethodDecl *Method = M->second.getPointer(); CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); @@ -7000,7 +6987,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, } unsigned Priority = CCP_CodePattern; - if (!M->second.second) + if (!M->second.getInt()) Priority += CCD_InBaseClass; Results.AddResult(Result(Builder.TakeString(), Method, Priority)); @@ -7054,8 +7041,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy, - IdentifierInfo **SelIdents, - unsigned NumSelIdents) { + ArrayRef<IdentifierInfo *> SelIdents) { // If we have an external source, load the entire class method // pool from the AST file. if (ExternalSource) { @@ -7086,12 +7072,12 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, &M->second.second; MethList && MethList->Method; MethList = MethList->getNext()) { - if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, - NumSelIdents)) + if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents)) continue; if (AtParameterName) { // Suggest parameter names we've seen before. + unsigned NumSelIdents = SelIdents.size(); if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) { ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1]; if (Param->getIdentifier()) { @@ -7107,7 +7093,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, } Result R(MethList->Method, Results.getBasePriority(MethList->Method), 0); - R.StartParameter = NumSelIdents; + R.StartParameter = SelIdents.size(); R.AllParametersAreInformative = false; R.DeclaringEntity = true; Results.MaybeAddResult(R, CurContext); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp index fd7cfeb6f0da..328ce7059631 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp @@ -15,6 +15,7 @@ #include "TypeLocBuilder.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" #include "clang/AST/CommentDiagnostic.h" @@ -39,6 +40,7 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/Template.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Triple.h" #include <algorithm> @@ -108,6 +110,7 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const { case tok::kw_char16_t: case tok::kw_char32_t: case tok::kw_typeof: + case tok::annot_decltype: case tok::kw_decltype: return getLangOpts().CPlusPlus; @@ -126,9 +129,6 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const { /// determine whether the name refers to a type. If so, returns an /// opaque pointer (actually a QualType) corresponding to that /// type. Otherwise, returns NULL. -/// -/// If name lookup results in an ambiguity, this routine will complain -/// and then return NULL. ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS, bool isClassName, bool HasTrailingDot, @@ -237,17 +237,9 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, IsCtorOrDtorName, WantNontrivialTypeSourceInfo); if (Ty) { - std::string CorrectedStr(Correction.getAsString(getLangOpts())); - std::string CorrectedQuotedStr( - Correction.getQuoted(getLangOpts())); - Diag(NameLoc, diag::err_unknown_type_or_class_name_suggest) - << Result.getLookupName() << CorrectedQuotedStr << isClassName - << FixItHint::CreateReplacement(SourceRange(NameLoc), - CorrectedStr); - if (NamedDecl *FirstDecl = Correction.getCorrectionDecl()) - Diag(FirstDecl->getLocation(), diag::note_previous_decl) - << CorrectedQuotedStr; - + diagnoseTypo(Correction, + PDiag(diag::err_unknown_type_or_class_name_suggest) + << Result.getLookupName() << isClassName); if (SS && NNS) SS->MakeTrivial(Context, NNS, SourceRange(NameLoc)); *CorrectedII = NewII; @@ -412,38 +404,33 @@ bool Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(II, IILoc), LookupOrdinaryName, S, SS, Validator)) { - std::string CorrectedStr(Corrected.getAsString(getLangOpts())); - std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); - if (Corrected.isKeyword()) { // We corrected to a keyword. - IdentifierInfo *NewII = Corrected.getCorrectionAsIdentifierInfo(); - if (!isSimpleTypeSpecifier(NewII->getTokenID())) - CorrectedQuotedStr = "the keyword " + CorrectedQuotedStr; - Diag(IILoc, diag::err_unknown_typename_suggest) - << II << CorrectedQuotedStr - << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr); - II = NewII; + diagnoseTypo(Corrected, PDiag(diag::err_unknown_typename_suggest) << II); + II = Corrected.getCorrectionAsIdentifierInfo(); } else { - NamedDecl *Result = Corrected.getCorrectionDecl(); // 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(Corrected.getCorrectionRange(), - CorrectedStr); - else + if (!SS || !SS->isSet()) { + diagnoseTypo(Corrected, + PDiag(diag::err_unknown_typename_suggest) << II); + } else if (DeclContext *DC = computeDeclContext(*SS, false)) { + std::string CorrectedStr(Corrected.getAsString(getLangOpts())); + bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && + II->getName().equals(CorrectedStr); + diagnoseTypo(Corrected, + PDiag(diag::err_unknown_nested_typename_suggest) + << II << DC << DroppedSpecifier << SS->getRange()); + } 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(), + CXXScopeSpec tmpSS; + if (Corrected.getCorrectionSpecifier()) + tmpSS.MakeTrivial(Context, Corrected.getCorrectionSpecifier(), + SourceRange(IILoc)); + SuggestedType = getTypeName(*Corrected.getCorrectionAsIdentifierInfo(), + IILoc, S, tmpSS.isSet() ? &tmpSS : SS, false, + false, ParsedType(), /*IsCtorOrDtorName=*/false, /*NonTrivialTypeSourceInfo=*/true); } @@ -460,7 +447,7 @@ bool Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, if (isTemplateName(S, SS ? *SS : EmptySS, /*hasTemplateKeyword=*/false, Name, ParsedType(), true, TemplateResult, MemberOfUnknownSpecialization) == TNK_Type_template) { - TemplateName TplName = TemplateResult.getAsVal<TemplateName>(); + TemplateName TplName = TemplateResult.get(); Diag(IILoc, diag::err_template_missing_args) << TplName; if (TemplateDecl *TplDecl = TplName.getAsTemplateDecl()) { Diag(TplDecl->getLocation(), diag::note_template_decl_here) @@ -662,9 +649,7 @@ Corrected: &SS, *CCC)) { unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest; unsigned QualifiedDiag = diag::err_no_member_suggest; - std::string CorrectedStr(Corrected.getAsString(getLangOpts())); - std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); - + NamedDecl *FirstDecl = Corrected.getCorrectionDecl(); NamedDecl *UnderlyingFirstDecl = FirstDecl? FirstDecl->getUnderlyingDecl() : 0; @@ -680,33 +665,30 @@ Corrected: QualifiedDiag = diag::err_unknown_nested_typename_suggest; } - if (SS.isEmpty()) - Diag(NameLoc, UnqualifiedDiag) - << Name << CorrectedQuotedStr - << FixItHint::CreateReplacement(NameLoc, CorrectedStr); - else // FIXME: is this even reachable? Test it. - Diag(NameLoc, QualifiedDiag) - << Name << computeDeclContext(SS, false) << CorrectedQuotedStr - << SS.getRange() - << FixItHint::CreateReplacement(Corrected.getCorrectionRange(), - CorrectedStr); + if (SS.isEmpty()) { + diagnoseTypo(Corrected, PDiag(UnqualifiedDiag) << Name); + } else {// FIXME: is this even reachable? Test it. + std::string CorrectedStr(Corrected.getAsString(getLangOpts())); + bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && + Name->getName().equals(CorrectedStr); + diagnoseTypo(Corrected, PDiag(QualifiedDiag) + << Name << computeDeclContext(SS, false) + << DroppedSpecifier << SS.getRange()); + } // 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(); + return Name; // Also update the LookupResult... // FIXME: This should probably go away at some point Result.clear(); Result.setLookupName(Corrected.getCorrection()); - 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 @@ -789,6 +771,7 @@ Corrected: if (!Result.empty()) { bool IsFunctionTemplate; + bool IsVarTemplate; TemplateName Template; if (Result.end() - Result.begin() > 1) { IsFunctionTemplate = true; @@ -798,7 +781,8 @@ Corrected: TemplateDecl *TD = cast<TemplateDecl>((*Result.begin())->getUnderlyingDecl()); IsFunctionTemplate = isa<FunctionTemplateDecl>(TD); - + IsVarTemplate = isa<VarTemplateDecl>(TD); + if (SS.isSet() && !SS.isInvalid()) Template = Context.getQualifiedTemplateName(SS.getScopeRep(), /*TemplateKeyword=*/false, @@ -815,8 +799,9 @@ Corrected: return NameClassification::FunctionTemplate(Template); } - - return NameClassification::TypeTemplate(Template); + + return IsVarTemplate ? NameClassification::VarTemplate(Template) + : NameClassification::TypeTemplate(Template); } } @@ -858,18 +843,16 @@ Corrected: // Check for a tag type hidden by a non-type decl in a few cases where it // seems likely a type is wanted instead of the non-type that was found. - if (!getLangOpts().ObjC1) { - bool NextIsOp = NextToken.is(tok::amp) || NextToken.is(tok::star); - if ((NextToken.is(tok::identifier) || - (NextIsOp && FirstDecl->isFunctionOrFunctionTemplate())) && - isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) { - TypeDecl *Type = Result.getAsSingle<TypeDecl>(); - DiagnoseUseOfDecl(Type, NameLoc); - QualType T = Context.getTypeDeclType(Type); - if (SS.isNotEmpty()) - return buildNestedType(*this, SS, T, NameLoc); - return ParsedType::make(T); - } + bool NextIsOp = NextToken.is(tok::amp) || NextToken.is(tok::star); + if ((NextToken.is(tok::identifier) || + (NextIsOp && FirstDecl->isFunctionOrFunctionTemplate())) && + isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) { + TypeDecl *Type = Result.getAsSingle<TypeDecl>(); + DiagnoseUseOfDecl(Type, NameLoc); + QualType T = Context.getTypeDeclType(Type); + if (SS.isNotEmpty()) + return buildNestedType(*this, SS, T, NameLoc); + return ParsedType::make(T); } if (FirstDecl->isCXXClassMember()) @@ -887,7 +870,16 @@ DeclContext *Sema::getContainingDC(DeclContext *DC) { // Functions defined inline within classes aren't parsed until we've // finished parsing the top-level class, so the top-level class is // the context we'll need to return to. - if (isa<FunctionDecl>(DC)) { + // A Lambda call operator whose parent is a class must not be treated + // as an inline member function. A Lambda can be used legally + // either as an in-class member initializer or a default argument. These + // are parsed once the class has been marked complete and so the containing + // context would be the nested class (when the lambda is defined in one); + // If the class is not complete, then the lambda is being used in an + // ill-formed fashion (such as to specify the width of a bit-field, or + // in an array-bound) - in which case we still want to return the + // lexically containing DC (which could be a nested class). + if (isa<FunctionDecl>(DC) && !isLambdaCallOperator(DC)) { DC = DC->getLexicalParent(); // A function not defined within a class will always return to its @@ -962,7 +954,7 @@ void Sema::ExitDeclaratorContext(Scope *S) { // enforced by an assert in EnterDeclaratorContext. Scope *Ancestor = S->getParent(); while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent(); - CurContext = (DeclContext*) Ancestor->getEntity(); + CurContext = Ancestor->getEntity(); // We don't need to do anything with the scope, which is going to // disappear. @@ -1032,8 +1024,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { // Move up the scope chain until we find the nearest enclosing // non-transparent context. The declaration will be introduced into this // scope. - while (S->getEntity() && - ((DeclContext *)S->getEntity())->isTransparentContext()) + while (S->getEntity() && S->getEntity()->isTransparentContext()) S = S->getParent(); // Add scoped declarations into their context, so that they can be @@ -1042,12 +1033,12 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { if (AddToContext) CurContext->addDecl(D); - // 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 ((getLangOpts().CPlusPlus || isa<VarDecl>(D) || isa<FunctionDecl>(D)) && - D->isOutOfLine() && + // Out-of-line definitions shouldn't be pushed into scope in C++, unless they + // are function-local declarations. + if (getLangOpts().CPlusPlus && D->isOutOfLine() && !D->getDeclContext()->getRedeclContext()->Equals( - D->getLexicalDeclContext()->getRedeclContext())) + D->getLexicalDeclContext()->getRedeclContext()) && + !D->getLexicalDeclContext()->isFunctionOrMethod()) return; // Template instantiations should also not be pushed into scope. @@ -1094,7 +1085,7 @@ void Sema::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { TUScope->AddDecl(D); } -bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S, +bool Sema::isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S, bool ExplicitInstantiationOrSpecialization) { return IdResolver.isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization); @@ -1103,7 +1094,7 @@ bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S, Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) { DeclContext *TargetDC = DC->getPrimaryContext(); do { - if (DeclContext *ScopeDC = (DeclContext*) S->getEntity()) + if (DeclContext *ScopeDC = S->getEntity()) if (ScopeDC->getPrimaryContext() == TargetDC) return S; } while ((S = S->getParent())); @@ -1196,7 +1187,15 @@ bool Sema::mightHaveNonExternalLinkage(const DeclaratorDecl *D) { DC = DC->getParent(); } - return !D->hasExternalLinkage(); + return !D->isExternallyVisible(); +} + +// FIXME: This needs to be refactored; some other isInMainFile users want +// these semantics. +static bool isMainFileLoc(const Sema &S, SourceLocation Loc) { + if (S.TUKind != TU_Complete) + return false; + return S.SourceMgr.isInMainFile(Loc); } bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const { @@ -1218,12 +1217,9 @@ bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const { if (MD->isVirtual() || IsDisallowedCopyOrAssign(MD)) return false; } else { - // 'static inline' functions are used in headers; don't warn. - // Make sure we get the storage class from the canonical declaration, - // since otherwise we will get spurious warnings on specialized - // static template functions. - if (FD->getCanonicalDecl()->getStorageClass() == SC_Static && - FD->isInlineSpecified()) + // 'static inline' functions are defined in headers; don't warn. + if (FD->isInlineSpecified() && + !isMainFileLoc(*this, FD->getLocation())) return false; } @@ -1231,21 +1227,18 @@ bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const { Context.DeclMustBeEmitted(FD)) return false; } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - // Don't warn on variables of const-qualified or reference type, since their - // values can be used even if though they're not odr-used, and because const - // qualified variables can appear in headers in contexts where they're not - // intended to be used. - // FIXME: Use more principled rules for these exemptions. - if (!VD->isFileVarDecl() || - VD->getType().isConstQualified() || - VD->getType()->isReferenceType() || - Context.DeclMustBeEmitted(VD)) + // Constants and utility variables are defined in headers with internal + // linkage; don't warn. (Unlike functions, there isn't a convenient marker + // like "inline".) + if (!isMainFileLoc(*this, VD->getLocation())) + return false; + + if (Context.DeclMustBeEmitted(VD)) return false; if (VD->isStaticDataMember() && VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) return false; - } else { return false; } @@ -1259,13 +1252,13 @@ void Sema::MarkUnusedFileScopedDecl(const DeclaratorDecl *D) { return; if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - const FunctionDecl *First = FD->getFirstDeclaration(); + const FunctionDecl *First = FD->getFirstDecl(); if (FD != First && ShouldWarnIfUnusedFileScopedDecl(First)) return; // First should already be in the vector. } if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - const VarDecl *First = VD->getFirstDeclaration(); + const VarDecl *First = VD->getFirstDecl(); if (VD != First && ShouldWarnIfUnusedFileScopedDecl(First)) return; // First should already be in the vector. } @@ -1312,7 +1305,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { return false; if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) { - if (!RD->hasTrivialDestructor()) + if (!RD->hasTrivialDestructor() && !RD->hasAttr<WarnUnusedAttr>()) return false; if (const Expr *Init = VD->getInit()) { @@ -1322,7 +1315,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { dyn_cast<CXXConstructExpr>(Init); if (Construct && !Construct->isElidable()) { CXXConstructorDecl *CD = Construct->getConstructor(); - if (!CD->isTrivial()) + if (!CD->isTrivial() && !RD->hasAttr<WarnUnusedAttr>()) return false; } } @@ -1402,6 +1395,7 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { // Remove this name from our lexical scope. IdResolver.RemoveDecl(D); } + DiagnoseUnusedBackingIvarInAccessor(S); } void Sema::ActOnStartFunctionDeclarator() { @@ -1440,13 +1434,8 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id, if (TypoCorrection C = CorrectTypo(DeclarationNameInfo(Id, IdLoc), LookupOrdinaryName, TUScope, NULL, Validator)) { + diagnoseTypo(C, PDiag(diag::err_undef_interface_suggest) << Id); IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>(); - Diag(IdLoc, diag::err_undef_interface_suggest) - << Id << IDecl->getDeclName() - << FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString()); - Diag(IDecl->getLocation(), diag::note_previous_decl) - << IDecl->getDeclName(); - Id = IDecl->getIdentifier(); } } @@ -1482,8 +1471,7 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id, /// contain non-field names. Scope *Sema::getNonFieldDeclScope(Scope *S) { while (((S->getFlags() & Scope::DeclScope) == 0) || - (S->getEntity() && - ((DeclContext *)S->getEntity())->isTransparentContext()) || + (S->getEntity() && S->getEntity()->isTransparentContext()) || (S->isClassScope() && !getLangOpts().CPlusPlus)) S = S->getParent(); return S; @@ -1556,8 +1544,17 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, << Context.BuiltinInfo.GetName(BID); } + DeclContext *Parent = Context.getTranslationUnitDecl(); + if (getLangOpts().CPlusPlus) { + LinkageSpecDecl *CLinkageDecl = + LinkageSpecDecl::Create(Context, Parent, Loc, Loc, + LinkageSpecDecl::lang_c, false); + Parent->addDecl(CLinkageDecl); + Parent = CLinkageDecl; + } + FunctionDecl *New = FunctionDecl::Create(Context, - Context.getTranslationUnitDecl(), + Parent, Loc, Loc, II, R, /*TInfo=*/0, SC_Extern, false, @@ -1581,13 +1578,14 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, } AddKnownFunctionAttributes(New); + RegisterLocallyScopedExternCDecl(New, S); // TUScope is the translation-unit scope to insert this function into. // FIXME: This is hideous. We need to teach PushOnScopeChains to // relate Scopes to DeclContexts, and probably eliminate CurContext // entirely, but we're not there yet. DeclContext *SavedContext = CurContext; - CurContext = Context.getTranslationUnitDecl(); + CurContext = Parent; PushOnScopeChains(New, TUScope); CurContext = SavedContext; return New; @@ -1616,7 +1614,7 @@ static void filterNonConflictingPreviousDecls(ASTContext &context, if (!old->isHidden()) continue; - if (old->getLinkage() != ExternalLinkage) + if (!old->isExternallyVisible()) filter.erase(); } @@ -1730,10 +1728,12 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { if (isIncompatibleTypedef(Old, New)) return; - // The types match. Link up the redeclaration chain if the old - // declaration was a typedef. - if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old)) - New->setPreviousDeclaration(Typedef); + // The types match. Link up the redeclaration chain and merge attributes if + // the old declaration was a typedef. + if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old)) { + New->setPreviousDecl(Typedef); + mergeDeclAttributes(New, Old); + } if (getLangOpts().MicrosoftExt) return; @@ -2014,11 +2014,15 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, InheritableAttr *Attr, static const Decl *getDefinition(const Decl *D) { if (const TagDecl *TD = dyn_cast<TagDecl>(D)) return TD->getDefinition(); - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) - return VD->getDefinition(); + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + const VarDecl *Def = VD->getDefinition(); + if (Def) + return Def; + return VD->getActingDefinition(); + } if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { const FunctionDecl* Def; - if (FD->hasBody(Def)) + if (FD->isDefined(Def)) return Def; } return NULL; @@ -2047,6 +2051,32 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { AttrVec &NewAttributes = New->getAttrs(); for (unsigned I = 0, E = NewAttributes.size(); I != E;) { const Attr *NewAttribute = NewAttributes[I]; + + if (isa<AliasAttr>(NewAttribute)) { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New)) + S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def)); + else { + VarDecl *VD = cast<VarDecl>(New); + unsigned Diag = cast<VarDecl>(Def)->isThisDeclarationADefinition() == + VarDecl::TentativeDefinition + ? diag::err_alias_after_tentative + : diag::err_redefinition; + S.Diag(VD->getLocation(), Diag) << VD->getDeclName(); + S.Diag(Def->getLocation(), diag::note_previous_definition); + VD->setInvalidDecl(); + } + ++I; + continue; + } + + if (const VarDecl *VD = dyn_cast<VarDecl>(Def)) { + // Tentative definitions are only interesting for the alias check above. + if (VD->isThisDeclarationADefinition() != VarDecl::Definition) { + ++I; + continue; + } + } + if (hasAttribute(Def, NewAttribute->getKind())) { ++I; continue; // regular attr merging will take care of validating this. @@ -2087,6 +2117,12 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { /// mergeDeclAttributes - Copy attributes from the Old decl to the New one. void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, AvailabilityMergeKind AMK) { + if (UsedAttr *OldAttr = Old->getMostRecentDecl()->getAttr<UsedAttr>()) { + UsedAttr *NewAttr = OldAttr->clone(Context); + NewAttr->setInherited(true); + New->addAttr(NewAttr); + } + if (!Old->hasAttrs() && !New->hasAttrs()) return; @@ -2124,6 +2160,10 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, } } + // Already handled. + if (isa<UsedAttr>(*i)) + continue; + if (mergeDeclAttribute(*this, New, *i, Override)) foundAny = true; } @@ -2150,7 +2190,7 @@ static void mergeParamDeclAttributes(ParmVarDecl *newDecl, // Find the first declaration of the parameter. // FIXME: Should we build redeclaration chains for function parameters? const FunctionDecl *FirstFD = - cast<FunctionDecl>(oldDecl->getDeclContext())->getFirstDeclaration(); + cast<FunctionDecl>(oldDecl->getDeclContext())->getFirstDecl(); const ParmVarDecl *FirstVD = FirstFD->getParamDecl(oldDecl->getFunctionScopeIndex()); S.Diag(FirstVD->getLocation(), @@ -2226,17 +2266,11 @@ static bool canRedefineFunction(const FunctionDecl *FD, FD->getStorageClass() == SC_Extern); } -/// Is the given calling convention the ABI default for the given -/// declaration? -static bool isABIDefaultCC(Sema &S, CallingConv CC, FunctionDecl *D) { - CallingConv ABIDefaultCC; - if (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance()) { - ABIDefaultCC = S.Context.getDefaultCXXMethodCallConv(D->isVariadic()); - } else { - // Free C function or a static method. - ABIDefaultCC = (S.Context.getLangOpts().MRTD ? CC_X86StdCall : CC_C); - } - return ABIDefaultCC == CC; +const AttributedType *Sema::getCallingConvAttributedType(QualType T) const { + const AttributedType *AT = T->getAs<AttributedType>(); + while (AT && !AT->isCallingConv()) + AT = AT->getModifiedType()->getAs<AttributedType>(); + return AT; } template <typename T> @@ -2264,7 +2298,8 @@ static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) { /// merged with. /// /// Returns true if there was an error, false otherwise. -bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { +bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, + bool MergeTypeWithOld) { // Verify the old decl was also a function. FunctionDecl *Old = 0; if (FunctionTemplateDecl *OldFunctionTemplate @@ -2297,6 +2332,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { return true; } + // If the old declaration is invalid, just give up here. + if (Old->isInvalidDecl()) + return true; + // Determine whether the previous declaration was a definition, // implicit declaration, or a declaration. diag::kind PrevDiag; @@ -2307,16 +2346,13 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { else PrevDiag = diag::note_previous_declaration; - QualType OldQType = Context.getCanonicalType(Old->getType()); - QualType NewQType = Context.getCanonicalType(New->getType()); - // Don't complain about this if we're in GNU89 mode and the old function // is an extern inline function. // Don't complain about specializations. They are not supposed to have // storage classes. if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) && New->getStorageClass() == SC_Static && - isExternalLinkage(Old->getLinkage()) && + Old->hasExternalFormalLinkage() && !New->getTemplateSpecializationInfo() && !canRedefineFunction(Old, getLangOpts())) { if (getLangOpts().MicrosoftExt) { @@ -2329,53 +2365,52 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { } } - // If a function is first declared with a calling convention, but is - // later declared or defined without one, the second decl assumes the - // calling convention of the first. + + // If a function is first declared with a calling convention, but is later + // declared or defined without one, all following decls assume the calling + // convention of the first. // // It's OK if a function is first declared without a calling convention, // but is later declared or defined with the default calling convention. // - // For the new decl, we have to look at the NON-canonical type to tell the - // difference between a function that really doesn't have a calling - // convention and one that is declared cdecl. That's because in - // canonicalization (see ASTContext.cpp), cdecl is canonicalized away - // because it is the default calling convention. + // To test if either decl has an explicit calling convention, we look for + // AttributedType sugar nodes on the type as written. If they are missing or + // were canonicalized away, we assume the calling convention was implicit. // // Note also that we DO NOT return at this point, because we still have // other tests to run. + QualType OldQType = Context.getCanonicalType(Old->getType()); + QualType NewQType = Context.getCanonicalType(New->getType()); const FunctionType *OldType = cast<FunctionType>(OldQType); - const FunctionType *NewType = New->getType()->getAs<FunctionType>(); + const FunctionType *NewType = cast<FunctionType>(NewQType); FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo(); FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo(); bool RequiresAdjustment = false; - if (OldTypeInfo.getCC() == NewTypeInfo.getCC()) { - // Fast path: nothing to do. - - // Inherit the CC from the previous declaration if it was specified - // there but not here. - } else if (NewTypeInfo.getCC() == CC_Default) { - NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC()); - RequiresAdjustment = true; - // Don't complain about mismatches when the default CC is - // effectively the same as the explict one. Only Old decl contains correct - // information about storage class of CXXMethod. - } else if (OldTypeInfo.getCC() == CC_Default && - isABIDefaultCC(*this, NewTypeInfo.getCC(), Old)) { - NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC()); - RequiresAdjustment = true; - - } else if (!Context.isSameCallConv(OldTypeInfo.getCC(), - NewTypeInfo.getCC())) { - // Calling conventions really aren't compatible, so complain. - Diag(New->getLocation(), diag::err_cconv_change) - << FunctionType::getNameForCallConv(NewTypeInfo.getCC()) - << (OldTypeInfo.getCC() == CC_Default) - << (OldTypeInfo.getCC() == CC_Default ? "" : - FunctionType::getNameForCallConv(OldTypeInfo.getCC())); - Diag(Old->getLocation(), diag::note_previous_declaration); - return true; + if (OldTypeInfo.getCC() != NewTypeInfo.getCC()) { + FunctionDecl *First = Old->getFirstDecl(); + const FunctionType *FT = + First->getType().getCanonicalType()->castAs<FunctionType>(); + FunctionType::ExtInfo FI = FT->getExtInfo(); + bool NewCCExplicit = getCallingConvAttributedType(New->getType()); + if (!NewCCExplicit) { + // Inherit the CC from the previous declaration if it was specified + // there but not here. + NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC()); + RequiresAdjustment = true; + } else { + // Calling conventions aren't compatible, so complain. + bool FirstCCExplicit = getCallingConvAttributedType(First->getType()); + Diag(New->getLocation(), diag::err_cconv_change) + << FunctionType::getNameForCallConv(NewTypeInfo.getCC()) + << !FirstCCExplicit + << (!FirstCCExplicit ? "" : + FunctionType::getNameForCallConv(FI.getCC())); + + // Put the note on the first decl, since it is the one that matters. + Diag(First->getLocation(), diag::note_previous_declaration); + return true; + } } // FIXME: diagnose the other way around? @@ -2412,9 +2447,11 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { } if (RequiresAdjustment) { - NewType = Context.adjustFunctionType(NewType, NewTypeInfo); - New->setType(QualType(NewType, 0)); + const FunctionType *AdjustedType = New->getType()->getAs<FunctionType>(); + AdjustedType = Context.adjustFunctionType(AdjustedType, NewTypeInfo); + New->setType(QualType(AdjustedType, 0)); NewQType = Context.getCanonicalType(New->getType()); + NewType = cast<FunctionType>(NewQType); } // If this redeclaration makes the function inline, we may need to add it to @@ -2441,7 +2478,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { // cannot be overloaded. // Go back to the type source info to compare the declared return types, - // per C++1y [dcl.type.auto]p??: + // per C++1y [dcl.type.auto]p13: // Redeclarations or specializations of a function or function template // with a declared return type that uses a placeholder type shall also // use that placeholder, not a deduced type. @@ -2452,7 +2489,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { ? New->getTypeSourceInfo()->getType()->castAs<FunctionType>() : NewType)->getResultType(); QualType ResQT; - if (!Context.hasSameType(OldDeclaredReturnType, NewDeclaredReturnType)) { + if (!Context.hasSameType(OldDeclaredReturnType, NewDeclaredReturnType) && + !((NewQType->isDependentType() || OldQType->isDependentType()) && + New->isLocalExternDecl())) { if (NewDeclaredReturnType->isObjCObjectPointerType() && OldDeclaredReturnType->isObjCObjectPointerType()) ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType); @@ -2476,9 +2515,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { // defined, copy the deduced value from the old declaration. AutoType *OldAT = Old->getResultType()->getContainedAutoType(); if (OldAT && OldAT->isDeduced()) { - New->setType(SubstAutoType(New->getType(), OldAT->getDeducedType())); + New->setType( + SubstAutoType(New->getType(), + OldAT->isDependentType() ? Context.DependentTy + : OldAT->getDeducedType())); NewQType = Context.getCanonicalType( - SubstAutoType(NewQType, OldAT->getDeducedType())); + SubstAutoType(NewQType, + OldAT->isDependentType() ? Context.DependentTy + : OldAT->getDeducedType())); } } @@ -2501,7 +2545,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { // -- Member function declarations with the same name and the // same parameter types cannot be overloaded if any of them // is a static member function declaration. - if (OldMethod->isStatic() || NewMethod->isStatic()) { + if (OldMethod->isStatic() != NewMethod->isStatic()) { Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member); Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); return true; @@ -2559,7 +2603,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { !Old->hasAttr<CXX11NoReturnAttr>()) { Diag(New->getAttr<CXX11NoReturnAttr>()->getLocation(), diag::err_noreturn_missing_on_first_decl); - Diag(Old->getFirstDeclaration()->getLocation(), + Diag(Old->getFirstDecl()->getLocation(), diag::note_noreturn_missing_first_decl); } @@ -2571,7 +2615,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { !Old->hasAttr<CarriesDependencyAttr>()) { Diag(New->getAttr<CarriesDependencyAttr>()->getLocation(), diag::err_carries_dependency_missing_on_first_decl) << 0/*Function*/; - Diag(Old->getFirstDeclaration()->getLocation(), + Diag(Old->getFirstDecl()->getLocation(), diag::note_carries_dependency_missing_first_decl) << 0/*Function*/; } @@ -2591,13 +2635,34 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { } if (haveIncompatibleLanguageLinkages(Old, New)) { - Diag(New->getLocation(), diag::err_different_language_linkage) << New; - Diag(Old->getLocation(), PrevDiag); - return true; + // As a special case, retain the language linkage from previous + // declarations of a friend function as an extension. + // + // This liberal interpretation of C++ [class.friend]p3 matches GCC/MSVC + // and is useful because there's otherwise no way to specify language + // linkage within class scope. + // + // Check cautiously as the friend object kind isn't yet complete. + if (New->getFriendObjectKind() != Decl::FOK_None) { + Diag(New->getLocation(), diag::ext_retained_language_linkage) << New; + Diag(Old->getLocation(), PrevDiag); + } else { + Diag(New->getLocation(), diag::err_different_language_linkage) << New; + Diag(Old->getLocation(), PrevDiag); + return true; + } } if (OldQTypeForComparison == NewQType) - return MergeCompatibleFunctionDecls(New, Old, S); + return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld); + + if ((NewQType->isDependentType() || OldQType->isDependentType()) && + New->isLocalExternDecl()) { + // It's OK if we couldn't merge types for a local function declaraton + // if either the old or new type is dependent. We'll merge the types + // when we instantiate the function. + return false; + } // Fall through for conflicting redeclarations and redefinitions. } @@ -2609,7 +2674,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { const FunctionType *OldFuncType = OldQType->getAs<FunctionType>(); const FunctionType *NewFuncType = NewQType->getAs<FunctionType>(); const FunctionProtoType *OldProto = 0; - if (isa<FunctionNoProtoType>(NewFuncType) && + if (MergeTypeWithOld && isa<FunctionNoProtoType>(NewFuncType) && (OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) { // The old declaration provided a function prototype, but the // new declaration does not. Merge in the prototype. @@ -2642,7 +2707,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { New->setParams(Params); } - return MergeCompatibleFunctionDecls(New, Old, S); + return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld); } // GNU C permits a K&R definition to follow a prototype declaration @@ -2700,9 +2765,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { diag::note_previous_declaration); } - New->setType(Context.getFunctionType(MergedReturn, ArgTypes, - OldProto->getExtProtoInfo())); - return MergeCompatibleFunctionDecls(New, Old, S); + if (MergeTypeWithOld) + New->setType(Context.getFunctionType(MergedReturn, ArgTypes, + OldProto->getExtProtoInfo())); + return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld); } // Fall through to diagnose conflicting types. @@ -2730,7 +2796,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { // local declaration will produce a hard error; if it doesn't // remain visible, a single bogus local redeclaration (which is // actually only a warning) could break all the downstream code. - if (!New->getDeclContext()->isFunctionOrMethod()) + if (!New->getLexicalDeclContext()->isFunctionOrMethod()) New->getIdentifier()->setBuiltinID(Builtin::NotBuiltin); return false; @@ -2748,13 +2814,13 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { /// known to be compatible. /// /// This routine handles the merging of attributes and other -/// properties of function declarations form the old declaration to +/// properties of function declarations from the old declaration to /// the new declaration, once we know that New is in fact a /// redeclaration of Old. /// /// \returns false bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, - Scope *S) { + Scope *S, bool MergeTypeWithOld) { // Merge the attributes mergeDeclAttributes(New, Old); @@ -2763,8 +2829,8 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, New->setPure(); // Merge "used" flag. - if (Old->isUsed(false)) - New->setUsed(); + if (Old->getMostRecentDecl()->isUsed(false)) + New->setIsUsed(); // Merge attributes from the parameters. These can mismatch with K&R // declarations. @@ -2777,9 +2843,10 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, return MergeCXXFunctionDecl(New, Old, S); // Merge the function types so the we get the composite types for the return - // and argument types. + // and argument types. Per C11 6.2.7/4, only update the type if the old decl + // was visible. QualType Merged = Context.mergeTypes(Old->getType(), New->getType()); - if (!Merged.isNull()) + if (!Merged.isNull() && MergeTypeWithOld) New->setType(Merged); return false; @@ -2813,7 +2880,8 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, /// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back /// to here in AddInitializerToDecl. We can't check them before the initializer /// is attached. -void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldWasHidden) { +void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, + bool MergeTypeWithOld) { if (New->isInvalidDecl() || Old->isInvalidDecl()) return; @@ -2839,21 +2907,48 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldWasHidden) { NewArray->getElementType())) MergedT = New->getType(); } else if (Old->getType()->isArrayType() && - New->getType()->isIncompleteArrayType()) { + New->getType()->isIncompleteArrayType()) { const ArrayType *OldArray = Context.getAsArrayType(Old->getType()); const ArrayType *NewArray = Context.getAsArrayType(New->getType()); if (Context.hasSameType(OldArray->getElementType(), NewArray->getElementType())) MergedT = Old->getType(); - } else if (New->getType()->isObjCObjectPointerType() - && Old->getType()->isObjCObjectPointerType()) { - MergedT = Context.mergeObjCGCQualifiers(New->getType(), - Old->getType()); + } else if (New->getType()->isObjCObjectPointerType() && + Old->getType()->isObjCObjectPointerType()) { + MergedT = Context.mergeObjCGCQualifiers(New->getType(), + Old->getType()); } } else { + // C 6.2.7p2: + // All declarations that refer to the same object or function shall have + // compatible type. MergedT = Context.mergeTypes(New->getType(), Old->getType()); } if (MergedT.isNull()) { + // It's OK if we couldn't merge types if either type is dependent, for a + // block-scope variable. In other cases (static data members of class + // templates, variable templates, ...), we require the types to be + // equivalent. + // FIXME: The C++ standard doesn't say anything about this. + if ((New->getType()->isDependentType() || + Old->getType()->isDependentType()) && New->isLocalVarDecl()) { + // If the old type was dependent, we can't merge with it, so the new type + // becomes dependent for now. We'll reproduce the original type when we + // instantiate the TypeSourceInfo for the variable. + if (!New->getType()->isDependentType() && MergeTypeWithOld) + New->setType(Context.DependentTy); + return; + } + + // FIXME: Even if this merging succeeds, some other non-visible declaration + // of this variable might have an incompatible type. For instance: + // + // extern int arr[]; + // void f() { extern int arr[2]; } + // void g() { extern int arr[3]; } + // + // Neither C nor C++ requires a diagnostic for this, but we should still try + // to diagnose it. Diag(New->getLocation(), diag::err_redefinition_different_type) << New->getDeclName() << New->getType() << Old->getType(); Diag(Old->getLocation(), diag::note_previous_definition); @@ -2861,11 +2956,40 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldWasHidden) { } // Don't actually update the type on the new declaration if the old - // declaration was a extern declaration in a different scope. - if (!OldWasHidden) + // declaration was an extern declaration in a different scope. + if (MergeTypeWithOld) New->setType(MergedT); } +static bool mergeTypeWithPrevious(Sema &S, VarDecl *NewVD, VarDecl *OldVD, + LookupResult &Previous) { + // C11 6.2.7p4: + // For an identifier with internal or external linkage declared + // in a scope in which a prior declaration of that identifier is + // visible, if the prior declaration specifies internal or + // external linkage, the type of the identifier at the later + // declaration becomes the composite type. + // + // If the variable isn't visible, we do not merge with its type. + if (Previous.isShadowed()) + return false; + + if (S.getLangOpts().CPlusPlus) { + // C++11 [dcl.array]p3: + // If there is a preceding declaration of the entity in the same + // scope in which the bound was specified, an omitted array bound + // is taken to be the same as in that earlier declaration. + return NewVD->isPreviousDeclInSameBlockScope() || + (!OldVD->getLexicalDeclContext()->isFunctionOrMethod() && + !NewVD->getLexicalDeclContext()->isFunctionOrMethod()); + } else { + // If the old declaration was function-local, don't merge with its + // type unless we're in the same function. + return !OldVD->getLexicalDeclContext()->isFunctionOrMethod() || + OldVD->getLexicalDeclContext() == NewVD->getLexicalDeclContext(); + } +} + /// MergeVarDecl - We just parsed a variable 'New' which has the same name /// and scope as a previous declaration 'Old'. Figure out how to resolve this /// situation, merging decls or emitting diagnostics as appropriate. @@ -2874,16 +2998,21 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldWasHidden) { /// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative /// definitions here, since the initializer hasn't been attached. /// -void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous, - bool PreviousWasHidden) { +void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { // If the new decl is already invalid, don't do any other checking. if (New->isInvalidDecl()) return; - // Verify the old decl was also a variable. + // Verify the old decl was also a variable or variable template. VarDecl *Old = 0; - if (!Previous.isSingleResult() || - !(Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) { + if (Previous.isSingleResult() && + (Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) { + if (New->getDescribedVarTemplate()) + Old = Old->getDescribedVarTemplate() ? Old : 0; + else + Old = Old->getDescribedVarTemplate() ? 0 : Old; + } + if (!Old) { Diag(New->getLocation(), diag::err_redefinition_different_kind) << New->getDeclName(); Diag(Previous.getRepresentativeDecl()->getLocation(), @@ -2918,14 +3047,15 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous, } // Merge the types. - MergeVarDeclTypes(New, Old, PreviousWasHidden); + MergeVarDeclTypes(New, Old, mergeTypeWithPrevious(*this, New, Old, Previous)); + if (New->isInvalidDecl()) return; // [dcl.stc]p8: Check if we have a non-static decl followed by a static. if (New->getStorageClass() == SC_Static && !New->isStaticDataMember() && - isExternalLinkage(Old->getLinkage())) { + Old->hasExternalFormalLinkage()) { Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName(); Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); @@ -2999,8 +3129,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous, if (getLangOpts().CPlusPlus && New->isThisDeclarationADefinition() == VarDecl::Definition && (Def = Old->getDefinition())) { - Diag(New->getLocation(), diag::err_redefinition) - << New->getDeclName(); + Diag(New->getLocation(), diag::err_redefinition) << New; Diag(Def->getLocation(), diag::note_previous_definition); New->setInvalidDecl(); return; @@ -3014,14 +3143,19 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous, } // Merge "used" flag. - if (Old->isUsed(false)) - New->setUsed(); + if (Old->getMostRecentDecl()->isUsed(false)) + New->setIsUsed(); // Keep a chain of previous declarations. - New->setPreviousDeclaration(Old); + New->setPreviousDecl(Old); // Inherit access appropriately. New->setAccess(Old->getAccess()); + + if (VarTemplateDecl *VTD = New->getDescribedVarTemplate()) { + if (New->isStaticDataMember() && New->isOutOfLine()) + VTD->setAccess(New->getAccess()); + } } /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with @@ -3031,6 +3165,30 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return ParsedFreeStandingDeclSpec(S, AS, DS, MultiTemplateParamsArg()); } +static void HandleTagNumbering(Sema &S, const TagDecl *Tag) { + if (!S.Context.getLangOpts().CPlusPlus) + return; + + if (isa<CXXRecordDecl>(Tag->getParent())) { + // If this tag is the direct child of a class, number it if + // it is anonymous. + if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl()) + return; + MangleNumberingContext &MCtx = + S.Context.getManglingNumberContext(Tag->getParent()); + S.Context.setManglingNumber(Tag, MCtx.getManglingNumber(Tag)); + return; + } + + // If this tag isn't a direct child of a class, number it if it is local. + Decl *ManglingContextDecl; + if (MangleNumberingContext *MCtx = + S.getCurrentMangleNumberContext(Tag->getDeclContext(), + ManglingContextDecl)) { + S.Context.setManglingNumber(Tag, MCtx->getManglingNumber(Tag)); + } +} + /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with /// no declarator (e.g. "struct foo;") is parsed. It also accepts template /// parameters to cope with template friend declarations. @@ -3060,7 +3218,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, } if (Tag) { - getASTContext().addUnnamedTag(Tag); + HandleTagNumbering(*this, Tag); Tag->setFreeStanding(); if (Tag->isInvalidDecl()) return Tag; @@ -3301,11 +3459,11 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef, /// This routine is recursive, injecting the names of nested anonymous /// structs/unions into the owning context and scope as well. static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S, - DeclContext *Owner, - RecordDecl *AnonRecord, - AccessSpecifier AS, - SmallVector<NamedDecl*, 2> &Chaining, - bool MSAnonStruct) { + DeclContext *Owner, + RecordDecl *AnonRecord, + AccessSpecifier AS, + SmallVectorImpl<NamedDecl *> &Chaining, + bool MSAnonStruct) { unsigned diagKind = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl : diag::err_anonymous_struct_member_redecl; @@ -3961,7 +4119,7 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, DeclarationName Name, SourceLocation Loc) { DeclContext *Cur = CurContext; - while (isa<LinkageSpecDecl>(Cur)) + while (isa<LinkageSpecDecl>(Cur) || isa<CapturedDecl>(Cur)) Cur = Cur->getParent(); // C++ [dcl.meaning]p1: @@ -3999,6 +4157,9 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, else if (isa<FunctionDecl>(Cur)) Diag(Loc, diag::err_invalid_declarator_in_function) << Name << SS.getRange(); + else if (isa<BlockDecl>(Cur)) + Diag(Loc, diag::err_invalid_declarator_in_block) + << Name << SS.getRange(); else Diag(Loc, diag::err_invalid_declarator_scope) << Name << cast<NamedDecl>(Cur) << cast<NamedDecl>(DC) << SS.getRange(); @@ -4071,7 +4232,7 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, bool EnteringContext = !D.getDeclSpec().isFriendSpecified(); DC = computeDeclContext(D.getCXXScopeSpec(), EnteringContext); - if (!DC) { + if (!DC || isa<EnumDecl>(DC)) { // If we could not compute the declaration context, it's because the // declaration context is dependent but does not refer to a class, // class template, or class template partial specialization. Complain @@ -4132,26 +4293,31 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, // See if this is a redefinition of a variable in the same scope. if (!D.getCXXScopeSpec().isSet()) { bool IsLinkageLookup = false; + bool CreateBuiltins = false; // If the declaration we're planning to build will be a function // or object with linkage, then look for another declaration with // linkage (C99 6.2.2p4-5 and C++ [basic.link]p6). + // + // If the declaration we're planning to build will be declared with + // external linkage in the translation unit, create any builtin with + // the same name. if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) /* Do nothing*/; - else if (R->isFunctionType()) { - if (CurContext->isFunctionOrMethod() || - D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) - IsLinkageLookup = true; - } else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern) - IsLinkageLookup = true; - else if (CurContext->getRedeclContext()->isTranslationUnit() && - D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) + else if (CurContext->isFunctionOrMethod() && + (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern || + R->isFunctionType())) { IsLinkageLookup = true; + CreateBuiltins = + CurContext->getEnclosingNamespaceContext()->isTranslationUnit(); + } else if (CurContext->getRedeclContext()->isTranslationUnit() && + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) + CreateBuiltins = true; if (IsLinkageLookup) Previous.clear(LookupRedeclarationWithLinkage); - LookupName(Previous, S, /* CreateBuiltins = */ IsLinkageLookup); + LookupName(Previous, S, CreateBuiltins); } else { // Something like "int foo::x;" LookupQualifiedName(Previous, DC); @@ -4223,8 +4389,8 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, TemplateParamLists, AddToScope); } else { - New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous, - TemplateParamLists); + New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous, TemplateParamLists, + AddToScope); } if (New == 0) @@ -4233,8 +4399,15 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, // If this has an identifier and is not an invalid redeclaration or // function template specialization, add it to the scope stack. if (New->getDeclName() && AddToScope && - !(D.isRedeclaration() && New->isInvalidDecl())) - PushOnScopeChains(New, S); + !(D.isRedeclaration() && New->isInvalidDecl())) { + // Only make a locally-scoped extern declaration visible if it is the first + // declaration of this entity. Qualified lookup for such an entity should + // only find this declaration if there is no visible declaration of it. + bool AddToContext = !D.isRedeclaration() || !New->isLocalExternDecl(); + PushOnScopeChains(New, S, AddToContext); + if (!AddToContext) + CurContext->addHiddenDecl(New); + } return New; } @@ -4356,21 +4529,26 @@ TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo, } /// \brief Register the given locally-scoped extern "C" declaration so -/// that it can be found later for redeclarations +/// that it can be found later for redeclarations. We include any extern "C" +/// declaration that is not visible in the translation unit here, not just +/// function-scope declarations. void -Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, - const LookupResult &Previous, - Scope *S) { - assert(ND->getLexicalDeclContext()->isFunctionOrMethod() && - "Decl is not a locally-scoped decl!"); +Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S) { + if (!getLangOpts().CPlusPlus && + ND->getLexicalDeclContext()->getRedeclContext()->isTranslationUnit()) + // Don't need to track declarations in the TU in C. + return; + // Note that we have a locally-scoped external with this name. + // FIXME: There can be multiple such declarations if they are functions marked + // __attribute__((overloadable)) declared in function scope in C. LocallyScopedExternCDecls[ND->getDeclName()] = ND; } -llvm::DenseMap<DeclarationName, NamedDecl *>::iterator -Sema::findLocallyScopedExternCDecl(DeclarationName Name) { +NamedDecl *Sema::findLocallyScopedExternCDecl(DeclarationName Name) { if (ExternalSource) { // Load locally-scoped external decls from the external source. + // FIXME: This is inefficient. Maybe add a DeclContext for extern "C" decls? SmallVector<NamedDecl *, 4> Decls; ExternalSource->ReadLocallyScopedExternCDecls(Decls); for (unsigned I = 0, N = Decls.size(); I != N; ++I) { @@ -4380,8 +4558,9 @@ Sema::findLocallyScopedExternCDecl(DeclarationName Name) { LocallyScopedExternCDecls[Decls[I]->getDeclName()] = Decls[I]; } } - - return LocallyScopedExternCDecls.find(Name); + + NamedDecl *D = LocallyScopedExternCDecls.lookup(Name); + return D ? D->getMostRecentDecl() : 0; } /// \brief Diagnose function specifiers on a declaration of an identifier that @@ -4627,17 +4806,26 @@ bool Sema::inferObjCARCLifetime(ValueDecl *decl) { static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { // 'weak' only applies to declarations with external linkage. if (WeakAttr *Attr = ND.getAttr<WeakAttr>()) { - if (ND.getLinkage() != ExternalLinkage) { + if (!ND.isExternallyVisible()) { S.Diag(Attr->getLocation(), diag::err_attribute_weak_static); ND.dropAttr<WeakAttr>(); } } if (WeakRefAttr *Attr = ND.getAttr<WeakRefAttr>()) { - if (ND.hasExternalLinkage()) { + if (ND.isExternallyVisible()) { S.Diag(Attr->getLocation(), diag::err_attribute_weakref_not_static); ND.dropAttr<WeakRefAttr>(); } } + + // 'selectany' only applies to externally visible varable declarations. + // It does not apply to functions. + if (SelectAnyAttr *Attr = ND.getAttr<SelectAnyAttr>()) { + if (isa<FunctionDecl>(ND) || !ND.isExternallyVisible()) { + S.Diag(Attr->getLocation(), diag::err_attribute_selectany_non_extern_data); + ND.dropAttr<SelectAnyAttr>(); + } + } } /// Given that we are within the definition of the given function, @@ -4672,6 +4860,32 @@ static bool isFunctionDefinitionDiscarded(Sema &S, FunctionDecl *FD) { return isC99Inline; } +/// Determine whether a variable is extern "C" prior to attaching +/// an initializer. We can't just call isExternC() here, because that +/// will also compute and cache whether the declaration is externally +/// visible, which might change when we attach the initializer. +/// +/// This can only be used if the declaration is known to not be a +/// redeclaration of an internal linkage declaration. +/// +/// For instance: +/// +/// auto x = []{}; +/// +/// Attaching the initializer here makes this declaration not externally +/// visible, because its type has internal linkage. +/// +/// FIXME: This is a hack. +template<typename T> +static bool isIncompleteDeclExternC(Sema &S, const T *D) { + if (S.getLangOpts().CPlusPlus) { + // In C++, the overloadable attribute negates the effects of extern "C". + if (!D->isInExternCContext() || D->template hasAttr<OverloadableAttr>()) + return false; + } + return D->isExternC(); +} + static bool shouldConsiderLinkage(const VarDecl *VD) { const DeclContext *DC = VD->getDeclContext()->getRedeclContext(); if (DC->isFunctionOrMethod()) @@ -4692,10 +4906,35 @@ static bool shouldConsiderLinkage(const FunctionDecl *FD) { llvm_unreachable("Unexpected context"); } -NamedDecl* +/// Adjust the \c DeclContext for a function or variable that might be a +/// function-local external declaration. +bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) { + if (!DC->isFunctionOrMethod()) + return false; + + // If this is a local extern function or variable declared within a function + // template, don't add it into the enclosing namespace scope until it is + // instantiated; it might have a dependent type right now. + if (DC->isDependentContext()) + return true; + + // C++11 [basic.link]p7: + // When a block scope declaration of an entity with linkage is not found to + // refer to some other declaration, then that entity is a member of the + // innermost enclosing namespace. + // + // Per C++11 [namespace.def]p6, the innermost enclosing namespace is a + // semantically-enclosing namespace, not a lexically-enclosing one. + while (!DC->isFileContext() && !isa<LinkageSpecDecl>(DC)) + DC = DC->getParent(); + return true; +} + +NamedDecl * Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, LookupResult &Previous, - MultiTemplateParamsArg TemplateParamLists) { + MultiTemplateParamsArg TemplateParamLists, + bool &AddToScope) { QualType R = TInfo->getType(); DeclarationName Name = GetNameForDeclarator(D).getName(); @@ -4703,6 +4942,10 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(D.getDeclSpec()); + DeclContext *OriginalDC = DC; + bool IsLocalExternDecl = SC == SC_Extern && + adjustContextForLocalExternDecl(DC); + if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16) { // OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and // half array type (unless the cl_khr_fp16 extension is enabled). @@ -4720,15 +4963,16 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, SC = SC_None; } - // C++11 [dcl.stc]p4: - // When thread_local is applied to a variable of block scope the - // storage-class-specifier static is implied if it does not appear - // explicitly. - // Core issue: 'static' is not implied if the variable is declared 'extern'. - if (SCSpec == DeclSpec::SCS_unspecified && - D.getDeclSpec().getThreadStorageClassSpec() == - DeclSpec::TSCS_thread_local && DC->isFunctionOrMethod()) - SC = SC_Static; + if (getLangOpts().CPlusPlus11 && SCSpec == DeclSpec::SCS_register && + !D.getAsmLabel() && !getSourceManager().isInSystemMacro( + D.getDeclSpec().getStorageClassSpecLoc())) { + // In C++11, the 'register' storage class specifier is deprecated. + // Suppress the warning in system macros, it's used in macros in some + // popular C system headers, such as in glibc's htonl() macro. + Diag(D.getDeclSpec().getStorageClassSpecLoc(), + diag::warn_deprecated_register) + << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); + } IdentifierInfo *II = Name.getAsIdentifierInfo(); if (!II) { @@ -4743,7 +4987,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // C99 6.9p2: The storage-class specifiers auto and register shall not // appear in the declaration specifiers in an external declaration. if (SC == SC_Auto || SC == SC_Register) { - // If this is a register variable with an asm label specified, then this // is a GNU extension. if (SC == SC_Register && D.getAsmLabel()) @@ -4753,7 +4996,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, D.setInvalidType(); } } - + if (getLangOpts().OpenCL) { // Set up the special work-group-local storage class for variables in the // OpenCL __local address space. @@ -4786,8 +5029,13 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } - bool isExplicitSpecialization = false; - VarDecl *NewVD; + bool IsExplicitSpecialization = false; + bool IsVariableTemplateSpecialization = false; + bool IsPartialSpecialization = false; + bool IsVariableTemplate = false; + VarTemplateDecl *PrevVarTemplate = 0; + VarDecl *NewVD = 0; + VarTemplateDecl *NewTemplate = 0; if (!getLangOpts().CPlusPlus) { NewVD = VarDecl::Create(Context, DC, D.getLocStart(), D.getIdentifierLoc(), II, @@ -4796,14 +5044,37 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (D.isInvalidType()) NewVD->setInvalidDecl(); } else { + bool Invalid = false; + if (DC->isRecord() && !CurContext->isRecord()) { // This is an out-of-line definition of a static data member. - if (SC == SC_Static) { + switch (SC) { + case SC_None: + break; + case SC_Static: Diag(D.getDeclSpec().getStorageClassSpecLoc(), diag::err_static_out_of_line) << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); + break; + case SC_Auto: + case SC_Register: + case SC_Extern: + // [dcl.stc] p2: The auto or register specifiers shall be applied only + // to names of variables declared in a block or to function parameters. + // [dcl.stc] p6: The extern specifier cannot be used in the declaration + // of class members + + Diag(D.getDeclSpec().getStorageClassSpecLoc(), + diag::err_storage_class_for_static_member) + << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); + break; + case SC_PrivateExtern: + llvm_unreachable("C storage class in c++!"); + case SC_OpenCLWorkGroupLocal: + llvm_unreachable("OpenCL storage class in c++!"); } - } + } + if (SC == SC_Static && CurContext->isRecord()) { if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) { if (RD->isLocalClass()) @@ -4826,28 +5097,21 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } + NamedDecl *PrevDecl = 0; + if (Previous.begin() != Previous.end()) + PrevDecl = (*Previous.begin())->getUnderlyingDecl(); + PrevVarTemplate = dyn_cast_or_null<VarTemplateDecl>(PrevDecl); + // Match up the template parameter lists with the scope specifier, then // determine whether we have a template or a template specialization. - isExplicitSpecialization = false; - bool Invalid = false; - if (TemplateParameterList *TemplateParams - = MatchTemplateParametersToScopeSpecifier( - D.getDeclSpec().getLocStart(), - D.getIdentifierLoc(), - D.getCXXScopeSpec(), - TemplateParamLists.data(), - TemplateParamLists.size(), - /*never a friend*/ false, - isExplicitSpecialization, - Invalid)) { - if (TemplateParams->size() > 0) { - // There is no such thing as a variable template. - Diag(D.getIdentifierLoc(), diag::err_template_variable) - << II - << SourceRange(TemplateParams->getTemplateLoc(), - TemplateParams->getRAngleLoc()); - return 0; - } else { + TemplateParameterList *TemplateParams = + MatchTemplateParametersToScopeSpecifier( + D.getDeclSpec().getLocStart(), D.getIdentifierLoc(), + D.getCXXScopeSpec(), TemplateParamLists, + /*never a friend*/ false, IsExplicitSpecialization, Invalid); + if (TemplateParams) { + if (!TemplateParams->size() && + D.getName().getKind() != UnqualifiedId::IK_TemplateId) { // There is an extraneous 'template<>' for this variable. Complain // about it, but allow the declaration of the variable. Diag(TemplateParams->getTemplateLoc(), @@ -4855,24 +5119,148 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, << II << SourceRange(TemplateParams->getTemplateLoc(), TemplateParams->getRAngleLoc()); + } else { + // Only C++1y supports variable templates (N3651). + Diag(D.getIdentifierLoc(), + getLangOpts().CPlusPlus1y + ? diag::warn_cxx11_compat_variable_template + : diag::ext_variable_template); + + if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { + // This is an explicit specialization or a partial specialization. + // Check that we can declare a specialization here + + IsVariableTemplateSpecialization = true; + IsPartialSpecialization = TemplateParams->size() > 0; + + } else { // if (TemplateParams->size() > 0) + // This is a template declaration. + IsVariableTemplate = true; + + // Check that we can declare a template here. + if (CheckTemplateDeclScope(S, TemplateParams)) + return 0; + + // If there is a previous declaration with the same name, check + // whether this is a valid redeclaration. + if (PrevDecl && !isDeclInScope(PrevDecl, DC, S)) + PrevDecl = PrevVarTemplate = 0; + + if (PrevVarTemplate) { + // Ensure that the template parameter lists are compatible. + if (!TemplateParameterListsAreEqual( + TemplateParams, PrevVarTemplate->getTemplateParameters(), + /*Complain=*/true, TPL_TemplateMatch)) + return 0; + } else if (PrevDecl && PrevDecl->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); + + // Just pretend that we didn't see the previous declaration. + PrevDecl = 0; + } else if (PrevDecl) { + // C++ [temp]p5: + // ... a template name declared in namespace scope or in class + // scope shall be unique in that scope. + Diag(D.getIdentifierLoc(), diag::err_redefinition_different_kind) + << Name; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + return 0; + } + + // Check the template parameter list of this declaration, possibly + // merging in the template parameter list from the previous variable + // template declaration. + if (CheckTemplateParameterList( + TemplateParams, + PrevVarTemplate ? PrevVarTemplate->getTemplateParameters() + : 0, + (D.getCXXScopeSpec().isSet() && DC && DC->isRecord() && + DC->isDependentContext()) + ? TPC_ClassTemplateMember + : TPC_VarTemplate)) + Invalid = true; + + if (D.getCXXScopeSpec().isSet()) { + // If the name of the template was qualified, we must be defining + // the template out-of-line. + if (!D.getCXXScopeSpec().isInvalid() && !Invalid && + !PrevVarTemplate) { + Diag(D.getIdentifierLoc(), diag::err_member_decl_does_not_match) + << Name << DC << /*IsDefinition*/true + << D.getCXXScopeSpec().getRange(); + Invalid = true; + } + } + } } + } else if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { + TemplateIdAnnotation *TemplateId = D.getName().TemplateId; + + // We have encountered something that the user meant to be a + // specialization (because it has explicitly-specified template + // arguments) but that was not introduced with a "template<>" (or had + // too few of them). + // FIXME: Differentiate between attempts for explicit instantiations + // (starting with "template") and the rest. + Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header) + << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc) + << FixItHint::CreateInsertion(D.getDeclSpec().getLocStart(), + "template<> "); + IsVariableTemplateSpecialization = true; } - NewVD = VarDecl::Create(Context, DC, D.getLocStart(), - D.getIdentifierLoc(), II, - R, TInfo, SC); + if (IsVariableTemplateSpecialization) { + if (!PrevVarTemplate) { + Diag(D.getIdentifierLoc(), diag::err_var_spec_no_template) + << IsPartialSpecialization; + return 0; + } + + SourceLocation TemplateKWLoc = + TemplateParamLists.size() > 0 + ? TemplateParamLists[0]->getTemplateLoc() + : SourceLocation(); + DeclResult Res = ActOnVarTemplateSpecialization( + S, PrevVarTemplate, D, TInfo, TemplateKWLoc, TemplateParams, SC, + IsPartialSpecialization); + if (Res.isInvalid()) + return 0; + NewVD = cast<VarDecl>(Res.get()); + AddToScope = false; + } else + NewVD = VarDecl::Create(Context, DC, D.getLocStart(), + D.getIdentifierLoc(), II, R, TInfo, SC); + + // If this is supposed to be a variable template, create it as such. + if (IsVariableTemplate) { + NewTemplate = + VarTemplateDecl::Create(Context, DC, D.getIdentifierLoc(), Name, + TemplateParams, NewVD, PrevVarTemplate); + NewVD->setDescribedVarTemplate(NewTemplate); + } // If this decl has an auto type in need of deduction, make a note of the // Decl so we can diagnose uses of it in its own initializer. if (D.getDeclSpec().containsPlaceholderType() && R->getContainedAutoType()) ParsingInitForAutoVars.insert(NewVD); - if (D.isInvalidType() || Invalid) + if (D.isInvalidType() || Invalid) { NewVD->setInvalidDecl(); + if (NewTemplate) + NewTemplate->setInvalidDecl(); + } SetNestedNameSpecifier(NewVD, D); - if (TemplateParamLists.size() > 0 && D.getCXXScopeSpec().isSet()) { + // FIXME: Do we need D.getCXXScopeSpec().isSet()? + if (TemplateParams && TemplateParamLists.size() > 1 && + (!IsVariableTemplateSpecialization || D.getCXXScopeSpec().isSet())) { + NewVD->setTemplateParameterListsInfo( + Context, TemplateParamLists.size() - 1, TemplateParamLists.data()); + } else if (IsVariableTemplateSpecialization || + (!TemplateParams && TemplateParamLists.size() > 0 && + (D.getCXXScopeSpec().isSet()))) { NewVD->setTemplateParameterListsInfo(Context, TemplateParamLists.size(), TemplateParamLists.data()); @@ -4885,13 +5273,29 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Set the lexical context. If the declarator has a C++ scope specifier, the // lexical context will be different from the semantic context. NewVD->setLexicalDeclContext(CurContext); + if (NewTemplate) + NewTemplate->setLexicalDeclContext(CurContext); + + if (IsLocalExternDecl) + NewVD->setLocalExternDecl(); if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) { - if (NewVD->hasLocalStorage()) - Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), - diag::err_thread_non_global) - << DeclSpec::getSpecifierName(TSCS); - else if (!Context.getTargetInfo().isTLSSupported()) + if (NewVD->hasLocalStorage()) { + // C++11 [dcl.stc]p4: + // When thread_local is applied to a variable of block scope the + // storage-class-specifier static is implied if it does not appear + // explicitly. + // Core issue: 'static' is not implied if the variable is declared + // 'extern'. + if (SCSpec == DeclSpec::SCS_unspecified && + TSCS == DeclSpec::TSCS_thread_local && + DC->isFunctionOrMethod()) + NewVD->setTSCSpec(TSCS); + else + Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), + diag::err_thread_non_global) + << DeclSpec::getSpecifierName(TSCS); + } else if (!Context.getTargetInfo().isTLSSupported()) Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), diag::err_thread_unsupported); else @@ -4918,7 +5322,12 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, } if (D.getDeclSpec().isModulePrivateSpecified()) { - if (isExplicitSpecialization) + if (IsVariableTemplateSpecialization) + Diag(NewVD->getLocation(), diag::err_module_private_specialization) + << (IsPartialSpecialization ? 1 : 0) + << FixItHint::CreateRemoval( + D.getDeclSpec().getModulePrivateSpecLoc()); + else if (IsExplicitSpecialization) Diag(NewVD->getLocation(), diag::err_module_private_specialization) << 2 << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); @@ -4927,8 +5336,11 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, << 0 << NewVD->getDeclName() << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); - else + else { NewVD->setModulePrivate(); + if (NewTemplate) + NewTemplate->setModulePrivate(); + } } // Handle attributes prior to checking for duplicates in MergeVarDecl @@ -4993,9 +5405,18 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Don't consider existing declarations that are in a different // scope and are out-of-semantic-context declarations (if the new // declaration has linkage). - FilterLookupForScope(Previous, DC, S, shouldConsiderLinkage(NewVD), - isExplicitSpecialization); - + FilterLookupForScope( + Previous, OriginalDC, S, shouldConsiderLinkage(NewVD), + IsExplicitSpecialization || IsVariableTemplateSpecialization); + + // Check whether the previous declaration is in the same block scope. This + // affects whether we merge types with it, per C++11 [dcl.array]p3. + if (getLangOpts().CPlusPlus && + NewVD->isLocalVarDecl() && NewVD->hasExternalStorage()) + NewVD->setPreviousDeclInSameBlockScope( + Previous.isSingleResult() && !Previous.isShadowed() && + isDeclInScope(Previous.getFoundDecl(), OriginalDC, S, false)); + if (!getLangOpts().CPlusPlus) { D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); } else { @@ -5019,10 +5440,18 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewVD->setInvalidDecl(); } - D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); + if (!IsVariableTemplateSpecialization) { + if (PrevVarTemplate) { + LookupResult PrevDecl(*this, GetNameForDeclarator(D), + LookupOrdinaryName, ForRedeclaration); + PrevDecl.addDecl(PrevVarTemplate->getTemplatedDecl()); + D.setRedeclaration(CheckVariableDeclaration(NewVD, PrevDecl)); + } else + D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); + } // This is an explicit specialization of a static data member. Check it. - if (isExplicitSpecialization && !NewVD->isInvalidDecl() && + if (IsExplicitSpecialization && !NewVD->isInvalidDecl() && CheckMemberSpecialization(NewVD, Previous)) NewVD->setInvalidDecl(); } @@ -5030,11 +5459,30 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, ProcessPragmaWeak(S, NewVD); checkAttributesAfterMerging(*this, *NewVD); - // If this is a locally-scoped extern C variable, update the map of - // such variables. - if (CurContext->isFunctionOrMethod() && NewVD->isExternC() && - !NewVD->isInvalidDecl()) - RegisterLocallyScopedExternCDecl(NewVD, Previous, S); + // If this is the first declaration of an extern C variable, update + // the map of such variables. + if (NewVD->isFirstDecl() && !NewVD->isInvalidDecl() && + isIncompleteDeclExternC(*this, NewVD)) + RegisterLocallyScopedExternCDecl(NewVD, S); + + if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) { + Decl *ManglingContextDecl; + if (MangleNumberingContext *MCtx = + getCurrentMangleNumberContext(NewVD->getDeclContext(), + ManglingContextDecl)) { + Context.setManglingNumber(NewVD, MCtx->getManglingNumber(NewVD)); + } + } + + // If we are providing an explicit specialization of a static variable + // template, make a note of that. + if (PrevVarTemplate && PrevVarTemplate->getInstantiatedFromMemberTemplate()) + PrevVarTemplate->setMemberSpecialization(); + + if (NewTemplate) { + ActOnDocumentableDecl(NewTemplate); + return NewTemplate; + } return NewVD; } @@ -5134,30 +5582,121 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) { CheckShadow(S, D, R); } +/// Check for conflict between this global or extern "C" declaration and +/// previous global or extern "C" declarations. This is only used in C++. template<typename T> -static bool mayConflictWithNonVisibleExternC(const T *ND) { - const DeclContext *DC = ND->getDeclContext(); - if (DC->getRedeclContext()->isTranslationUnit()) - return true; +static bool checkGlobalOrExternCConflict( + Sema &S, const T *ND, bool IsGlobal, LookupResult &Previous) { + assert(S.getLangOpts().CPlusPlus && "only C++ has extern \"C\""); + NamedDecl *Prev = S.findLocallyScopedExternCDecl(ND->getDeclName()); + + if (!Prev && IsGlobal && !isIncompleteDeclExternC(S, ND)) { + // The common case: this global doesn't conflict with any extern "C" + // declaration. + return false; + } - // We know that is the first decl we see, other than function local - // extern C ones. If this is C++ and the decl is not in a extern C context - // it cannot have C language linkage. Avoid calling isExternC in that case. - // We need to this because of code like - // - // namespace { struct bar {}; } - // auto foo = bar(); - // - // This code runs before the init of foo is set, and therefore before - // the type of foo is known. Not knowing the type we cannot know its linkage - // unless it is in an extern C block. - if (!ND->isInExternCContext()) { - const ASTContext &Context = ND->getASTContext(); - if (Context.getLangOpts().CPlusPlus) + if (Prev) { + if (!IsGlobal || isIncompleteDeclExternC(S, ND)) { + // Both the old and new declarations have C language linkage. This is a + // redeclaration. + Previous.clear(); + Previous.addDecl(Prev); + return true; + } + + // This is a global, non-extern "C" declaration, and there is a previous + // non-global extern "C" declaration. Diagnose if this is a variable + // declaration. + if (!isa<VarDecl>(ND)) return false; + } else { + // The declaration is extern "C". Check for any declaration in the + // translation unit which might conflict. + if (IsGlobal) { + // We have already performed the lookup into the translation unit. + IsGlobal = false; + for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); + I != E; ++I) { + if (isa<VarDecl>(*I)) { + Prev = *I; + break; + } + } + } else { + DeclContext::lookup_result R = + S.Context.getTranslationUnitDecl()->lookup(ND->getDeclName()); + for (DeclContext::lookup_result::iterator I = R.begin(), E = R.end(); + I != E; ++I) { + if (isa<VarDecl>(*I)) { + Prev = *I; + break; + } + // FIXME: If we have any other entity with this name in global scope, + // the declaration is ill-formed, but that is a defect: it breaks the + // 'stat' hack, for instance. Only variables can have mangled name + // clashes with extern "C" declarations, so only they deserve a + // diagnostic. + } + } + + if (!Prev) + return false; + } + + // Use the first declaration's location to ensure we point at something which + // is lexically inside an extern "C" linkage-spec. + assert(Prev && "should have found a previous declaration to diagnose"); + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Prev)) + Prev = FD->getFirstDecl(); + else + Prev = cast<VarDecl>(Prev)->getFirstDecl(); + + S.Diag(ND->getLocation(), diag::err_extern_c_global_conflict) + << IsGlobal << ND; + S.Diag(Prev->getLocation(), diag::note_extern_c_global_conflict) + << IsGlobal; + return false; +} + +/// Apply special rules for handling extern "C" declarations. Returns \c true +/// if we have found that this is a redeclaration of some prior entity. +/// +/// Per C++ [dcl.link]p6: +/// Two declarations [for a function or variable] with C language linkage +/// with the same name that appear in different scopes refer to the same +/// [entity]. An entity with C language linkage shall not be declared with +/// the same name as an entity in global scope. +template<typename T> +static bool checkForConflictWithNonVisibleExternC(Sema &S, const T *ND, + LookupResult &Previous) { + if (!S.getLangOpts().CPlusPlus) { + // In C, when declaring a global variable, look for a corresponding 'extern' + // variable declared in function scope. We don't need this in C++, because + // we find local extern decls in the surrounding file-scope DeclContext. + if (ND->getDeclContext()->getRedeclContext()->isTranslationUnit()) { + if (NamedDecl *Prev = S.findLocallyScopedExternCDecl(ND->getDeclName())) { + Previous.clear(); + Previous.addDecl(Prev); + return true; + } + } + return false; } - return ND->isExternC(); + // A declaration in the translation unit can conflict with an extern "C" + // declaration. + if (ND->getDeclContext()->getRedeclContext()->isTranslationUnit()) + return checkGlobalOrExternCConflict(S, ND, /*IsGlobal*/true, Previous); + + // An extern "C" declaration can conflict with a declaration in the + // translation unit or can be a redeclaration of an extern "C" declaration + // in another scope. + if (isIncompleteDeclExternC(S,ND)) + return checkGlobalOrExternCConflict(S, ND, /*IsGlobal*/false, Previous); + + // Neither global nor extern "C": nothing to do. + return false; } void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { @@ -5239,7 +5778,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { if (NewVD->isFileVarDecl()) Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope) << SizeRange; - else if (NewVD->getStorageClass() == SC_Static) + else if (NewVD->isStaticLocal()) Diag(NewVD->getLocation(), diag::err_vla_decl_has_static_storage) << SizeRange; else @@ -5263,11 +5802,15 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { NewVD->setTypeSourceInfo(FixedTInfo); } - if (T->isVoidType() && NewVD->isThisDeclarationADefinition()) { - Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type) - << T; - NewVD->setInvalidDecl(); - return; + if (T->isVoidType()) { + // C++98 [dcl.stc]p5: The extern specifier can be applied only to the names + // of objects and functions. + if (NewVD->isThisDeclarationADefinition() || getLangOpts().CPlusPlus) { + Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type) + << T; + NewVD->setInvalidDecl(); + return; + } } if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>()) { @@ -5303,8 +5846,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { /// Sets NewVD->isInvalidDecl() if an error was encountered. /// /// Returns true if the variable declaration is a redeclaration. -bool Sema::CheckVariableDeclaration(VarDecl *NewVD, - LookupResult &Previous) { +bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) { CheckVariableDeclarationType(NewVD); // If the decl is already known invalid, don't check it. @@ -5313,44 +5855,15 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, // If we did not find anything by this name, look for a non-visible // extern "C" declaration with the same name. - // - // Clang has a lot of problems with extern local declarations. - // The actual standards text here is: - // - // C++11 [basic.link]p6: - // The name of a function declared in block scope and the name - // of a variable declared by a block scope extern declaration - // have linkage. If there is a visible declaration of an entity - // with linkage having the same name and type, ignoring entities - // declared outside the innermost enclosing namespace scope, the - // block scope declaration declares that same entity and - // receives the linkage of the previous declaration. - // - // C11 6.2.7p4: - // For an identifier with internal or external linkage declared - // in a scope in which a prior declaration of that identifier is - // visible, if the prior declaration specifies internal or - // external linkage, the type of the identifier at the later - // declaration becomes the composite type. - // - // The most important point here is that we're not allowed to - // update our understanding of the type according to declarations - // not in scope. - bool PreviousWasHidden = false; - if (Previous.empty() && mayConflictWithNonVisibleExternC(NewVD)) { - llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos - = findLocallyScopedExternCDecl(NewVD->getDeclName()); - if (Pos != LocallyScopedExternCDecls.end()) { - Previous.addDecl(Pos->second); - PreviousWasHidden = true; - } - } + if (Previous.empty() && + checkForConflictWithNonVisibleExternC(*this, NewVD, Previous)) + Previous.setShadowed(); // Filter out any non-conflicting previous declarations. filterNonConflictingPreviousDecls(Context, NewVD, Previous); if (!Previous.empty()) { - MergeVarDecl(NewVD, Previous, PreviousWasHidden); + MergeVarDecl(NewVD, Previous); return true; } return false; @@ -5524,24 +6037,27 @@ class DifferentNameValidatorCCC : public CorrectionCandidateCallback { /// /// Returns a NamedDecl iff typo correction was performed and substituting in /// the new declaration name does not cause new errors. -static NamedDecl* DiagnoseInvalidRedeclaration( +static NamedDecl *DiagnoseInvalidRedeclaration( Sema &SemaRef, LookupResult &Previous, FunctionDecl *NewFD, - ActOnFDArgs &ExtraArgs) { - NamedDecl *Result = NULL; + ActOnFDArgs &ExtraArgs, bool IsLocalFriend, Scope *S) { DeclarationName Name = NewFD->getDeclName(); DeclContext *NewDC = NewFD->getDeclContext(); - LookupResult Prev(SemaRef, Name, NewFD->getLocation(), - Sema::LookupOrdinaryName, Sema::ForRedeclaration); SmallVector<unsigned, 1> MismatchedParams; SmallVector<std::pair<FunctionDecl *, unsigned>, 1> NearMatches; TypoCorrection Correction; - 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; + bool IsDefinition = ExtraArgs.D.isFunctionDefinition(); + unsigned DiagMsg = IsLocalFriend ? diag::err_no_matching_local_friend + : diag::err_member_decl_does_not_match; + LookupResult Prev(SemaRef, Name, NewFD->getLocation(), + IsLocalFriend ? Sema::LookupLocalFriendName + : Sema::LookupOrdinaryName, + Sema::ForRedeclaration); NewFD->setInvalidDecl(); - SemaRef.LookupQualifiedName(Prev, NewDC); + if (IsLocalFriend) + SemaRef.LookupName(Prev, S); + else + SemaRef.LookupQualifiedName(Prev, NewDC); assert(!Prev.isAmbiguous() && "Cannot have an ambiguity in previous-declaration lookup"); CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD); @@ -5561,12 +6077,10 @@ static NamedDecl* DiagnoseInvalidRedeclaration( } } // If the qualified name lookup yielded nothing, try typo correction - } else if ((Correction = SemaRef.CorrectTypo(Prev.getLookupNameInfo(), - Prev.getLookupKind(), 0, 0, - Validator, NewDC))) { - // Trap errors. - Sema::SFINAETrap Trap(SemaRef); - + } else if ((Correction = SemaRef.CorrectTypo( + Prev.getLookupNameInfo(), Prev.getLookupKind(), S, + &ExtraArgs.D.getCXXScopeSpec(), Validator, + IsLocalFriend ? 0 : NewDC))) { // Set up everything for the call to ActOnFunctionDeclarator ExtraArgs.D.SetIdentifier(Correction.getCorrectionAsIdentifierInfo(), ExtraArgs.D.getIdentifierLoc()); @@ -5582,85 +6096,85 @@ static NamedDecl* DiagnoseInvalidRedeclaration( } } bool wasRedeclaration = ExtraArgs.D.isRedeclaration(); - // 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, - Correction.getCorrectionDecl()->getDeclContext(), - NewFD->getTypeSourceInfo(), Previous, ExtraArgs.TemplateParamLists, - ExtraArgs.AddToScope); - if (Trap.hasErrorOccurred()) { - // Pretend the typo correction never occurred - ExtraArgs.D.SetIdentifier(Name.getAsIdentifierInfo(), - ExtraArgs.D.getIdentifierLoc()); - ExtraArgs.D.setRedeclaration(wasRedeclaration); - Previous.clear(); - Previous.setLookupName(Name); - Result = NULL; - } else { - for (LookupResult::iterator Func = Previous.begin(), - FuncEnd = Previous.end(); - Func != FuncEnd; ++Func) { - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func)) - NearMatches.push_back(std::make_pair(FD, 0)); - } + + NamedDecl *Result; + // Retry building the function declaration with the new previous + // declarations, and with errors suppressed. + { + // Trap errors. + Sema::SFINAETrap Trap(SemaRef); + + // TODO: Refactor ActOnFunctionDeclarator so that we can call only the + // pieces need to verify the typo-corrected C++ declaration and hopefully + // eliminate the need for the parameter pack ExtraArgs. + Result = SemaRef.ActOnFunctionDeclarator( + ExtraArgs.S, ExtraArgs.D, + Correction.getCorrectionDecl()->getDeclContext(), + NewFD->getTypeSourceInfo(), Previous, ExtraArgs.TemplateParamLists, + ExtraArgs.AddToScope); + + if (Trap.hasErrorOccurred()) + Result = 0; + } + + if (Result) { + // Determine which correction we picked. + Decl *Canonical = Result->getCanonicalDecl(); + for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); + I != E; ++I) + if ((*I)->getCanonicalDecl() == Canonical) + Correction.setCorrectionDecl(*I); + + SemaRef.diagnoseTypo( + Correction, + SemaRef.PDiag(IsLocalFriend + ? diag::err_no_matching_local_friend_suggest + : diag::err_member_decl_does_not_match_suggest) + << Name << NewDC << IsDefinition); + return Result; } - if (NearMatches.empty()) { - // Ignore the correction if it didn't yield any close FunctionDecl matches - Correction = TypoCorrection(); - } else { - DiagMsg = isFriendDecl ? diag::err_no_matching_local_friend_suggest - : diag::err_member_def_does_not_match_suggest; - } - } - - if (Correction) { - // FIXME: use Correction.getCorrectionRange() instead of computing the range - // here. This requires passing in the CXXScopeSpec to CorrectTypo which in - // turn causes the correction to fully qualify the name. If we fix - // CorrectTypo to minimally qualify then this change should be good. - SourceRange FixItLoc(NewFD->getLocation()); - CXXScopeSpec &SS = ExtraArgs.D.getCXXScopeSpec(); - if (Correction.getCorrectionSpecifier() && SS.isValid()) - FixItLoc.setBegin(SS.getBeginLoc()); - SemaRef.Diag(NewFD->getLocStart(), DiagMsg) - << Name << NewDC << Correction.getQuoted(SemaRef.getLangOpts()) - << FixItHint::CreateReplacement( - FixItLoc, Correction.getAsString(SemaRef.getLangOpts())); - } else { - SemaRef.Diag(NewFD->getLocation(), DiagMsg) - << Name << NewDC << NewFD->getLocation(); + + // Pretend the typo correction never occurred + ExtraArgs.D.SetIdentifier(Name.getAsIdentifierInfo(), + ExtraArgs.D.getIdentifierLoc()); + ExtraArgs.D.setRedeclaration(wasRedeclaration); + Previous.clear(); + Previous.setLookupName(Name); } + SemaRef.Diag(NewFD->getLocation(), DiagMsg) + << Name << NewDC << IsDefinition << NewFD->getLocation(); + bool NewFDisConst = false; if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD)) NewFDisConst = NewMD->isConst(); - for (SmallVector<std::pair<FunctionDecl *, unsigned>, 1>::iterator + for (SmallVectorImpl<std::pair<FunctionDecl *, unsigned> >::iterator NearMatch = NearMatches.begin(), NearMatchEnd = NearMatches.end(); NearMatch != NearMatchEnd; ++NearMatch) { FunctionDecl *FD = NearMatch->first; - bool FDisConst = false; - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) - FDisConst = MD->isConst(); + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); + bool FDisConst = MD && MD->isConst(); + bool IsMember = MD || !IsLocalFriend; + // FIXME: These notes are poorly worded for the local friend case. if (unsigned Idx = NearMatch->second) { ParmVarDecl *FDParam = FD->getParamDecl(Idx-1); 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.getLangOpts()); + SemaRef.Diag(Loc, IsMember ? diag::note_member_def_close_param_match + : diag::note_local_decl_close_param_match) + << Idx << FDParam->getType() + << NewFD->getParamDecl(Idx - 1)->getType(); } else if (FDisConst != NewFDisConst) { SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) << NewFDisConst << FD->getSourceRange().getEnd(); } else - SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_match); + SemaRef.Diag(FD->getLocation(), + IsMember ? diag::note_member_def_close_match + : diag::note_local_decl_close_match); } - return Result; + return 0; } static FunctionDecl::StorageClass getFunctionStorageClass(Sema &SemaRef, @@ -5778,6 +6292,15 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, SemaRef.AdjustDestructorExceptionSpec(Record, NewDD); } + // The Microsoft ABI requires that we perform the destructor body + // checks (i.e. operator delete() lookup) at every declaration, as + // any translation unit may need to emit a deleting destructor. + if (SemaRef.Context.getTargetInfo().getCXXABI().isMicrosoft() && + !Record->isDependentType() && Record->getDefinition() && + !Record->isBeingDefined()) { + SemaRef.CheckDestructor(NewDD); + } + IsVirtualOkay = true; return NewDD; @@ -5856,6 +6379,173 @@ void Sema::checkVoidParamDecl(ParmVarDecl *Param) { } } +enum OpenCLParamType { + ValidKernelParam, + PtrPtrKernelParam, + PtrKernelParam, + InvalidKernelParam, + RecordKernelParam +}; + +static OpenCLParamType getOpenCLKernelParameterType(QualType PT) { + if (PT->isPointerType()) { + QualType PointeeType = PT->getPointeeType(); + return PointeeType->isPointerType() ? PtrPtrKernelParam : PtrKernelParam; + } + + // TODO: Forbid the other integer types (size_t, ptrdiff_t...) when they can + // be used as builtin types. + + if (PT->isImageType()) + return PtrKernelParam; + + if (PT->isBooleanType()) + return InvalidKernelParam; + + if (PT->isEventT()) + return InvalidKernelParam; + + if (PT->isHalfType()) + return InvalidKernelParam; + + if (PT->isRecordType()) + return RecordKernelParam; + + return ValidKernelParam; +} + +static void checkIsValidOpenCLKernelParameter( + Sema &S, + Declarator &D, + ParmVarDecl *Param, + llvm::SmallPtrSet<const Type *, 16> &ValidTypes) { + QualType PT = Param->getType(); + + // Cache the valid types we encounter to avoid rechecking structs that are + // used again + if (ValidTypes.count(PT.getTypePtr())) + return; + + switch (getOpenCLKernelParameterType(PT)) { + case PtrPtrKernelParam: + // OpenCL v1.2 s6.9.a: + // A kernel function argument cannot be declared as a + // pointer to a pointer type. + S.Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_param); + D.setInvalidType(); + return; + + // OpenCL v1.2 s6.9.k: + // Arguments to kernel functions in a program cannot be declared with the + // built-in scalar types bool, half, size_t, ptrdiff_t, intptr_t, and + // uintptr_t or a struct and/or union that contain fields declared to be + // one of these built-in scalar types. + + case InvalidKernelParam: + // OpenCL v1.2 s6.8 n: + // A kernel function argument cannot be declared + // of event_t type. + S.Diag(Param->getLocation(), diag::err_bad_kernel_param_type) << PT; + D.setInvalidType(); + return; + + case PtrKernelParam: + case ValidKernelParam: + ValidTypes.insert(PT.getTypePtr()); + return; + + case RecordKernelParam: + break; + } + + // Track nested structs we will inspect + SmallVector<const Decl *, 4> VisitStack; + + // Track where we are in the nested structs. Items will migrate from + // VisitStack to HistoryStack as we do the DFS for bad field. + SmallVector<const FieldDecl *, 4> HistoryStack; + HistoryStack.push_back((const FieldDecl *) 0); + + const RecordDecl *PD = PT->castAs<RecordType>()->getDecl(); + VisitStack.push_back(PD); + + assert(VisitStack.back() && "First decl null?"); + + do { + const Decl *Next = VisitStack.pop_back_val(); + if (!Next) { + assert(!HistoryStack.empty()); + // Found a marker, we have gone up a level + if (const FieldDecl *Hist = HistoryStack.pop_back_val()) + ValidTypes.insert(Hist->getType().getTypePtr()); + + continue; + } + + // Adds everything except the original parameter declaration (which is not a + // field itself) to the history stack. + const RecordDecl *RD; + if (const FieldDecl *Field = dyn_cast<FieldDecl>(Next)) { + HistoryStack.push_back(Field); + RD = Field->getType()->castAs<RecordType>()->getDecl(); + } else { + RD = cast<RecordDecl>(Next); + } + + // Add a null marker so we know when we've gone back up a level + VisitStack.push_back((const Decl *) 0); + + for (RecordDecl::field_iterator I = RD->field_begin(), + E = RD->field_end(); I != E; ++I) { + const FieldDecl *FD = *I; + QualType QT = FD->getType(); + + if (ValidTypes.count(QT.getTypePtr())) + continue; + + OpenCLParamType ParamType = getOpenCLKernelParameterType(QT); + if (ParamType == ValidKernelParam) + continue; + + if (ParamType == RecordKernelParam) { + VisitStack.push_back(FD); + continue; + } + + // OpenCL v1.2 s6.9.p: + // Arguments to kernel functions that are declared to be a struct or union + // do not allow OpenCL objects to be passed as elements of the struct or + // union. + if (ParamType == PtrKernelParam || ParamType == PtrPtrKernelParam) { + S.Diag(Param->getLocation(), + diag::err_record_with_pointers_kernel_param) + << PT->isUnionType() + << PT; + } else { + S.Diag(Param->getLocation(), diag::err_bad_kernel_param_type) << PT; + } + + S.Diag(PD->getLocation(), diag::note_within_field_of_type) + << PD->getDeclName(); + + // We have an error, now let's go back up through history and show where + // the offending field came from + for (ArrayRef<const FieldDecl *>::const_iterator I = HistoryStack.begin() + 1, + E = HistoryStack.end(); I != E; ++I) { + const FieldDecl *OuterField = *I; + S.Diag(OuterField->getLocation(), diag::note_within_field_of_type) + << OuterField->getType(); + } + + S.Diag(FD->getLocation(), diag::note_illegal_field_declared_here) + << QT->isPointerType() + << QT; + D.setInvalidType(); + return; + } + } while (!VisitStack.empty()); +} + NamedDecl* Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, LookupResult &Previous, @@ -5875,25 +6565,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, diag::err_invalid_thread) << DeclSpec::getSpecifierName(TSCS); - // Do not allow returning a objc interface by-value. - if (R->getAs<FunctionType>()->getResultType()->isObjCObjectType()) { - Diag(D.getIdentifierLoc(), - diag::err_object_cannot_be_passed_returned_by_value) << 0 - << R->getAs<FunctionType>()->getResultType() - << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*"); - - QualType T = R->getAs<FunctionType>()->getResultType(); - T = Context.getObjCObjectPointerType(T); - if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(R)) { - FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - R = Context.getFunctionType(T, - ArrayRef<QualType>(FPT->arg_type_begin(), - FPT->getNumArgs()), - EPI); - } - else if (isa<FunctionNoProtoType>(R)) - R = Context.getFunctionNoProtoType(T); - } + if (D.isFirstDeclarationOfMember()) + adjustMemberFunctionCC(R, D.isStaticMember()); bool isFriend = false; FunctionTemplateDecl *FunctionTemplate = 0; @@ -5906,6 +6579,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, bool isVirtualOkay = false; + DeclContext *OriginalDC = DC; + bool IsLocalExternDecl = adjustContextForLocalExternDecl(DC); + FunctionDecl *NewFD = CreateNewFunctionDecl(*this, D, DC, R, TInfo, SC, isVirtualOkay); if (!NewFD) return 0; @@ -5913,6 +6589,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer()) NewFD->setTopLevelDeclInObjCContainer(); + // Set the lexical context. If this is a function-scope declaration, or has a + // C++ scope specifier, or is the object of a friend declaration, the lexical + // context will be different from the semantic context. + NewFD->setLexicalDeclContext(CurContext); + + if (IsLocalExternDecl) + NewFD->setLocalExternDecl(); + if (getLangOpts().CPlusPlus) { bool isInline = D.getDeclSpec().isInlineSpecified(); bool isVirtual = D.getDeclSpec().isVirtualSpecified(); @@ -5940,25 +6624,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, isFunctionTemplateSpecialization = false; if (D.isInvalidType()) NewFD->setInvalidDecl(); - - // Set the lexical context. If the declarator has a C++ - // 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().getLocStart(), - D.getIdentifierLoc(), - D.getCXXScopeSpec(), - TemplateParamLists.data(), - TemplateParamLists.size(), - isFriend, - isExplicitSpecialization, - Invalid)) { + if (TemplateParameterList *TemplateParams = + MatchTemplateParametersToScopeSpecifier( + D.getDeclSpec().getLocStart(), D.getIdentifierLoc(), + D.getCXXScopeSpec(), TemplateParamLists, isFriend, + isExplicitSpecialization, Invalid)) { if (TemplateParams->size() > 0) { // This is a function template @@ -6072,6 +6746,24 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual); } + if (getLangOpts().CPlusPlus1y && + (NewFD->isDependentContext() || + (isFriend && CurContext->isDependentContext())) && + NewFD->getResultType()->isUndeducedType()) { + // If the function template is referenced directly (for instance, as a + // member of the current instantiation), pretend it has a dependent type. + // This is not really justified by the standard, but is the only sane + // thing to do. + // FIXME: For a friend function, we have not marked the function as being + // a friend yet, so 'isDependentContext' on the FD doesn't work. + const FunctionProtoType *FPT = + NewFD->getType()->castAs<FunctionProtoType>(); + QualType Result = SubstAutoType(FPT->getResultType(), + Context.DependentTy); + NewFD->setType(Context.getFunctionType(Result, FPT->getArgTypes(), + FPT->getExtProtoInfo())); + } + // C++ [dcl.fct.spec]p3: // The inline specifier shall not appear on a block scope function // declaration. @@ -6132,12 +6824,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } if (isFriend) { - // For now, claim that the objects have no previous declaration. if (FunctionTemplate) { - FunctionTemplate->setObjectOfFriendDecl(false); + FunctionTemplate->setObjectOfFriendDecl(); FunctionTemplate->setAccess(AS_public); } - NewFD->setObjectOfFriendDecl(false); + NewFD->setObjectOfFriendDecl(); NewFD->setAccess(AS_public); } @@ -6188,17 +6879,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExceptionSpecType = EST_BasicNoexcept; NewFD->setType(Context.getFunctionType(FPT->getResultType(), - ArrayRef<QualType>(FPT->arg_type_begin(), - FPT->getNumArgs()), - EPI)); + FPT->getArgTypes(), EPI)); } } // Filter out previous declarations that don't match the scope. - FilterLookupForScope(Previous, DC, S, shouldConsiderLinkage(NewFD), + FilterLookupForScope(Previous, OriginalDC, S, shouldConsiderLinkage(NewFD), isExplicitSpecialization || isFunctionTemplateSpecialization); - + // Handle GNU asm-label extension (encoded as an attribute). if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. @@ -6282,10 +6971,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, ::new(Context) C11NoReturnAttr(D.getDeclSpec().getNoreturnSpecLoc(), Context)); - // Process the non-inheritable attributes on this declaration. - ProcessDeclAttributes(S, NewFD, D, - /*NonInheritable=*/true, /*Inheritable=*/false); - // Functions returning a variably modified type violate C99 6.7.5.2p2 // because all functions have linkage. if (!NewFD->isInvalidDecl() && @@ -6295,8 +6980,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } // Handle attributes. - ProcessDeclAttributes(S, NewFD, D, - /*NonInheritable=*/false, /*Inheritable=*/true); + ProcessDeclAttributes(S, NewFD, D); QualType RetType = NewFD->getResultType(); const CXXRecordDecl *Ret = RetType->isRecordType() ? @@ -6304,7 +6988,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (!NewFD->isInvalidDecl() && !NewFD->hasAttr<WarnUnusedResultAttr>() && Ret && Ret->hasAttr<WarnUnusedResultAttr>()) { const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD); - if (!(MD && MD->getCorrespondingMethodInClass(Ret, true))) { + // Attach the attribute to the new decl. Don't apply the attribute if it + // returns an instance of the class (e.g. assignment operators). + if (!MD || MD->getParent() != Ret) { NewFD->addAttr(new (Context) WarnUnusedResultAttr(SourceRange(), Context)); } @@ -6313,19 +6999,36 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (!getLangOpts().CPlusPlus) { // Perform semantic checking on the function declaration. bool isExplicitSpecialization=false; - if (!NewFD->isInvalidDecl()) { - if (NewFD->isMain()) - CheckMain(NewFD, D.getDeclSpec()); + if (!NewFD->isInvalidDecl() && NewFD->isMain()) + CheckMain(NewFD, D.getDeclSpec()); + + if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint()) + CheckMSVCRTEntryPoint(NewFD); + + if (!NewFD->isInvalidDecl()) D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization)); - } - // Make graceful recovery from an invalid redeclaration. else if (!Previous.empty()) - D.setRedeclaration(true); + // Make graceful recovery from an invalid redeclaration. + D.setRedeclaration(true); assert((NewFD->isInvalidDecl() || !D.isRedeclaration() || Previous.getResultKind() != LookupResult::FoundOverloaded) && "previous declaration set still overloaded"); } else { + // C++11 [replacement.functions]p3: + // The program's definitions shall not be specified as inline. + // + // N.B. We diagnose declarations instead of definitions per LWG issue 2340. + // + // Suppress the diagnostic if the function is __attribute__((used)), since + // that forces an external definition to be emitted. + if (D.getDeclSpec().isInlineSpecified() && + NewFD->isReplaceableGlobalAllocationFunction() && + !NewFD->hasAttr<UsedAttr>()) + Diag(D.getDeclSpec().getInlineSpecLoc(), + diag::ext_operator_new_delete_declared_inline) + << NewFD->getDeclName(); + // If the declarator is a template-id, translate the parser's template // argument list into our AST format. if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { @@ -6353,6 +7056,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // specialization (because it has explicitly-specified template // arguments) but that was not introduced with a "template<>" (or had // too few of them). + // FIXME: Differentiate between attempts for explicit instantiations + // (starting with "template") and the rest. Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header) << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc) << FixItHint::CreateInsertion( @@ -6406,8 +7111,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // C++ [dcl.stc]p1: // A storage-class-specifier shall not be specified in an explicit // specialization (14.7.3) - if (SC != SC_None) { - if (SC != NewFD->getTemplateSpecializationInfo()->getTemplate()->getTemplatedDecl()->getStorageClass()) + FunctionTemplateSpecializationInfo *Info = + NewFD->getTemplateSpecializationInfo(); + if (Info && SC != SC_None) { + if (SC != Info->getTemplate()->getTemplatedDecl()->getStorageClass()) Diag(NewFD->getLocation(), diag::err_explicit_specialization_inconsistent_storage_class) << SC @@ -6428,17 +7135,20 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Perform semantic checking on the function declaration. if (!isDependentClassScopeExplicitSpecialization) { + if (!NewFD->isInvalidDecl() && NewFD->isMain()) + CheckMain(NewFD, D.getDeclSpec()); + + if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint()) + CheckMSVCRTEntryPoint(NewFD); + if (NewFD->isInvalidDecl()) { // If this is a class member, mark the class invalid immediately. // This avoids some consistency errors later. if (CXXMethodDecl* methodDecl = dyn_cast<CXXMethodDecl>(NewFD)) methodDecl->getParent()->setInvalidDecl(); - } else { - if (NewFD->isMain()) - CheckMain(NewFD, D.getDeclSpec()); + } else D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization)); - } } assert((NewFD->isInvalidDecl() || !D.isRedeclaration() || @@ -6456,8 +7166,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->setAccess(Access); if (FunctionTemplate) FunctionTemplate->setAccess(Access); - - PrincipalDecl->setObjectOfFriendDecl(true); } if (NewFD->isOverloadedOperator() && !DC->isRecord() && @@ -6523,9 +7231,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // matches (e.g., those that differ only in cv-qualifiers and // whether the parameter types are references). - if (NamedDecl *Result = DiagnoseInvalidRedeclaration(*this, Previous, - NewFD, - ExtraArgs)) { + if (NamedDecl *Result = DiagnoseInvalidRedeclaration( + *this, Previous, NewFD, ExtraArgs, false, 0)) { AddToScope = ExtraArgs.AddToScope; return Result; } @@ -6534,9 +7241,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Unqualified local friend declarations are required to resolve // to something. } else if (isFriend && cast<CXXRecordDecl>(CurContext)->isLocalClass()) { - if (NamedDecl *Result = DiagnoseInvalidRedeclaration(*this, Previous, - NewFD, - ExtraArgs)) { + if (NamedDecl *Result = DiagnoseInvalidRedeclaration( + *this, Previous, NewFD, ExtraArgs, true, S)) { AddToScope = ExtraArgs.AddToScope; return Result; } @@ -6570,7 +7276,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Turn this into a variadic function with no parameters. const FunctionType *FT = NewFD->getType()->getAs<FunctionType>(); - FunctionProtoType::ExtProtoInfo EPI; + FunctionProtoType::ExtProtoInfo EPI( + Context.getDefaultCallingConvention(true, false)); EPI.Variadic = true; EPI.ExtInfo = FT->getExtInfo(); @@ -6580,18 +7287,18 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // If there's a #pragma GCC visibility in scope, and this isn't a class // member, set the visibility of this function. - if (!DC->isRecord() && NewFD->hasExternalLinkage()) + if (!DC->isRecord() && NewFD->isExternallyVisible()) AddPushedVisibilityAttribute(NewFD); // If there's a #pragma clang arc_cf_code_audited in scope, consider // marking the function. AddCFAuditedAttribute(NewFD); - // If this is a locally-scoped extern C function, update the - // map of such names. - if (CurContext->isFunctionOrMethod() && NewFD->isExternC() - && !NewFD->isInvalidDecl()) - RegisterLocallyScopedExternCDecl(NewFD, Previous, S); + // If this is the first declaration of an extern C variable, update + // the map of such variables. + if (NewFD->isFirstDecl() && !NewFD->isInvalidDecl() && + isIncompleteDeclExternC(*this, NewFD)) + RegisterLocallyScopedExternCDecl(NewFD, S); // Set this FunctionDecl's range up to the right paren. NewFD->setRangeEnd(D.getSourceRange().getEnd()); @@ -6618,27 +7325,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, diag::err_expected_kernel_void_return_type); D.setInvalidType(); } - + + llvm::SmallPtrSet<const Type *, 16> ValidTypes; for (FunctionDecl::param_iterator PI = NewFD->param_begin(), PE = NewFD->param_end(); PI != PE; ++PI) { ParmVarDecl *Param = *PI; - QualType PT = Param->getType(); - - // OpenCL v1.2 s6.9.a: - // A kernel function argument cannot be declared as a - // pointer to a pointer type. - if (PT->isPointerType() && PT->getPointeeType()->isPointerType()) { - Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_arg); - D.setInvalidType(); - } - - // OpenCL v1.2 s6.8 n: - // A kernel function argument cannot be declared - // of event_t type. - if (PT->isEventT()) { - Diag(Param->getLocation(), diag::err_event_t_kernel_arg); - D.setInvalidType(); - } + checkIsValidOpenCLKernelParameter(*this, D, Param, ValidTypes); } } @@ -6694,15 +7386,11 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, assert(!NewFD->getResultType()->isVariablyModifiedType() && "Variably modified return types are not handled here"); - // Check for a previous declaration of this name. - if (Previous.empty() && mayConflictWithNonVisibleExternC(NewFD)) { - // Since we did not find anything by this name, look for a non-visible - // extern "C" declaration with the same name. - llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos - = findLocallyScopedExternCDecl(NewFD->getDeclName()); - if (Pos != LocallyScopedExternCDecls.end()) - Previous.addDecl(Pos->second); - } + // Determine whether the type of this function should be merged with + // a previous visible declaration. This never happens for functions in C++, + // and always happens in C if the previous declaration was visible. + bool MergeTypeWithPrevious = !getLangOpts().CPlusPlus && + !Previous.isShadowed(); // Filter out any non-conflicting previous declarations. filterNonConflictingPreviousDecls(Context, NewFD, Previous); @@ -6758,6 +7446,35 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } } + // Check for a previous extern "C" declaration with this name. + if (!Redeclaration && + checkForConflictWithNonVisibleExternC(*this, NewFD, Previous)) { + filterNonConflictingPreviousDecls(Context, NewFD, Previous); + if (!Previous.empty()) { + // This is an extern "C" declaration with the same name as a previous + // declaration, and thus redeclares that entity... + Redeclaration = true; + OldDecl = Previous.getFoundDecl(); + MergeTypeWithPrevious = false; + + // ... except in the presence of __attribute__((overloadable)). + if (OldDecl->hasAttr<OverloadableAttr>()) { + if (!getLangOpts().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) { + Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing) + << Redeclaration << NewFD; + Diag(Previous.getFoundDecl()->getLocation(), + diag::note_attribute_overloadable_prev_overload); + NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(), + Context)); + } + if (IsOverload(NewFD, cast<FunctionDecl>(OldDecl), false)) { + Redeclaration = false; + OldDecl = 0; + } + } + } + } + // C++11 [dcl.constexpr]p8: // A constexpr specifier for a non-static member function that is not // a constructor declares that member function to be const. @@ -6781,9 +7498,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.TypeQuals |= Qualifiers::Const; MD->setType(Context.getFunctionType(FPT->getResultType(), - ArrayRef<QualType>(FPT->arg_type_begin(), - FPT->getNumArgs()), - EPI)); + FPT->getArgTypes(), EPI)); // Warn that we did this, if we're not performing template instantiation. // In that case, we'll have warned already when the template was defined. @@ -6802,7 +7517,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, if (Redeclaration) { // NewFD and OldDecl represent declarations that need to be // merged. - if (MergeFunctionDecl(NewFD, OldDecl, S)) { + if (MergeFunctionDecl(NewFD, OldDecl, S, MergeTypeWithPrevious)) { NewFD->setInvalidDecl(); return Redeclaration; } @@ -6850,7 +7565,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // setNonKeyFunction needs to work with the original // declaration from the class definition, and isVirtual() is // just faster in that case, so map back to that now. - oldMethod = cast<CXXMethodDecl>(oldMethod->getFirstDeclaration()); + oldMethod = cast<CXXMethodDecl>(oldMethod->getFirstDecl()); if (oldMethod->isVirtual()) { Context.setNonKeyFunction(oldMethod); } @@ -6922,7 +7637,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // during delayed parsing anyway. if (!CurContext->isRecord()) CheckCXXDefaultArguments(NewFD); - + // If this function declares a builtin function, check the type of this // declaration against the expected type for the builtin. if (unsigned BuiltinID = NewFD->getBuiltinID()) { @@ -6935,7 +7650,7 @@ 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. @@ -6998,6 +7713,13 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { FD->setConstexpr(false); } + if (getLangOpts().OpenCL) { + Diag(FD->getLocation(), diag::err_opencl_no_main) + << FD->hasAttr<OpenCLKernelAttr>(); + FD->setInvalidDecl(); + return; + } + QualType T = FD->getType(); assert(T->isFunctionType() && "function decl is not of function type"); const FunctionType* FT = T->castAs<FunctionType>(); @@ -7096,7 +7818,27 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { } if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) { - Diag(FD->getLocation(), diag::err_main_template_decl); + Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD->getName(); + FD->setInvalidDecl(); + } +} + +void Sema::CheckMSVCRTEntryPoint(FunctionDecl *FD) { + QualType T = FD->getType(); + assert(T->isFunctionType() && "function decl is not of function type"); + const FunctionType *FT = T->castAs<FunctionType>(); + + // Set an implicit return of 'zero' if the function can return some integral, + // enumeration, pointer or nullptr type. + if (FT->getResultType()->isIntegralOrEnumerationType() || + FT->getResultType()->isAnyPointerType() || + FT->getResultType()->isNullPtrType()) + // DllMain is exempt because a return value of zero means it failed. + if (FD->getName() != "DllMain") + FD->setHasImplicitReturnZero(true); + + if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) { + Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD->getName(); FD->setInvalidDecl(); } } @@ -7313,7 +8055,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, RealDecl->setInvalidDecl(); return; } - ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. @@ -7326,14 +8067,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // 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->isInitCapture() ? diag::err_init_capture_no_expression + : 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->isInitCapture() + ? diag::err_init_capture_multiple_expressions + : diag::err_auto_var_init_multiple_expressions) << VDecl->getDeclName() << VDecl->getType() << VDecl->getSourceRange(); RealDecl->setInvalidDecl(); @@ -7385,8 +8129,11 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // If this is a redeclaration, check that the type we just deduced matches // the previously declared type. - if (VarDecl *Old = VDecl->getPreviousDecl()) - MergeVarDeclTypes(VDecl, Old, /*OldWasHidden*/ false); + if (VarDecl *Old = VDecl->getPreviousDecl()) { + // We never need to merge the type, because we cannot form an incomplete + // array of auto, nor deduce such a type. + MergeVarDeclTypes(VDecl, Old, /*MergeTypeWithPrevious*/false); + } // Check the deduced type is valid for a variable declaration. CheckVariableDeclarationType(VDecl); @@ -7576,9 +8323,20 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // 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); + if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl()) { + if (VDecl->getStorageClass() == SC_Static) + CheckForConstantInitializer(Init, DclT); + // C89 is stricter than C99 for non-static aggregate types. + // C89 6.5.7p3: All the expressions [...] in an initializer list + // for an object that has aggregate or union type shall be + // constant expressions. + else if (!getLangOpts().C99 && VDecl->getType()->isAggregateType() && + isa<InitListExpr>(Init) && + !Init->isConstantInitializer(Context, false)) + Diag(Init->getExprLoc(), + diag::ext_aggregate_init_not_constant) + << Init->getSourceRange(); + } } else if (VDecl->isStaticDataMember() && VDecl->getLexicalDeclContext()->isRecord()) { // This is an in-class initialization for a static data member, e.g., @@ -7679,7 +8437,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, if (VDecl->getStorageClass() == SC_Extern && (!getLangOpts().CPlusPlus || !(Context.getBaseElementType(VDecl->getType()).isConstQualified() || - VDecl->isExternC()))) + VDecl->isExternC())) && + !isTemplateInstantiation(VDecl->getTemplateSpecializationKind())) Diag(VDecl->getLocation(), diag::warn_extern_init); // C99 6.7.8p4. All file scoped initializers need to be constant. @@ -7817,7 +8576,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, // declared with no linkage (C99 6.2.2p6), the type for the // object shall be complete. if (!Type->isDependentType() && Var->isLocalVarDecl() && - !Var->getLinkage() && !Var->isInvalidDecl() && + !Var->hasLinkage() && !Var->isInvalidDecl() && RequireCompleteType(Var->getLocation(), Type, diag::err_typecheck_decl_incomplete_type)) Var->setInvalidDecl(); @@ -7859,7 +8618,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->getPreviousDecl() == 0) + if (Var->isFirstDecl()) RequireCompleteType(Var->getLocation(), Type, diag::ext_typecheck_decl_incomplete_type); } @@ -8030,7 +8789,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { } if (var->isThisDeclarationADefinition() && - var->hasExternalLinkage() && + var->isExternallyVisible() && var->hasLinkage() && getDiagnostics().getDiagnosticLevel( diag::warn_missing_variable_declarations, var->getLocation())) { @@ -8091,10 +8850,16 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { 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(); + != DiagnosticsEngine::Ignored) { + // Warn about globals which don't have a constant initializer. Don't + // warn about globals with a non-trivial destructor because we already + // warned about them. + CXXRecordDecl *RD = baseType->getAsCXXRecordDecl(); + if (!(RD && !RD->hasTrivialDestructor()) && + !Init->isConstantInitializer(Context, baseType->isReferenceType())) + Diag(var->getLocation(), diag::warn_global_constructor) + << Init->getSourceRange(); + } if (var->isConstexpr()) { SmallVector<PartialDiagnosticAt, 8> Notes; @@ -8136,10 +8901,29 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) { if (!VD) return; + if (UsedAttr *Attr = VD->getAttr<UsedAttr>()) { + if (!Attr->isInherited() && !VD->isThisDeclarationADefinition()) { + Diag(Attr->getLocation(), diag::warn_attribute_ignored) << "used"; + VD->dropAttr<UsedAttr>(); + } + } + + if (!VD->isInvalidDecl() && + VD->isThisDeclarationADefinition() == VarDecl::TentativeDefinition) { + if (const VarDecl *Def = VD->getDefinition()) { + if (Def->hasAttr<AliasAttr>()) { + Diag(VD->getLocation(), diag::err_tentative_after_alias) + << VD->getDeclName(); + Diag(Def->getLocation(), diag::note_previous_definition); + VD->setInvalidDecl(); + } + } + } + const DeclContext *DC = VD->getDeclContext(); // If there's a #pragma GCC visibility in scope, and this isn't a class // member, set the visibility of this variable. - if (!DC->isRecord() && VD->hasExternalLinkage()) + if (!DC->isRecord() && VD->isExternallyVisible()) AddPushedVisibilityAttribute(VD); if (VD->isFileVarDecl()) @@ -8181,30 +8965,37 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) { } } -Sema::DeclGroupPtrTy -Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, - Decl **Group, unsigned NumDecls) { +Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, + ArrayRef<Decl *> Group) { SmallVector<Decl*, 8> Decls; if (DS.isTypeSpecOwned()) Decls.push_back(DS.getRepAsDecl()); - for (unsigned i = 0; i != NumDecls; ++i) - if (Decl *D = Group[i]) + DeclaratorDecl *FirstDeclaratorInGroup = 0; + for (unsigned i = 0, e = Group.size(); i != e; ++i) + if (Decl *D = Group[i]) { + if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) + if (!FirstDeclaratorInGroup) + FirstDeclaratorInGroup = DD; Decls.push_back(D); + } - if (DeclSpec::isDeclRep(DS.getTypeSpecType())) - if (const TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl())) - getASTContext().addUnnamedTag(Tag); + if (DeclSpec::isDeclRep(DS.getTypeSpecType())) { + if (TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl())) { + HandleTagNumbering(*this, Tag); + if (!Tag->hasNameForLinkage() && !Tag->hasDeclaratorForAnonDecl()) + Tag->setDeclaratorForAnonDecl(FirstDeclaratorInGroup); + } + } - return BuildDeclaratorGroup(Decls.data(), Decls.size(), - DS.containsPlaceholderType()); + return BuildDeclaratorGroup(Decls, DS.containsPlaceholderType()); } /// BuildDeclaratorGroup - convert a list of declarations into a declaration /// group, performing any necessary semantic checking. Sema::DeclGroupPtrTy -Sema::BuildDeclaratorGroup(Decl **Group, unsigned NumDecls, +Sema::BuildDeclaratorGroup(llvm::MutableArrayRef<Decl *> Group, bool TypeMayContainAuto) { // C++0x [dcl.spec.auto]p7: // If the type deduced for the template parameter U is not the same in each @@ -8213,11 +9004,11 @@ Sema::BuildDeclaratorGroup(Decl **Group, unsigned NumDecls, // between the deduced type U and the deduced type which 'auto' stands for. // auto a = 0, b = { 1, 2, 3 }; // is legal because the deduced type U is 'int' in both cases. - if (TypeMayContainAuto && NumDecls > 1) { + if (TypeMayContainAuto && Group.size() > 1) { QualType Deduced; CanQualType DeducedCanon; VarDecl *DeducedDecl = 0; - for (unsigned i = 0; i != NumDecls; ++i) { + for (unsigned i = 0, e = Group.size(); i != e; ++i) { if (VarDecl *D = dyn_cast<VarDecl>(Group[i])) { AutoType *AT = D->getType()->getContainedAutoType(); // Don't reissue diagnostics when instantiating a template. @@ -8246,18 +9037,19 @@ Sema::BuildDeclaratorGroup(Decl **Group, unsigned NumDecls, } } - ActOnDocumentableDecls(Group, NumDecls); + ActOnDocumentableDecls(Group); - return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Group, NumDecls)); + return DeclGroupPtrTy::make( + DeclGroupRef::Create(Context, Group.data(), Group.size())); } void Sema::ActOnDocumentableDecl(Decl *D) { - ActOnDocumentableDecls(&D, 1); + ActOnDocumentableDecls(D); } -void Sema::ActOnDocumentableDecls(Decl **Group, unsigned NumDecls) { +void Sema::ActOnDocumentableDecls(ArrayRef<Decl *> Group) { // Don't parse the comment if Doxygen diagnostics are ignored. - if (NumDecls == 0 || !Group[0]) + if (Group.empty() || !Group[0]) return; if (Diags.getDiagnosticLevel(diag::warn_doc_param_not_found, @@ -8265,9 +9057,9 @@ void Sema::ActOnDocumentableDecls(Decl **Group, unsigned NumDecls) { == DiagnosticsEngine::Ignored) return; - if (NumDecls >= 2) { + if (Group.size() >= 2) { // This is a decl group. Normally it will contain only declarations - // procuded from declarator list. But in case we have any definitions or + // produced from declarator list. But in case we have any definitions or // additional declaration references: // 'typedef struct S {} S;' // 'typedef struct S *S;' @@ -8275,8 +9067,7 @@ void Sema::ActOnDocumentableDecls(Decl **Group, unsigned NumDecls) { // FinalizeDeclaratorGroup adds these as separate declarations. Decl *MaybeTagDecl = Group[0]; if (MaybeTagDecl && isa<TagDecl>(MaybeTagDecl)) { - Group++; - NumDecls--; + Group = Group.slice(1); } } @@ -8291,7 +9082,7 @@ void Sema::ActOnDocumentableDecls(Decl **Group, unsigned NumDecls) { // declaration, but also comments that *follow* the declaration -- thanks to // the lookahead in the lexer: we've consumed the semicolon and looked // ahead through comments. - for (unsigned i = 0; i != NumDecls; ++i) + for (unsigned i = 0, e = Group.size(); i != e; ++i) Context.getCommentForDecl(Group[i], &PP); } } @@ -8302,6 +9093,7 @@ 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; if (DS.getStorageClassSpec() == DeclSpec::SCS_register) { @@ -8614,38 +9406,90 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD, // Don't warn for OpenCL kernels. if (FD->hasAttr<OpenCLKernelAttr>()) return false; - + bool MissingPrototype = true; 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()) + if (Prev->getLexicalDeclContext()->isFunctionOrMethod()) continue; - + MissingPrototype = !Prev->getType()->isFunctionProtoType(); if (FD->getNumParams() == 0) PossibleZeroParamPrototype = Prev; break; } - + return MissingPrototype; } -void Sema::CheckForFunctionRedefinition(FunctionDecl *FD) { +void +Sema::CheckForFunctionRedefinition(FunctionDecl *FD, + const FunctionDecl *EffectiveDefinition) { // Don't complain if we're in GNU89 mode and the previous definition // was an extern inline function. - const FunctionDecl *Definition; - if (FD->isDefined(Definition) && - !canRedefineFunction(Definition, getLangOpts())) { - if (getLangOpts().GNUMode && Definition->isInlineSpecified() && - Definition->getStorageClass() == SC_Extern) - Diag(FD->getLocation(), diag::err_redefinition_extern_inline) + const FunctionDecl *Definition = EffectiveDefinition; + if (!Definition) + if (!FD->isDefined(Definition)) + return; + + if (canRedefineFunction(Definition, getLangOpts())) + return; + + if (getLangOpts().GNUMode && Definition->isInlineSpecified() && + Definition->getStorageClass() == SC_Extern) + Diag(FD->getLocation(), diag::err_redefinition_extern_inline) << FD->getDeclName() << getLangOpts().CPlusPlus; - else - Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); - Diag(Definition->getLocation(), diag::note_previous_definition); - FD->setInvalidDecl(); + else + Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); + + Diag(Definition->getLocation(), diag::note_previous_definition); + FD->setInvalidDecl(); +} + + +static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator, + Sema &S) { + CXXRecordDecl *const LambdaClass = CallOperator->getParent(); + + LambdaScopeInfo *LSI = S.PushLambdaScope(); + LSI->CallOperator = CallOperator; + LSI->Lambda = LambdaClass; + LSI->ReturnType = CallOperator->getResultType(); + const LambdaCaptureDefault LCD = LambdaClass->getLambdaCaptureDefault(); + + if (LCD == LCD_None) + LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_None; + else if (LCD == LCD_ByCopy) + LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByval; + else if (LCD == LCD_ByRef) + LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref; + DeclarationNameInfo DNI = CallOperator->getNameInfo(); + + LSI->IntroducerRange = DNI.getCXXOperatorNameRange(); + LSI->Mutable = !CallOperator->isConst(); + + // Add the captures to the LSI so they can be noted as already + // captured within tryCaptureVar. + for (LambdaExpr::capture_iterator C = LambdaClass->captures_begin(), + CEnd = LambdaClass->captures_end(); C != CEnd; ++C) { + if (C->capturesVariable()) { + VarDecl *VD = C->getCapturedVar(); + if (VD->isInitCapture()) + S.CurrentInstantiationScope->InstantiatedLocal(VD, VD); + QualType CaptureType = VD->getType(); + const bool ByRef = C->getCaptureKind() == LCK_ByRef; + LSI->addCapture(VD, /*IsBlock*/false, ByRef, + /*RefersToEnclosingLocal*/true, C->getLocation(), + /*EllipsisLoc*/C->isPackExpansion() + ? C->getEllipsisLoc() : SourceLocation(), + CaptureType, /*Expr*/ 0); + + } else if (C->capturesThis()) { + LSI->addThisCapture(/*Nested*/ false, C->getLocation(), + S.getCurrentThisType(), /*Expr*/ 0); + } } } @@ -8661,9 +9505,24 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { FD = FunTmpl->getTemplatedDecl(); else FD = cast<FunctionDecl>(D); - - // Enter a new function scope - PushFunctionScope(); + // If we are instantiating a generic lambda call operator, push + // a LambdaScopeInfo onto the function stack. But use the information + // that's already been calculated (ActOnLambdaExpr) to prime the current + // LambdaScopeInfo. + // When the template operator is being specialized, the LambdaScopeInfo, + // has to be properly restored so that tryCaptureVariable doesn't try + // and capture any new variables. In addition when calculating potential + // captures during transformation of nested lambdas, it is necessary to + // have the LSI properly restored. + if (isGenericLambdaCallOperatorSpecialization(FD)) { + assert(ActiveTemplateInstantiations.size() && + "There should be an active template instantiation on the stack " + "when instantiating a generic lambda!"); + RebuildLambdaScopeInfo(cast<CXXMethodDecl>(D), *this); + } + else + // Enter a new function scope + PushFunctionScope(); // See if this is a redefinition. if (!FD->isLateTemplateParsed()) @@ -8695,17 +9554,19 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { const FunctionDecl *PossibleZeroParamPrototype = 0; if (ShouldWarnAboutMissingPrototype(FD, PossibleZeroParamPrototype)) { Diag(FD->getLocation(), diag::warn_missing_prototype) << FD; - + if (PossibleZeroParamPrototype) { - // We found a declaration that is not a prototype, + // We found a declaration that is not a prototype, // but that could be a zero-parameter prototype - TypeSourceInfo* TI = PossibleZeroParamPrototype->getTypeSourceInfo(); - TypeLoc TL = TI->getTypeLoc(); - if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>()) - Diag(PossibleZeroParamPrototype->getLocation(), - diag::note_declaration_not_a_prototype) - << PossibleZeroParamPrototype - << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void"); + if (TypeSourceInfo *TI = + PossibleZeroParamPrototype->getTypeSourceInfo()) { + TypeLoc TL = TI->getTypeLoc(); + if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>()) + Diag(PossibleZeroParamPrototype->getLocation(), + diag::note_declaration_not_a_prototype) + << PossibleZeroParamPrototype + << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void"); + } } } @@ -8732,8 +9593,10 @@ 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) { + for (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 @@ -8852,7 +9715,9 @@ bool Sema::canSkipFunctionBody(Decl *D) { // We cannot skip the body of a function (or function template) which is // constexpr, since we may need to evaluate its body in order to parse the // rest of the file. - return !FD->isConstexpr(); + // We cannot skip the body of a function with an undeduced return type, + // because any callers of that function need to know the type. + return !FD->isConstexpr() && !FD->getResultType()->isUndeducedType(); } Decl *Sema::ActOnSkippedFunctionBody(Decl *Decl) { @@ -8882,26 +9747,29 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (FD) { FD->setBody(Body); - if (getLangOpts().CPlusPlus1y && !FD->isInvalidDecl() && - !FD->isDependentContext()) { - if (FD->getResultType()->isUndeducedType()) { - // If the function has a deduced result type but contains no 'return' - // statements, the result type as written must be exactly 'auto', and - // the deduced result type is 'void'. - if (!FD->getResultType()->getAs<AutoType>()) { - Diag(dcl->getLocation(), diag::err_auto_fn_no_return_but_not_auto) - << FD->getResultType(); - FD->setInvalidDecl(); - } - Context.adjustDeducedFunctionResultType(FD, Context.VoidTy); + if (getLangOpts().CPlusPlus1y && !FD->isInvalidDecl() && Body && + !FD->isDependentContext() && FD->getResultType()->isUndeducedType()) { + // If the function has a deduced result type but contains no 'return' + // statements, the result type as written must be exactly 'auto', and + // the deduced result type is 'void'. + if (!FD->getResultType()->getAs<AutoType>()) { + Diag(dcl->getLocation(), diag::err_auto_fn_no_return_but_not_auto) + << FD->getResultType(); + FD->setInvalidDecl(); + } else { + // Substitute 'void' for the 'auto' in the type. + TypeLoc ResultType = FD->getTypeSourceInfo()->getTypeLoc(). + IgnoreParens().castAs<FunctionProtoTypeLoc>().getResultLoc(); + Context.adjustDeducedFunctionResultType( + FD, SubstAutoType(ResultType.getType(), Context.VoidTy)); } } // The only way to be included in UndefinedButUsed is if there is an // ODR use before the definition. Avoid the expensive map lookup if this // is the first declaration. - if (FD->getPreviousDecl() != 0 && FD->getPreviousDecl()->isUsed()) { - if (FD->getLinkage() != ExternalLinkage) + if (!FD->isFirstDecl() && FD->getPreviousDecl()->isUsed()) { + if (!FD->isExternallyVisible()) UndefinedButUsed.erase(FD); else if (FD->isInlined() && (LangOpts.CPlusPlus || !LangOpts.GNUInline) && @@ -8916,7 +9784,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, // MSVC permits the use of pure specifier (=0) on function definition, // defined at class scope, warn about this non standard construct. - if (getLangOpts().MicrosoftExt && FD->isPure()) + if (getLangOpts().MicrosoftExt && FD->isPure() && FD->isCanonicalDecl()) Diag(FD->getLocation(), diag::warn_pure_function_definition); if (!FD->isInvalidDecl()) { @@ -9014,7 +9882,6 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, PopDeclContext(); 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. @@ -9049,12 +9916,10 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, // function, see whether there was a locally-scoped declaration of // this name as a function or variable. If so, use that // (non-visible) declaration, and complain about it. - llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos - = findLocallyScopedExternCDecl(&II); - if (Pos != LocallyScopedExternCDecls.end()) { - Diag(Loc, diag::warn_use_out_of_scope_declaration) << Pos->second; - Diag(Pos->second->getLocation(), diag::note_previous_declaration); - return Pos->second; + if (NamedDecl *ExternCPrev = findLocallyScopedExternCDecl(&II)) { + Diag(Loc, diag::warn_use_out_of_scope_declaration) << ExternCPrev; + Diag(ExternCPrev->getLocation(), diag::note_previous_declaration); + return ExternCPrev; } // Extension in C99. Legal in C90, but warn about it. @@ -9073,19 +9938,9 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, 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; - } + LookupOrdinaryName, S, 0, Validator))) + diagnoseTypo(Corrected, PDiag(diag::note_function_suggestion), + /*ErrorRecovery*/false); } // Set a Declarator for the implicit definition: int foo(); @@ -9164,7 +10019,8 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { FD->getParamDecl(FormatIdx)->getType()->isObjCObjectPointerType()) fmt = "NSString"; FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context, - fmt, FormatIdx+1, + &Context.Idents.get(fmt), + FormatIdx+1, HasVAListArg ? 0 : FormatIdx+2)); } } @@ -9172,7 +10028,8 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { HasVAListArg)) { if (!FD->getAttr<FormatAttr>()) FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context, - "scanf", FormatIdx+1, + &Context.Idents.get("scanf"), + FormatIdx+1, HasVAListArg ? 0 : FormatIdx+2)); } @@ -9212,7 +10069,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { // target-specific builtins, perhaps? if (!FD->getAttr<FormatAttr>()) FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context, - "printf", 2, + &Context.Idents.get("printf"), 2, Name->isStr("vasprintf") ? 0 : 3)); } @@ -9246,7 +10103,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, NewTD->setInvalidDecl(); return NewTD; } - + if (D.getDeclSpec().isModulePrivateSpecified()) { if (CurContext->isFunctionOrMethod()) Diag(NewTD->getLocation(), diag::err_module_private_local) @@ -9497,13 +10354,10 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // for non-C++ cases. if (TemplateParameterLists.size() > 0 || (SS.isNotEmpty() && TUK != TUK_Reference)) { - if (TemplateParameterList *TemplateParams - = MatchTemplateParametersToScopeSpecifier(KWLoc, NameLoc, SS, - TemplateParameterLists.data(), - TemplateParameterLists.size(), - TUK == TUK_Friend, - isExplicitSpecialization, - Invalid)) { + if (TemplateParameterList *TemplateParams = + MatchTemplateParametersToScopeSpecifier( + KWLoc, NameLoc, SS, TemplateParameterLists, TUK == TUK_Friend, + isExplicitSpecialization, Invalid)) { if (Kind == TTK_Enum) { Diag(KWLoc, diag::err_enum_template); return 0; @@ -9572,7 +10426,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, Redecl = NotForRedeclaration; LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl); - + bool FriendSawTagOutsideEnclosingNamespace = false; if (Name && SS.isNotEmpty()) { // We have a nested-name tag ('struct foo::bar'). @@ -9665,8 +10519,11 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, while (F.hasNext()) { NamedDecl *ND = F.next(); DeclContext *DC = ND->getDeclContext()->getRedeclContext(); - if (DC->isFileContext() && !EnclosingNS->Encloses(ND->getDeclContext())) + if (DC->isFileContext() && + !EnclosingNS->Encloses(ND->getDeclContext())) { F.erase(); + FriendSawTagOutsideEnclosingNamespace = true; + } } F.done(); } @@ -9757,8 +10614,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, (getLangOpts().CPlusPlus && S->isFunctionPrototypeScope()) || ((S->getFlags() & Scope::DeclScope) == 0) || - (S->getEntity() && - ((DeclContext *)S->getEntity())->isTransparentContext())) + (S->getEntity() && S->getEntity()->isTransparentContext())) S = S->getParent(); } else { assert(TUK == TUK_Friend); @@ -9865,6 +10721,16 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, return TUK == TUK_Declaration ? PrevTagDecl : 0; } + // C++11 [class.mem]p1: + // A member shall not be declared twice in the member-specification, + // except that a nested class or member class template can be declared + // and then later defined. + if (TUK == TUK_Declaration && PrevDecl->isCXXClassMember() && + S->isDeclScope(PrevDecl)) { + Diag(NameLoc, diag::ext_member_redeclared); + Diag(PrevTagDecl->getLocation(), diag::note_previous_declaration); + } + if (!Invalid) { // If this is a use, just return the declaration we found. @@ -10155,7 +11021,7 @@ CreateNewDecl: // declaration so we always pass true to setObjectOfFriendDecl to make // the tag name visible. if (TUK == TUK_Friend) - New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty() || + New->setObjectOfFriendDecl(!FriendSawTagOutsideEnclosingNamespace && getLangOpts().MicrosoftExt); // Set the access specifier. @@ -10239,6 +11105,7 @@ Decl *Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) { void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, SourceLocation FinalLoc, + bool IsFinalSpelledSealed, SourceLocation LBraceLoc) { AdjustDeclIfTemplate(TagD); CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD); @@ -10249,8 +11116,9 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, return; if (FinalLoc.isValid()) - Record->addAttr(new (Context) FinalAttr(FinalLoc, Context)); - + Record->addAttr(new (Context) + FinalAttr(FinalLoc, Context, IsFinalSpelledSealed)); + // C++ [class]p2: // [...] The class-name is also inserted into the scope of the // class itself; this is known as the injected-class-name. For @@ -10337,8 +11205,8 @@ void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) { // Note that FieldName may be null for anonymous bitfields. ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, - QualType FieldTy, Expr *BitWidth, - bool *ZeroWidth) { + QualType FieldTy, bool IsMsStruct, + Expr *BitWidth, bool *ZeroWidth) { // Default to true; that shouldn't confuse checks for emptiness if (ZeroWidth) *ZeroWidth = true; @@ -10387,7 +11255,7 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, if (!FieldTy->isDependentType()) { uint64_t TypeSize = Context.getTypeSize(FieldTy); if (Value.getZExtValue() > TypeSize) { - if (!getLangOpts().CPlusPlus) { + if (!getLangOpts().CPlusPlus || IsMsStruct) { if (FieldName) return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size) << FieldName << (unsigned)Value.getZExtValue() @@ -10605,7 +11473,8 @@ 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) { - BitWidth = VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth).take(); + BitWidth = VerifyBitField(Loc, II, T, Record->isMsStruct(Context), BitWidth, + &ZeroWidth).take(); if (!BitWidth) { InvalidDecl = true; BitWidth = 0; @@ -10658,11 +11527,15 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, } // C++ [class.union]p1: If a union contains a member of reference type, - // the program is ill-formed. + // the program is ill-formed, except when compiling with MSVC extensions + // enabled. if (EltTy->isReferenceType()) { - Diag(NewFD->getLocation(), diag::err_union_member_of_reference_type) + Diag(NewFD->getLocation(), getLangOpts().MicrosoftExt ? + diag::ext_union_member_of_reference_type : + diag::err_union_member_of_reference_type) << NewFD->getDeclName() << EltTy; - NewFD->setInvalidDecl(); + if (!getLangOpts().MicrosoftExt) + NewFD->setInvalidDecl(); } } } @@ -10693,8 +11566,8 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { assert(FD); assert(getLangOpts().CPlusPlus && "valid check only for C++"); - if (FD->isInvalidDecl()) - return true; + if (FD->isInvalidDecl() || FD->getType()->isDependentType()) + return false; QualType EltTy = Context.getBaseElementType(FD->getType()); if (const RecordType *RT = EltTy->getAs<RecordType>()) { @@ -10782,7 +11655,7 @@ Decl *Sema::ActOnIvar(Scope *S, if (BitWidth) { // 6.7.2.1p3, 6.7.2.1p4 - BitWidth = VerifyBitField(Loc, II, T, BitWidth).take(); + BitWidth = VerifyBitField(Loc, II, T, /*IsMsStruct*/false, BitWidth).take(); if (!BitWidth) D.setInvalidType(); } else { @@ -10912,11 +11785,9 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, AllIvarDecls.push_back(Ivar); } -void Sema::ActOnFields(Scope* S, - SourceLocation RecLoc, Decl *EnclosingDecl, - llvm::ArrayRef<Decl *> Fields, - SourceLocation LBrac, SourceLocation RBrac, - AttributeList *Attr) { +void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, + ArrayRef<Decl *> Fields, SourceLocation LBrac, + SourceLocation RBrac, AttributeList *Attr) { assert(EnclosingDecl && "missing record or interface decl"); // If this is an Objective-C @implementation or category and we have @@ -10954,7 +11825,7 @@ void Sema::ActOnFields(Scope* S, SmallVector<FieldDecl*, 32> RecFields; bool ARCErrReported = false; - for (llvm::ArrayRef<Decl *>::iterator i = Fields.begin(), end = Fields.end(); + for (ArrayRef<Decl *>::iterator i = Fields.begin(), end = Fields.end(); i != end; ++i) { FieldDecl *FD = cast<FieldDecl>(*i); @@ -10999,34 +11870,38 @@ void Sema::ActOnFields(Scope* S, // 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 (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 (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) { + unsigned DiagID = 0; if (Record->isUnion()) - Diag(FD->getLocation(), diag::ext_flexible_array_union_gnu) - << FD->getDeclName(); - else + DiagID = getLangOpts().MicrosoftExt + ? diag::ext_flexible_array_union_ms + : getLangOpts().CPlusPlus + ? diag::ext_flexible_array_union_gnu + : diag::err_flexible_array_union; + else if (Fields.size() == 1) + DiagID = getLangOpts().MicrosoftExt + ? diag::ext_flexible_array_empty_aggregate_ms + : getLangOpts().CPlusPlus + ? diag::ext_flexible_array_empty_aggregate_gnu + : NumNamedMembers < 1 + ? diag::err_flexible_array_empty_aggregate + : 0; + + if (DiagID) + Diag(FD->getLocation(), DiagID) << FD->getDeclName() + << Record->getTagKind(); + // While the layout of types that contain virtual bases is not specified + // by the C++ standard, both the Itanium and Microsoft C++ ABIs place + // virtual bases after the derived members. This would make a flexible + // array member declared at the end of an object not adjacent to the end + // of the type. + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record)) + if (RD->getNumVBases() != 0) + Diag(FD->getLocation(), diag::err_flexible_array_virtual_base) + << FD->getDeclName() << Record->getTagKind(); + if (!getLangOpts().C99) 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(); - FD->setInvalidDecl(); - EnclosingDecl->setInvalidDecl(); - continue; - } + if (!FD->getType()->isDependentType() && !Context.getBaseElementType(FD->getType()).isPODType(Context)) { Diag(FD->getLocation(), diag::err_flexible_array_has_nonpod_type) @@ -11141,10 +12016,18 @@ void Sema::ActOnFields(Scope* S, I.setAccess((*I)->getAccess()); if (!CXXRecord->isDependentType()) { - // Adjust user-defined destructor exception spec. - if (getLangOpts().CPlusPlus11 && - CXXRecord->hasUserDeclaredDestructor()) - AdjustDestructorExceptionSpec(CXXRecord,CXXRecord->getDestructor()); + if (CXXRecord->hasUserDeclaredDestructor()) { + // Adjust user-defined destructor exception spec. + if (getLangOpts().CPlusPlus11) + AdjustDestructorExceptionSpec(CXXRecord, + CXXRecord->getDestructor()); + + // The Microsoft ABI requires that we perform the destructor body + // checks (i.e. operator delete() lookup) at every declaration, as + // any translation unit may need to emit a deleting destructor. + if (Context.getTargetInfo().getCXXABI().isMicrosoft()) + CheckDestructor(CXXRecord->getDestructor()); + } // Add any implicitly-declared members to this class. AddImplicitlyDeclaredMembersToClass(CXXRecord); @@ -11197,6 +12080,59 @@ void Sema::ActOnFields(Scope* S, if (Record->hasAttrs()) CheckAlignasUnderalignment(Record); + + // Check if the structure/union declaration is a type that can have zero + // size in C. For C this is a language extension, for C++ it may cause + // compatibility problems. + bool CheckForZeroSize; + if (!getLangOpts().CPlusPlus) { + CheckForZeroSize = true; + } else { + // For C++ filter out types that cannot be referenced in C code. + CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record); + CheckForZeroSize = + CXXRecord->getLexicalDeclContext()->isExternCContext() && + !CXXRecord->isDependentType() && + CXXRecord->isCLike(); + } + if (CheckForZeroSize) { + bool ZeroSize = true; + bool IsEmpty = true; + unsigned NonBitFields = 0; + for (RecordDecl::field_iterator I = Record->field_begin(), + E = Record->field_end(); + (NonBitFields == 0 || ZeroSize) && I != E; ++I) { + IsEmpty = false; + if (I->isUnnamedBitfield()) { + if (I->getBitWidthValue(Context) > 0) + ZeroSize = false; + } else { + ++NonBitFields; + QualType FieldType = I->getType(); + if (FieldType->isIncompleteType() || + !Context.getTypeSizeInChars(FieldType).isZero()) + ZeroSize = false; + } + } + + // Empty structs are an extension in C (C99 6.7.2.1p7). They are + // allowed in C++, but warn if its declaration is inside + // extern "C" block. + if (ZeroSize) { + Diag(RecLoc, getLangOpts().CPlusPlus ? + diag::warn_zero_size_struct_union_in_extern_c : + diag::warn_zero_size_struct_union_compat) + << IsEmpty << Record->isUnion() << (NonBitFields > 1); + } + + // Structs without named members are extension in C (C99 6.7.2.1p7), + // but are accepted by GCC. + if (NonBitFields == 0 && !getLangOpts().CPlusPlus) { + Diag(RecLoc, IsEmpty ? diag::ext_empty_struct_union : + diag::ext_no_named_members_in_struct_union) + << Record->isUnion(); + } + } } else { ObjCIvarDecl **ClsFields = reinterpret_cast<ObjCIvarDecl**>(RecFields.data()); @@ -11991,6 +12927,12 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc, return Import; } +void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) { + // FIXME: Should we synthesize an ImportDecl here? + PP.getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc, + /*Complain=*/true); +} + void Sema::createImplicitModuleImport(SourceLocation Loc, Module *Mod) { // Create the implicit import declaration. TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl(); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp index 4e5e4b20d774..3e583862092c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -23,6 +23,7 @@ #include "clang/Basic/CharInfo.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Lookup.h" @@ -52,7 +53,11 @@ enum AttributeDeclKind { ExpectedTLSVar, ExpectedVariableOrField, ExpectedVariableFieldOrTag, - ExpectedTypeOrNamespace + ExpectedTypeOrNamespace, + ExpectedObjectiveCInterface, + ExpectedMethodOrProperty, + ExpectedStructOrUnion, + ExpectedStructOrUnionOrClass }; //===----------------------------------------------------------------------===// @@ -204,12 +209,18 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) { return RD->getIdentifier() == &Ctx.Idents.get("__CFString"); } +static unsigned getNumAttributeArgs(const AttributeList &Attr) { + // FIXME: Include the type in the argument list. + return Attr.getNumArgs() + Attr.hasParsedType(); +} + /// \brief Check if the attribute has exactly as many args as Num. May /// output an error. static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr, - unsigned int Num) { - if (Attr.getNumArgs() != Num) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Num; + unsigned Num) { + if (getNumAttributeArgs(Attr) != Num) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << Num; return false; } @@ -220,8 +231,8 @@ static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr, /// \brief Check if the attribute has at least as many args as Num. May /// output an error. static bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &Attr, - unsigned int Num) { - if (Attr.getNumArgs() < Num) { + unsigned Num) { + if (getNumAttributeArgs(Attr) < Num) { S.Diag(Attr.getLoc(), diag::err_attribute_too_few_arguments) << Num; return false; } @@ -240,24 +251,27 @@ static bool checkFunctionOrMethodArgumentIndex(Sema &S, const Decl *D, const Expr *IdxExpr, uint64_t &Idx) { - assert(isFunctionOrMethod(D) && hasFunctionProto(D)); + assert(isFunctionOrMethod(D)); // In C++ the implicit 'this' function parameter also counts. // Parameters are counted from one. - const bool HasImplicitThisParam = isInstanceMethod(D); - const unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; - const unsigned FirstIdx = 1; + bool HP = hasFunctionProto(D); + bool HasImplicitThisParam = isInstanceMethod(D); + bool IV = HP && isFunctionOrMethodVariadic(D); + unsigned NumArgs = (HP ? getFunctionOrMethodNumArgs(D) : 0) + + HasImplicitThisParam; llvm::APSInt IdxInt; if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || !IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) { - S.Diag(AttrLoc, diag::err_attribute_argument_n_not_int) - << AttrName << AttrArgNum << IdxExpr->getSourceRange(); + std::string Name = std::string("'") + AttrName.str() + std::string("'"); + S.Diag(AttrLoc, diag::err_attribute_argument_n_type) << Name.c_str() + << AttrArgNum << AANT_ArgumentIntegerConstant << IdxExpr->getSourceRange(); return false; } Idx = IdxInt.getLimitedValue(); - if (Idx < FirstIdx || (!isFunctionOrMethodVariadic(D) && Idx > NumArgs)) { + if (Idx < 1 || (!IV && Idx > NumArgs)) { S.Diag(AttrLoc, diag::err_attribute_argument_out_of_bounds) << AttrName << AttrArgNum << IdxExpr->getSourceRange(); return false; @@ -276,6 +290,42 @@ static bool checkFunctionOrMethodArgumentIndex(Sema &S, const Decl *D, return true; } +/// \brief Check if the argument \p ArgNum of \p Attr is a ASCII string literal. +/// If not emit an error and return false. If the argument is an identifier it +/// will emit an error with a fixit hint and treat it as if it was a string +/// literal. +bool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr, + unsigned ArgNum, StringRef &Str, + SourceLocation *ArgLocation) { + // Look for identifiers. If we have one emit a hint to fix it to a literal. + if (Attr.isArgIdent(ArgNum)) { + IdentifierLoc *Loc = Attr.getArgAsIdent(ArgNum); + Diag(Loc->Loc, diag::err_attribute_argument_type) + << Attr.getName() << AANT_ArgumentString + << FixItHint::CreateInsertion(Loc->Loc, "\"") + << FixItHint::CreateInsertion(PP.getLocForEndOfToken(Loc->Loc), "\""); + Str = Loc->Ident->getName(); + if (ArgLocation) + *ArgLocation = Loc->Loc; + return true; + } + + // Now check for an actual string literal. + Expr *ArgExpr = Attr.getArgAsExpr(ArgNum); + StringLiteral *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts()); + if (ArgLocation) + *ArgLocation = ArgExpr->getLocStart(); + + if (!Literal || !Literal->isAscii()) { + Diag(ArgExpr->getLocStart(), diag::err_attribute_argument_type) + << Attr.getName() << AANT_ArgumentString; + return false; + } + + Str = Literal->getString(); + return true; +} + /// /// \brief Check if passed in Decl is a field or potentially shared global var /// \return true if the Decl is a field or potentially shared global variable @@ -414,7 +464,7 @@ static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D, int Sidx = 0, bool ParamIdxOk = false) { for(unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) { - Expr *ArgExp = Attr.getArg(Idx); + Expr *ArgExp = Attr.getArgAsExpr(Idx); if (ArgExp->isTypeDependent()) { // FIXME -- need to check this again on template instantiation @@ -424,7 +474,7 @@ static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D, if (StringLiteral *StrLit = dyn_cast<StringLiteral>(ArgExp)) { if (StrLit->getLength() == 0 || - StrLit->getString() == StringRef("*")) { + (StrLit->isAscii() && StrLit->getString() == StringRef("*"))) { // Pass empty strings to the analyzer without warnings. // Treat "*" as the universal lock. Args.push_back(ArgExp); @@ -492,11 +542,6 @@ enum ThreadAttributeDeclKind { static bool checkGuardedVarAttrCommon(Sema &S, Decl *D, const AttributeList &Attr) { - assert(!Attr.isInvalid()); - - if (!checkAttributeNumArgs(S, Attr, 0)) - return false; - // D must be either a member field or global (potentially shared) variable. if (!mayBeSharedVariable(D)) { S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) @@ -532,11 +577,6 @@ static void handlePtGuardedVarAttr(Sema &S, Decl *D, static bool checkGuardedByAttrCommon(Sema &S, Decl *D, const AttributeList &Attr, Expr* &Arg) { - assert(!Attr.isInvalid()); - - if (!checkAttributeNumArgs(S, Attr, 1)) - return false; - // D must be either a member field or global (potentially shared) variable. if (!mayBeSharedVariable(D)) { S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) @@ -579,13 +619,8 @@ static void handlePtGuardedByAttr(Sema &S, Decl *D, static bool checkLockableAttrCommon(Sema &S, Decl *D, const AttributeList &Attr) { - assert(!Attr.isInvalid()); - - if (!checkAttributeNumArgs(S, Attr, 0)) - return false; - // FIXME: Lockable structs for C code. - if (!isa<CXXRecordDecl>(D)) { + if (!isa<RecordDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) << Attr.getName() << ThreadExpectedClassOrStruct; return false; @@ -613,11 +648,6 @@ static void handleScopedLockableAttr(Sema &S, Decl *D, static void handleNoThreadSafetyAnalysis(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_thread_attribute_wrong_decl_type) << Attr.getName() << ThreadExpectedFunctionOrMethod; @@ -630,11 +660,6 @@ static void handleNoThreadSafetyAnalysis(Sema &S, Decl *D, static void handleNoSanitizeAddressAttr(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::err_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunctionOrMethod; @@ -648,11 +673,6 @@ static void handleNoSanitizeAddressAttr(Sema &S, Decl *D, static void handleNoSanitizeMemory(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::err_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunctionOrMethod; @@ -665,11 +685,6 @@ static void handleNoSanitizeMemory(Sema &S, Decl *D, static void handleNoSanitizeThread(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::err_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunctionOrMethod; @@ -682,9 +697,7 @@ static void handleNoSanitizeThread(Sema &S, Decl *D, static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, const AttributeList &Attr, - SmallVector<Expr*, 1> &Args) { - assert(!Attr.isInvalid()); - + SmallVectorImpl<Expr *> &Args) { if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) return false; @@ -743,9 +756,7 @@ static void handleAcquiredBeforeAttr(Sema &S, Decl *D, static bool checkLockFunAttrCommon(Sema &S, Decl *D, const AttributeList &Attr, - SmallVector<Expr*, 1> &Args) { - assert(!Attr.isInvalid()); - + SmallVectorImpl<Expr *> &Args) { // zero or more arguments ok // check that the attribute is applied to a function @@ -788,11 +799,37 @@ static void handleExclusiveLockFunctionAttr(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } +static void handleAssertSharedLockAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + SmallVector<Expr*, 1> Args; + if (!checkLockFunAttrCommon(S, D, Attr, Args)) + return; + + unsigned Size = Args.size(); + Expr **StartArg = Size == 0 ? 0 : &Args[0]; + D->addAttr(::new (S.Context) + AssertSharedLockAttr(Attr.getRange(), S.Context, StartArg, Size, + Attr.getAttributeSpellingListIndex())); +} + +static void handleAssertExclusiveLockAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + SmallVector<Expr*, 1> Args; + if (!checkLockFunAttrCommon(S, D, Attr, Args)) + return; + + unsigned Size = Args.size(); + Expr **StartArg = Size == 0 ? 0 : &Args[0]; + D->addAttr(::new (S.Context) + AssertExclusiveLockAttr(Attr.getRange(), S.Context, + StartArg, Size, + Attr.getAttributeSpellingListIndex())); +} + + static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const AttributeList &Attr, - SmallVector<Expr*, 2> &Args) { - assert(!Attr.isInvalid()); - + SmallVectorImpl<Expr *> &Args) { if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) return false; @@ -802,9 +839,9 @@ static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, return false; } - if (!isIntOrBool(Attr.getArg(0))) { - S.Diag(Attr.getLoc(), diag::err_attribute_first_argument_not_int_or_bool) - << Attr.getName(); + if (!isIntOrBool(Attr.getArgAsExpr(0))) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) + << Attr.getName() << 1 << AANT_ArgumentIntOrBool; return false; } @@ -820,11 +857,10 @@ static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D, if (!checkTryLockFunAttrCommon(S, D, Attr, Args)) return; - unsigned Size = Args.size(); - Expr **StartArg = Size == 0 ? 0 : &Args[0]; D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(Attr.getRange(), S.Context, - Attr.getArg(0), StartArg, Size, + Attr.getArgAsExpr(0), + Args.data(), Args.size(), Attr.getAttributeSpellingListIndex())); } @@ -834,19 +870,16 @@ static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, if (!checkTryLockFunAttrCommon(S, D, Attr, Args)) return; - unsigned Size = Args.size(); - Expr **StartArg = Size == 0 ? 0 : &Args[0]; D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(Attr.getRange(), S.Context, - Attr.getArg(0), StartArg, Size, + Attr.getArgAsExpr(0), + Args.data(), Args.size(), Attr.getAttributeSpellingListIndex())); } static bool checkLocksRequiredCommon(Sema &S, Decl *D, const AttributeList &Attr, - SmallVector<Expr*, 1> &Args) { - assert(!Attr.isInvalid()); - + SmallVectorImpl<Expr *> &Args) { if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) return false; @@ -892,8 +925,6 @@ static void handleSharedLocksRequiredAttr(Sema &S, Decl *D, static void handleUnlockFunAttr(Sema &S, Decl *D, const AttributeList &Attr) { - assert(!Attr.isInvalid()); - // zero or more arguments ok if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { @@ -915,11 +946,6 @@ static void handleUnlockFunAttr(Sema &S, Decl *D, static void handleLockReturnedAttr(Sema &S, Decl *D, const AttributeList &Attr) { - assert(!Attr.isInvalid()); - - if (!checkAttributeNumArgs(S, Attr, 1)) - return; - if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) << Attr.getName() << ThreadExpectedFunctionOrMethod; @@ -940,8 +966,6 @@ static void handleLockReturnedAttr(Sema &S, Decl *D, static void handleLocksExcludedAttr(Sema &S, Decl *D, const AttributeList &Attr) { - assert(!Attr.isInvalid()); - if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) return; @@ -964,6 +988,260 @@ static void handleLocksExcludedAttr(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } +static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) { + ConsumableAttr::ConsumedState DefaultState; + + if (Attr.isArgIdent(0)) { + IdentifierLoc *IL = Attr.getArgAsIdent(0); + if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(), + DefaultState)) { + S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) + << Attr.getName() << IL->Ident; + return; + } + } else { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) + << Attr.getName() << AANT_ArgumentIdentifier; + return; + } + + if (!isa<CXXRecordDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << + Attr.getName() << ExpectedClass; + return; + } + + D->addAttr(::new (S.Context) + ConsumableAttr(Attr.getRange(), S.Context, DefaultState, + Attr.getAttributeSpellingListIndex())); +} + +static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, + const AttributeList &Attr) { + ASTContext &CurrContext = S.getASTContext(); + QualType ThisType = MD->getThisType(CurrContext)->getPointeeType(); + + if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) { + if (!RD->hasAttr<ConsumableAttr>()) { + S.Diag(Attr.getLoc(), diag::warn_attr_on_unconsumable_class) << + RD->getNameAsString(); + + return false; + } + } + + return true; +} + + +static void handleCallableWhenAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) + return; + + if (!isa<CXXMethodDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << + Attr.getName() << ExpectedMethod; + return; + } + + if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) + return; + + SmallVector<CallableWhenAttr::ConsumedState, 3> States; + for (unsigned ArgIndex = 0; ArgIndex < Attr.getNumArgs(); ++ArgIndex) { + CallableWhenAttr::ConsumedState CallableState; + + StringRef StateString; + SourceLocation Loc; + if (!S.checkStringLiteralArgumentAttr(Attr, ArgIndex, StateString, &Loc)) + return; + + if (!CallableWhenAttr::ConvertStrToConsumedState(StateString, + CallableState)) { + S.Diag(Loc, diag::warn_attribute_type_not_supported) + << Attr.getName() << StateString; + return; + } + + States.push_back(CallableState); + } + + D->addAttr(::new (S.Context) + CallableWhenAttr(Attr.getRange(), S.Context, States.data(), + States.size(), Attr.getAttributeSpellingListIndex())); +} + + +static void handleParamTypestateAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!checkAttributeNumArgs(S, Attr, 1)) return; + + if (!isa<ParmVarDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << + Attr.getName() << ExpectedParameter; + return; + } + + ParamTypestateAttr::ConsumedState ParamState; + + if (Attr.isArgIdent(0)) { + IdentifierLoc *Ident = Attr.getArgAsIdent(0); + StringRef StateString = Ident->Ident->getName(); + + if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString, + ParamState)) { + S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) + << Attr.getName() << StateString; + return; + } + } else { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << + Attr.getName() << AANT_ArgumentIdentifier; + return; + } + + // FIXME: This check is currently being done in the analysis. It can be + // enabled here only after the parser propagates attributes at + // template specialization definition, not declaration. + //QualType ReturnType = cast<ParmVarDecl>(D)->getType(); + //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl(); + // + //if (!RD || !RD->hasAttr<ConsumableAttr>()) { + // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) << + // ReturnType.getAsString(); + // return; + //} + + D->addAttr(::new (S.Context) + ParamTypestateAttr(Attr.getRange(), S.Context, ParamState, + Attr.getAttributeSpellingListIndex())); +} + + +static void handleReturnTypestateAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!checkAttributeNumArgs(S, Attr, 1)) return; + + if (!(isa<FunctionDecl>(D) || isa<ParmVarDecl>(D))) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << + Attr.getName() << ExpectedFunctionMethodOrParameter; + return; + } + + ReturnTypestateAttr::ConsumedState ReturnState; + + if (Attr.isArgIdent(0)) { + IdentifierLoc *IL = Attr.getArgAsIdent(0); + if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(), + ReturnState)) { + S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) + << Attr.getName() << IL->Ident; + return; + } + } else { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << + Attr.getName() << AANT_ArgumentIdentifier; + return; + } + + // FIXME: This check is currently being done in the analysis. It can be + // enabled here only after the parser propagates attributes at + // template specialization definition, not declaration. + //QualType ReturnType; + // + //if (const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D)) { + // ReturnType = Param->getType(); + // + //} else if (const CXXConstructorDecl *Constructor = + // dyn_cast<CXXConstructorDecl>(D)) { + // ReturnType = Constructor->getThisType(S.getASTContext())->getPointeeType(); + // + //} else { + // + // ReturnType = cast<FunctionDecl>(D)->getCallResultType(); + //} + // + //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl(); + // + //if (!RD || !RD->hasAttr<ConsumableAttr>()) { + // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) << + // ReturnType.getAsString(); + // return; + //} + + D->addAttr(::new (S.Context) + ReturnTypestateAttr(Attr.getRange(), S.Context, ReturnState, + Attr.getAttributeSpellingListIndex())); +} + + +static void handleSetTypestateAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + + if (!isa<CXXMethodDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << + Attr.getName() << ExpectedMethod; + return; + } + + if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) + return; + + SetTypestateAttr::ConsumedState NewState; + if (Attr.isArgIdent(0)) { + IdentifierLoc *Ident = Attr.getArgAsIdent(0); + StringRef Param = Ident->Ident->getName(); + if (!SetTypestateAttr::ConvertStrToConsumedState(Param, NewState)) { + S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) + << Attr.getName() << Param; + return; + } + } else { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << + Attr.getName() << AANT_ArgumentIdentifier; + return; + } + + D->addAttr(::new (S.Context) + SetTypestateAttr(Attr.getRange(), S.Context, NewState, + Attr.getAttributeSpellingListIndex())); +} + +static void handleTestTypestateAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + + if (!isa<CXXMethodDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << + Attr.getName() << ExpectedMethod; + return; + } + + if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) + return; + + TestTypestateAttr::ConsumedState TestState; + if (Attr.isArgIdent(0)) { + IdentifierLoc *Ident = Attr.getArgAsIdent(0); + StringRef Param = Ident->Ident->getName(); + if (!TestTypestateAttr::ConvertStrToConsumedState(Param, TestState)) { + S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) + << Attr.getName() << Param; + return; + } + } else { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << + Attr.getName() << AANT_ArgumentIdentifier; + return; + } + + D->addAttr(::new (S.Context) + TestTypestateAttr(Attr.getRange(), S.Context, TestState, + Attr.getAttributeSpellingListIndex())); +} static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D, const AttributeList &Attr) { @@ -980,10 +1258,6 @@ static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D, } static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - if (TagDecl *TD = dyn_cast<TagDecl>(D)) TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context)); else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { @@ -1012,10 +1286,6 @@ static void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - // The IBAction attributes only apply to instance methods. if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) if (MD->isInstanceMethod()) { @@ -1055,10 +1325,6 @@ static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleIBOutlet(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - if (!checkIBOutletCommon(S, D, Attr)) return; @@ -1071,36 +1337,46 @@ static void handleIBOutletCollection(Sema &S, Decl *D, const AttributeList &Attr) { // The iboutletcollection attribute can have zero or one arguments. - if (Attr.getParameterName() && Attr.getNumArgs() > 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 1; return; } if (!checkIBOutletCommon(S, D, Attr)) return; - IdentifierInfo *II = Attr.getParameterName(); - if (!II) - II = &S.Context.Idents.get("NSObject"); - - ParsedType TypeRep = S.getTypeName(*II, Attr.getLoc(), - S.getScopeForContext(D->getDeclContext()->getParent())); - if (!TypeRep) { - S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; - return; + ParsedType PT; + + if (Attr.hasParsedType()) + PT = Attr.getTypeArg(); + else { + PT = S.getTypeName(S.Context.Idents.get("NSObject"), Attr.getLoc(), + S.getScopeForContext(D->getDeclContext()->getParent())); + if (!PT) { + S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << "NSObject"; + return; + } } - QualType QT = TypeRep.get(); + + TypeSourceInfo *QTLoc = 0; + QualType QT = S.GetTypeFromParser(PT, &QTLoc); + if (!QTLoc) + QTLoc = S.Context.getTrivialTypeSourceInfo(QT, Attr.getLoc()); + // Diagnose use of non-object type in iboutletcollection attribute. // FIXME. Gnu attribute extension ignores use of builtin types in // attributes. So, __attribute__((iboutletcollection(char))) will be // treated as __attribute__((iboutletcollection())). if (!QT->isObjCIdType() && !QT->isObjCObjectType()) { - S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; + S.Diag(Attr.getLoc(), + QT->isBuiltinType() ? diag::err_iboutletcollection_builtintype + : diag::err_iboutletcollection_type) << QT; return; } + D->addAttr(::new (S.Context) - IBOutletCollectionAttr(Attr.getRange(),S.Context, - QT, Attr.getParameterLoc(), + IBOutletCollectionAttr(Attr.getRange(), S.Context, QTLoc, Attr.getAttributeSpellingListIndex())); } @@ -1122,70 +1398,36 @@ static void possibleTransparentUnionPointerType(QualType &T) { static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!isFunctionOrMethod(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << "alloc_size" << ExpectedFunctionOrMethod; + << Attr.getName() << ExpectedFunctionOrMethod; return; } if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) return; - // In C++ the implicit 'this' function parameter also counts, and they are - // counted from one. - bool HasImplicitThisParam = isInstanceMethod(D); - unsigned NumArgs; - if (hasFunctionProto(D)) - NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; - else - NumArgs = 0; - SmallVector<unsigned, 8> SizeArgs; - - for (AttributeList::arg_iterator I = Attr.arg_begin(), - E = Attr.arg_end(); I!=E; ++I) { - // The argument must be an integer constant expression. - Expr *Ex = *I; - llvm::APSInt ArgNum; - if (Ex->isTypeDependent() || Ex->isValueDependent() || - !Ex->isIntegerConstantExpr(ArgNum, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) - << "alloc_size" << Ex->getSourceRange(); + for (unsigned i = 0; i < Attr.getNumArgs(); ++i) { + Expr *Ex = Attr.getArgAsExpr(i); + uint64_t Idx; + if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(), + Attr.getLoc(), i + 1, Ex, Idx)) return; - } - - uint64_t x = ArgNum.getZExtValue(); - - if (x < 1 || x > NumArgs) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) - << "alloc_size" << I.getArgNum() << Ex->getSourceRange(); - return; - } - - --x; - if (HasImplicitThisParam) { - if (x == 0) { - S.Diag(Attr.getLoc(), - diag::err_attribute_invalid_implicit_this_argument) - << "alloc_size" << Ex->getSourceRange(); - return; - } - --x; - } // check if the function argument is of an integer type - QualType T = getFunctionOrMethodArgType(D, x).getNonReferenceType(); + QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType(); if (!T->isIntegerType()) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) - << "alloc_size" << Ex->getSourceRange(); + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) + << Attr.getName() << AANT_ArgumentIntegerConstant + << Ex->getSourceRange(); return; } - - SizeArgs.push_back(x); + SizeArgs.push_back(Idx); } // check if the function returns a pointer if (!getFunctionType(D)->getResultType()->isAnyPointerType()) { S.Diag(Attr.getLoc(), diag::warn_ns_attribute_wrong_return_type) - << "alloc_size" << 0 /*function*/<< 1 /*pointer*/ << D->getSourceRange(); + << Attr.getName() << 0 /*function*/<< 1 /*pointer*/ << D->getSourceRange(); } D->addAttr(::new (S.Context) @@ -1203,47 +1445,16 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - // In C++ the implicit 'this' function parameter also counts, and they are - // counted from one. - bool HasImplicitThisParam = isInstanceMethod(D); - unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; - - // The nonnull attribute only applies to pointers. - SmallVector<unsigned, 10> NonNullArgs; - - for (AttributeList::arg_iterator I = Attr.arg_begin(), - E = Attr.arg_end(); I != E; ++I) { - // The argument must be an integer constant expression. - Expr *Ex = *I; - llvm::APSInt ArgNum(32); - if (Ex->isTypeDependent() || Ex->isValueDependent() || - !Ex->isIntegerConstantExpr(ArgNum, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) - << "nonnull" << Ex->getSourceRange(); - return; - } - - unsigned x = (unsigned) ArgNum.getZExtValue(); - - if (x < 1 || x > NumArgs) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) - << "nonnull" << I.getArgNum() << Ex->getSourceRange(); + SmallVector<unsigned, 8> NonNullArgs; + for (unsigned i = 0; i < Attr.getNumArgs(); ++i) { + Expr *Ex = Attr.getArgAsExpr(i); + uint64_t Idx; + if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(), + Attr.getLoc(), i + 1, Ex, Idx)) return; - } - - --x; - if (HasImplicitThisParam) { - if (x == 0) { - S.Diag(Attr.getLoc(), - diag::err_attribute_invalid_implicit_this_argument) - << "nonnull" << Ex->getSourceRange(); - return; - } - --x; - } // Is the function argument a pointer type? - QualType T = getFunctionOrMethodArgType(D, x).getNonReferenceType(); + QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType(); possibleTransparentUnionPointerType(T); if (!T->isAnyPointerType() && !T->isBlockPointerType()) { @@ -1253,7 +1464,7 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { continue; } - NonNullArgs.push_back(x); + NonNullArgs.push_back(Idx); } // If no arguments were specified to __attribute__((nonnull)) then all pointer @@ -1284,43 +1495,52 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { Attr.getAttributeSpellingListIndex())); } +static const char *ownershipKindToDiagName(OwnershipAttr::OwnershipKind K) { + switch (K) { + case OwnershipAttr::Holds: return "'ownership_holds'"; + case OwnershipAttr::Takes: return "'ownership_takes'"; + case OwnershipAttr::Returns: return "'ownership_returns'"; + } + llvm_unreachable("unknown ownership"); +} + static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { - // This attribute must be applied to a function declaration. - // The first argument to the attribute must be a string, - // the name of the resource, for example "malloc". - // The following arguments must be argument indexes, the arguments must be - // of integer type for Returns, otherwise of pointer type. + // This attribute must be applied to a function declaration. The first + // argument to the attribute must be an identifier, the name of the resource, + // for example: malloc. The following arguments must be argument indexes, the + // arguments must be of integer type for Returns, otherwise of pointer type. // The difference between Holds and Takes is that a pointer may still be used - // after being held. free() should be __attribute((ownership_takes)), whereas + // after being held. free() should be __attribute((ownership_takes)), whereas // a list append function may well be __attribute((ownership_holds)). - if (!AL.getParameterName()) { - S.Diag(AL.getLoc(), diag::err_attribute_argument_n_not_string) - << AL.getName()->getName() << 1; + if (!AL.isArgIdent(0)) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) + << AL.getName() << 1 << AANT_ArgumentIdentifier; return; } + // Figure out our Kind, and check arguments while we're at it. OwnershipAttr::OwnershipKind K; switch (AL.getKind()) { case AttributeList::AT_ownership_takes: K = OwnershipAttr::Takes; - if (AL.getNumArgs() < 1) { - S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; + if (AL.getNumArgs() < 2) { + S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << 2; return; } break; case AttributeList::AT_ownership_holds: K = OwnershipAttr::Holds; - if (AL.getNumArgs() < 1) { - S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; + if (AL.getNumArgs() < 2) { + S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << 2; return; } break; case AttributeList::AT_ownership_returns: K = OwnershipAttr::Returns; - if (AL.getNumArgs() > 1) { - S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) - << AL.getNumArgs() + 1; + + if (AL.getNumArgs() > 2) { + S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << 1; return; } break; @@ -1335,107 +1555,58 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { return; } - // In C++ the implicit 'this' function parameter also counts, and they are - // counted from one. - bool HasImplicitThisParam = isInstanceMethod(D); - unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; - - StringRef Module = AL.getParameterName()->getName(); + StringRef Module = AL.getArgAsIdent(0)->Ident->getName(); // Normalize the argument, __foo__ becomes foo. if (Module.startswith("__") && Module.endswith("__")) Module = Module.substr(2, Module.size() - 4); - SmallVector<unsigned, 10> OwnershipArgs; - - for (AttributeList::arg_iterator I = AL.arg_begin(), E = AL.arg_end(); I != E; - ++I) { - - Expr *IdxExpr = *I; - llvm::APSInt ArgNum(32); - if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() - || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) { - S.Diag(AL.getLoc(), diag::err_attribute_argument_not_int) - << AL.getName()->getName() << IdxExpr->getSourceRange(); - continue; - } - - unsigned x = (unsigned) ArgNum.getZExtValue(); - - if (x > NumArgs || x < 1) { - S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) - << AL.getName()->getName() << x << IdxExpr->getSourceRange(); - continue; - } - --x; - if (HasImplicitThisParam) { - if (x == 0) { - S.Diag(AL.getLoc(), diag::err_attribute_invalid_implicit_this_argument) - << "ownership" << IdxExpr->getSourceRange(); - return; - } - --x; - } + SmallVector<unsigned, 8> OwnershipArgs; + for (unsigned i = 1; i < AL.getNumArgs(); ++i) { + Expr *Ex = AL.getArgAsExpr(i); + uint64_t Idx; + if (!checkFunctionOrMethodArgumentIndex(S, D, AL.getName()->getName(), + AL.getLoc(), i, Ex, Idx)) + return; + // Is the function argument a pointer type? + QualType T = getFunctionOrMethodArgType(D, Idx); + int Err = -1; // No error switch (K) { - case OwnershipAttr::Takes: - case OwnershipAttr::Holds: { - // Is the function argument a pointer type? - QualType T = getFunctionOrMethodArgType(D, x); - if (!T->isAnyPointerType() && !T->isBlockPointerType()) { - // FIXME: Should also highlight argument in decl. - S.Diag(AL.getLoc(), diag::err_ownership_type) - << ((K==OwnershipAttr::Takes)?"ownership_takes":"ownership_holds") - << "pointer" - << IdxExpr->getSourceRange(); - continue; - } - break; + case OwnershipAttr::Takes: + case OwnershipAttr::Holds: + if (!T->isAnyPointerType() && !T->isBlockPointerType()) + Err = 0; + break; + case OwnershipAttr::Returns: + if (!T->isIntegerType()) + Err = 1; + break; } - case OwnershipAttr::Returns: { - if (AL.getNumArgs() > 1) { - // Is the function argument an integer type? - Expr *IdxExpr = AL.getArg(0); - llvm::APSInt ArgNum(32); - if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() - || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) { - S.Diag(AL.getLoc(), diag::err_ownership_type) - << "ownership_returns" << "integer" - << IdxExpr->getSourceRange(); - return; - } - } - break; + if (-1 != Err) { + S.Diag(AL.getLoc(), diag::err_ownership_type) << AL.getName() << Err + << Ex->getSourceRange(); + return; } - } // switch // Check we don't have a conflict with another ownership attribute. for (specific_attr_iterator<OwnershipAttr> - i = D->specific_attr_begin<OwnershipAttr>(), - e = D->specific_attr_end<OwnershipAttr>(); - i != e; ++i) { - if ((*i)->getOwnKind() != K) { - for (const unsigned *I = (*i)->args_begin(), *E = (*i)->args_end(); - I!=E; ++I) { - if (x == *I) { - S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) - << AL.getName()->getName() << "ownership_*"; - } - } + i = D->specific_attr_begin<OwnershipAttr>(), + e = D->specific_attr_end<OwnershipAttr>(); i != e; ++i) { + if ((*i)->getOwnKind() != K && (*i)->args_end() != + std::find((*i)->args_begin(), (*i)->args_end(), Idx)) { + S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) + << AL.getName() << ownershipKindToDiagName((*i)->getOwnKind()); + return; } } - OwnershipArgs.push_back(x); + OwnershipArgs.push_back(Idx); } unsigned* start = OwnershipArgs.data(); unsigned size = OwnershipArgs.size(); llvm::array_pod_sort(start, start + size); - if (K != OwnershipAttr::Returns && OwnershipArgs.empty()) { - S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; - return; - } - D->addAttr(::new (S.Context) OwnershipAttr(AL.getLoc(), S.Context, K, Module, start, size, AL.getAttributeSpellingListIndex())); @@ -1444,7 +1615,8 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Check the attribute arguments. if (Attr.getNumArgs() > 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 1; return; } @@ -1495,21 +1667,15 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { // static ((alias ("y"), weakref)). // Should we? How to check that weakref is before or after alias? - if (Attr.getNumArgs() == 1) { - Expr *Arg = Attr.getArg(0); - Arg = Arg->IgnoreParenCasts(); - StringLiteral *Str = dyn_cast<StringLiteral>(Arg); - - if (!Str || !Str->isAscii()) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) - << "weakref" << 1; - return; - } + // FIXME: it would be good for us to keep the WeakRefAttr as-written instead + // of transforming it into an AliasAttr. The WeakRefAttr never uses the + // StringRef parameter it was given anyway. + StringRef Str; + if (Attr.getNumArgs() && S.checkStringLiteralArgumentAttr(Attr, 0, Str)) // GCC will accept anything as the argument of weakref. Should we // check for an existing decl? - D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, - Str->getString())); - } + D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str, + Attr.getAttributeSpellingListIndex())); D->addAttr(::new (S.Context) WeakRefAttr(Attr.getRange(), S.Context, @@ -1517,21 +1683,9 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; - return; - } - - Expr *Arg = Attr.getArg(0); - Arg = Arg->IgnoreParenCasts(); - StringLiteral *Str = dyn_cast<StringLiteral>(Arg); - - if (!Str || !Str->isAscii()) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) - << "alias" << 1; + StringRef Str; + if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str)) return; - } if (S.Context.getTargetInfo().getTriple().isOSDarwin()) { S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin); @@ -1540,16 +1694,11 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { // FIXME: check if target symbol exists in current file - D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, - Str->getString(), + D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str, Attr.getAttributeSpellingListIndex())); } static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // Check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - if (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunctionOrMethod; @@ -1562,10 +1711,6 @@ static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // Check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; @@ -1583,10 +1728,6 @@ static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // Check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; @@ -1604,10 +1745,6 @@ static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // Check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; @@ -1621,12 +1758,6 @@ static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) { static void handleAlwaysInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // Check the attribute arguments. - if (Attr.hasParameterOrArguments()) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; - return; - } - if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; @@ -1640,21 +1771,11 @@ static void handleAlwaysInlineAttr(Sema &S, Decl *D, static void handleTLSModelAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // Check the attribute arguments. - if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; - return; - } - - Expr *Arg = Attr.getArg(0); - Arg = Arg->IgnoreParenCasts(); - StringLiteral *Str = dyn_cast<StringLiteral>(Arg); - + StringRef Model; + SourceLocation LiteralLoc; // Check that it is a string. - if (!Str) { - S.Diag(Attr.getLoc(), diag::err_attribute_not_string) << "tls_model"; + if (!S.checkStringLiteralArgumentAttr(Attr, 0, Model, &LiteralLoc)) return; - } if (!isa<VarDecl>(D) || !cast<VarDecl>(D)->getTLSKind()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) @@ -1663,10 +1784,9 @@ static void handleTLSModelAttr(Sema &S, Decl *D, } // Check that the value. - StringRef Model = Str->getString(); if (Model != "global-dynamic" && Model != "local-dynamic" && Model != "initial-exec" && Model != "local-exec") { - S.Diag(Attr.getLoc(), diag::err_attr_tlsmodel_arg); + S.Diag(LiteralLoc, diag::err_attr_tlsmodel_arg); return; } @@ -1676,12 +1796,6 @@ static void handleTLSModelAttr(Sema &S, Decl *D, } static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // Check the attribute arguments. - if (Attr.hasParameterOrArguments()) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; - return; - } - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { QualType RetTy = FD->getResultType(); if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) { @@ -1696,17 +1810,12 @@ static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleMayAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - D->addAttr(::new (S.Context) MayAliasAttr(Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); } static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { - assert(!Attr.isInvalid()); if (isa<VarDecl>(D)) D->addAttr(::new (S.Context) NoCommonAttr(Attr.getRange(), S.Context, @@ -1717,7 +1826,11 @@ static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { - assert(!Attr.isInvalid()); + if (S.LangOpts.CPlusPlus) { + S.Diag(Attr.getLoc(), diag::err_common_not_supported_cplusplus); + return; + } + if (isa<VarDecl>(D)) D->addAttr(::new (S.Context) CommonAttr(Attr.getRange(), S.Context, @@ -1744,8 +1857,7 @@ static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) { } bool Sema::CheckNoReturnAttr(const AttributeList &attr) { - if (attr.hasParameterOrArguments()) { - Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (!checkAttributeNumArgs(*this, attr, 0)) { attr.setInvalid(); return true; } @@ -1758,10 +1870,6 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, // The checking path for 'noreturn' and 'analyzer_noreturn' are different // because 'analyzer_noreturn' does not impact the type. - - if(!checkAttributeNumArgs(S, Attr, 0)) - return; - if (!isFunctionOrMethod(D) && !isa<BlockDecl>(D)) { ValueDecl *VD = dyn_cast<ValueDecl>(D); if (VD == 0 || (!VD->getType()->isBlockPointerType() @@ -1881,12 +1989,6 @@ static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D, } static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (Attr.hasParameterOrArguments()) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; - return; - } - if (!isa<VarDecl>(D) && !isa<ObjCIvarDecl>(D) && !isFunctionOrMethod(D) && !isa<TypeDecl>(D) && !isa<LabelDecl>(D) && !isa<FieldDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) @@ -1901,12 +2003,6 @@ static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { static void handleReturnsTwiceAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (Attr.hasParameterOrArguments()) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; - return; - } - if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; @@ -1919,14 +2015,8 @@ static void handleReturnsTwiceAttr(Sema &S, Decl *D, } static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (Attr.hasParameterOrArguments()) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; - return; - } - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - if (VD->hasLocalStorage() || VD->hasExternalStorage()) { + if (VD->hasLocalStorage()) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used"; return; } @@ -1950,12 +2040,13 @@ static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { int priority = 65535; // FIXME: Do not hardcode such constants. if (Attr.getNumArgs() > 0) { - Expr *E = Attr.getArg(0); + Expr *E = Attr.getArgAsExpr(0); llvm::APSInt Idx(32); if (E->isTypeDependent() || E->isValueDependent() || !E->isIntegerConstantExpr(Idx, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) - << "constructor" << 1 << E->getSourceRange(); + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) + << Attr.getName() << 1 << AANT_ArgumentIntegerConstant + << E->getSourceRange(); return; } priority = Idx.getZExtValue(); @@ -1981,12 +2072,13 @@ static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { int priority = 65535; // FIXME: Do not hardcode such constants. if (Attr.getNumArgs() > 0) { - Expr *E = Attr.getArg(0); + Expr *E = Attr.getArgAsExpr(0); llvm::APSInt Idx(32); if (E->isTypeDependent() || E->isValueDependent() || !E->isIntegerConstantExpr(Idx, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) - << "destructor" << 1 << E->getSourceRange(); + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) + << Attr.getName() << 1 << AANT_ArgumentIntegerConstant + << E->getSourceRange(); return; } priority = Idx.getZExtValue(); @@ -2004,8 +2096,8 @@ static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { } template <typename AttrTy> -static void handleAttrWithMessage(Sema &S, Decl *D, const AttributeList &Attr, - const char *Name) { +static void handleAttrWithMessage(Sema &S, Decl *D, + const AttributeList &Attr) { unsigned NumArgs = Attr.getNumArgs(); if (NumArgs > 1) { S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; @@ -2014,15 +2106,8 @@ static void handleAttrWithMessage(Sema &S, Decl *D, const AttributeList &Attr, // Handle the case where the attribute has a text message. StringRef Str; - if (NumArgs == 1) { - StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0)); - if (!SE) { - S.Diag(Attr.getArg(0)->getLocStart(), diag::err_attribute_not_string) - << Name; - return; - } - Str = SE->getString(); - } + if (NumArgs == 1 && !S.checkStringLiteralArgumentAttr(Attr, 0, Str)) + return; D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str, Attr.getAttributeSpellingListIndex())); @@ -2030,12 +2115,6 @@ static void handleAttrWithMessage(Sema &S, Decl *D, const AttributeList &Attr, static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D, const AttributeList &Attr) { - unsigned NumArgs = Attr.getNumArgs(); - if (NumArgs > 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0; - return; - } - D->addAttr(::new (S.Context) ArcWeakrefUnavailableAttr(Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); @@ -2044,13 +2123,8 @@ static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D, 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; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedObjectiveCInterface; return; } @@ -2066,12 +2140,6 @@ static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D, 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, Attr.getAttributeSpellingListIndex())); @@ -2261,13 +2329,15 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, static void handleAvailabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { - IdentifierInfo *Platform = Attr.getParameterName(); - SourceLocation PlatformLoc = Attr.getParameterLoc(); + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + IdentifierLoc *Platform = Attr.getArgAsIdent(0); unsigned Index = Attr.getAttributeSpellingListIndex(); - if (AvailabilityAttr::getPrettyPlatformName(Platform->getName()).empty()) - S.Diag(PlatformLoc, diag::warn_availability_unknown_platform) - << Platform; + IdentifierInfo *II = Platform->Ident; + if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty()) + S.Diag(Platform->Loc, diag::warn_availability_unknown_platform) + << Platform->Ident; NamedDecl *ND = dyn_cast<NamedDecl>(D); if (!ND) { @@ -2280,13 +2350,11 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted(); bool IsUnavailable = Attr.getUnavailableLoc().isValid(); StringRef Str; - const StringLiteral *SE = - dyn_cast_or_null<const StringLiteral>(Attr.getMessageExpr()); - if (SE) + if (const StringLiteral *SE = + dyn_cast_or_null<StringLiteral>(Attr.getMessageExpr())) Str = SE->getString(); - AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(), - Platform, + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(), II, Introduced.Version, Deprecated.Version, Obsoleted.Version, @@ -2346,41 +2414,25 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr, return; } - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 1)) + // Check that the argument is a string literal. + StringRef TypeStr; + SourceLocation LiteralLoc; + if (!S.checkStringLiteralArgumentAttr(Attr, 0, TypeStr, &LiteralLoc)) return; - Expr *Arg = Attr.getArg(0); - Arg = Arg->IgnoreParenCasts(); - StringLiteral *Str = dyn_cast<StringLiteral>(Arg); - - if (!Str || !Str->isAscii()) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) - << (isTypeVisibility ? "type_visibility" : "visibility") << 1; + VisibilityAttr::VisibilityType type; + if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) { + S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported) + << Attr.getName() << TypeStr; return; } - - StringRef TypeStr = Str->getString(); - VisibilityAttr::VisibilityType type; - if (TypeStr == "default") + // Complain about attempts to use protected visibility on targets + // (like Darwin) that don't support it. + if (type == VisibilityAttr::Protected && + !S.Context.getTargetInfo().hasProtectedVisibility()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_protected_visibility); type = VisibilityAttr::Default; - else if (TypeStr == "hidden") - type = VisibilityAttr::Hidden; - else if (TypeStr == "internal") - type = VisibilityAttr::Hidden; // FIXME - 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; } unsigned Index = Attr.getAttributeSpellingListIndex(); @@ -2405,39 +2457,21 @@ static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl, return; } - if (Attr.getNumArgs() != 0 || !Attr.getParameterName()) { - if (!Attr.getParameterName() && Attr.getNumArgs() == 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) - << "objc_method_family" << 1; - } else { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; - } - Attr.setInvalid(); + if (!Attr.isArgIdent(0)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) + << Attr.getName() << 1 << AANT_ArgumentIdentifier; return; } - StringRef param = Attr.getParameterName()->getName(); - ObjCMethodFamilyAttr::FamilyKind family; - if (param == "none") - family = ObjCMethodFamilyAttr::OMF_None; - else if (param == "alloc") - family = ObjCMethodFamilyAttr::OMF_alloc; - else if (param == "copy") - family = ObjCMethodFamilyAttr::OMF_copy; - else if (param == "init") - family = ObjCMethodFamilyAttr::OMF_init; - else if (param == "mutableCopy") - family = ObjCMethodFamilyAttr::OMF_mutableCopy; - else if (param == "new") - family = ObjCMethodFamilyAttr::OMF_new; - else { - // Just warn and ignore it. This is future-proof against new - // families being used in system headers. - S.Diag(Attr.getParameterLoc(), diag::warn_unknown_method_family); + IdentifierLoc *IL = Attr.getArgAsIdent(0); + ObjCMethodFamilyAttr::FamilyKind F; + if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) { + S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << Attr.getName() + << IL->Ident; return; } - if (family == ObjCMethodFamilyAttr::OMF_init && + if (F == ObjCMethodFamilyAttr::OMF_init && !method->getResultType()->isObjCObjectPointerType()) { S.Diag(method->getLocation(), diag::err_init_method_bad_return_type) << method->getResultType(); @@ -2446,17 +2480,15 @@ static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl, } method->addAttr(new (S.Context) ObjCMethodFamilyAttr(Attr.getRange(), - S.Context, family)); + S.Context, F)); } static void handleObjCExceptionAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D); if (OCI == 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface); + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedObjectiveCInterface; return; } @@ -2466,10 +2498,6 @@ static void handleObjCExceptionAttr(Sema &S, Decl *D, } static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) { - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; - return; - } if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { QualType T = TD->getUnderlyingType(); if (!T->isCARCBridgableType()) { @@ -2500,11 +2528,6 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) { static void handleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; - return; - } - if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function); return; @@ -2516,23 +2539,17 @@ handleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (!Attr.getParameterName()) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) - << "blocks" << 1; - return; - } - - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + if (!Attr.isArgIdent(0)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) + << Attr.getName() << 1 << AANT_ArgumentIdentifier; return; } + IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident; BlocksAttr::BlockType type; - if (Attr.getParameterName()->isStr("byref")) - type = BlocksAttr::ByRef; - else { + if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) { S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) - << "blocks" << Attr.getParameterName(); + << Attr.getName() << II; return; } @@ -2550,12 +2567,13 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) { unsigned sentinel = 0; if (Attr.getNumArgs() > 0) { - Expr *E = Attr.getArg(0); + Expr *E = Attr.getArgAsExpr(0); llvm::APSInt Idx(32); if (E->isTypeDependent() || E->isValueDependent() || !E->isIntegerConstantExpr(Idx, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) - << "sentinel" << 1 << E->getSourceRange(); + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) + << Attr.getName() << 1 << AANT_ArgumentIntegerConstant + << E->getSourceRange(); return; } @@ -2570,12 +2588,13 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) { unsigned nullPos = 0; if (Attr.getNumArgs() > 1) { - Expr *E = Attr.getArg(1); + Expr *E = Attr.getArgAsExpr(1); llvm::APSInt Idx(32); if (E->isTypeDependent() || E->isValueDependent() || !E->isIntegerConstantExpr(Idx, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) - << "sentinel" << 2 << E->getSourceRange(); + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) + << Attr.getName() << 2 << AANT_ArgumentIntegerConstant + << E->getSourceRange(); return; } nullPos = Idx.getZExtValue(); @@ -2635,11 +2654,14 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) { Attr.getAttributeSpellingListIndex())); } -static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; +static void handleWarnUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) + RD->addAttr(::new (S.Context) WarnUnusedAttr(Attr.getRange(), S.Context)); + else + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); +} +static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) { if (!isFunction(D) && !isa<ObjCMethodDecl>(D) && !isa<CXXRecordDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunctionMethodOrClass; @@ -2664,12 +2686,6 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) } static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (Attr.hasParameterOrArguments()) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; - return; - } - if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) { if (isa<CXXRecordDecl>(D)) { D->addAttr(::new (S.Context) WeakAttr(Attr.getRange(), S.Context)); @@ -2688,18 +2704,12 @@ static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - - // weak_import only applies to variable & function declarations. bool isDef = false; if (!D->canBeWeakImported(isDef)) { if (isDef) - S.Diag(Attr.getLoc(), - diag::warn_attribute_weak_import_invalid_on_definition) - << "weak_import" << 2 /*variable and function*/; + S.Diag(Attr.getLoc(), diag::warn_attribute_invalid_on_definition) + << "weak_import"; else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) || (S.Context.getTargetInfo().getTriple().isOSDarwin() && (isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) { @@ -2719,20 +2729,15 @@ static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Handles reqd_work_group_size and work_group_size_hint. static void handleWorkGroupSize(Sema &S, Decl *D, const AttributeList &Attr) { - assert(Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize - || Attr.getKind() == AttributeList::AT_WorkGroupSizeHint); - - // Attribute has 3 arguments. - if (!checkAttributeNumArgs(S, Attr, 3)) return; - unsigned WGSize[3]; for (unsigned i = 0; i < 3; ++i) { - Expr *E = Attr.getArg(i); + Expr *E = Attr.getArgAsExpr(i); llvm::APSInt ArgNum(32); if (E->isTypeDependent() || E->isValueDependent() || !E->isIntegerConstantExpr(ArgNum, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) - << Attr.getName()->getName() << E->getSourceRange(); + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) + << Attr.getName() << AANT_ArgumentIntegerConstant + << E->getSourceRange(); return; } WGSize[i] = (unsigned) ArgNum.getZExtValue(); @@ -2775,11 +2780,15 @@ static void handleWorkGroupSize(Sema &S, Decl *D, static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) { assert(Attr.getKind() == AttributeList::AT_VecTypeHint); - // Attribute has 1 argument. - if (!checkAttributeNumArgs(S, Attr, 1)) + if (!Attr.hasParsedType()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 1; return; + } - QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg()); + TypeSourceInfo *ParmTSI = 0; + QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg(), &ParmTSI); + assert(ParmTSI && "no type source info for attribute argument"); if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() && (ParmType->isBooleanType() || @@ -2792,23 +2801,14 @@ static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) { if (Attr.getKind() == AttributeList::AT_VecTypeHint && D->hasAttr<VecTypeHintAttr>()) { VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>(); - if (A->getTypeHint() != ParmType) { + if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) { S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName(); return; } } D->addAttr(::new (S.Context) VecTypeHintAttr(Attr.getLoc(), S.Context, - ParmType, Attr.getLoc())); -} - -static void handleEndianAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (!dyn_cast<VarDecl>(D)) - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << "endian" - << 9; - StringRef EndianType = Attr.getParameterName()->getName(); - if (EndianType != "host" && EndianType != "device") - S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_endian) << EndianType; + ParmTSI)); } SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range, @@ -2826,48 +2826,35 @@ SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range, } static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // Attribute has no arguments. - if (!checkAttributeNumArgs(S, Attr, 1)) - return; - // Make sure that there is a string literal as the sections's single // argument. - Expr *ArgExpr = Attr.getArg(0); - StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr); - if (!SE) { - S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) << "section"; + StringRef Str; + SourceLocation LiteralLoc; + if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc)) return; - } // If the target wants to validate the section specifier, make it happen. - std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(SE->getString()); + std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(Str); if (!Error.empty()) { - S.Diag(SE->getLocStart(), diag::err_attribute_section_invalid_for_target) + S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error; return; } // This attribute cannot be applied to local variables. if (isa<VarDecl>(D) && cast<VarDecl>(D)->hasLocalStorage()) { - S.Diag(SE->getLocStart(), diag::err_attribute_section_local_variable); + S.Diag(LiteralLoc, diag::err_attribute_section_local_variable); return; } unsigned Index = Attr.getAttributeSpellingListIndex(); - SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(), - SE->getString(), Index); + SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(), Str, Index); if (NewAttr) D->addAttr(NewAttr); } static void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (Attr.hasParameterOrArguments()) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; - return; - } - if (NoThrowAttr *Existing = D->getAttr<NoThrowAttr>()) { if (Existing->getLocation().isInvalid()) Existing->setRange(Attr.getRange()); @@ -2879,12 +2866,6 @@ static void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (Attr.hasParameterOrArguments()) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; - return; - } - if (ConstAttr *Existing = D->getAttr<ConstAttr>()) { if (Existing->getLocation().isInvalid()) Existing->setRange(Attr.getRange()); @@ -2896,56 +2877,55 @@ static void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handlePureAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - D->addAttr(::new (S.Context) PureAttr(Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); } static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (!Attr.getParameterName()) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; - return; - } - - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; - return; - } - VarDecl *VD = dyn_cast<VarDecl>(D); - if (!VD || !VD->hasLocalStorage()) { - S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup"; + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); return; } - // Look up the function - // FIXME: Lookup probably isn't looking in the right place - NamedDecl *CleanupDecl - = S.LookupSingleName(S.TUScope, Attr.getParameterName(), - Attr.getParameterLoc(), Sema::LookupOrdinaryName); - if (!CleanupDecl) { - S.Diag(Attr.getParameterLoc(), diag::err_attribute_cleanup_arg_not_found) << - Attr.getParameterName(); - return; - } + Expr *E = Attr.getArgAsExpr(0); + SourceLocation Loc = E->getExprLoc(); + FunctionDecl *FD = 0; + DeclarationNameInfo NI; - FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl); - if (!FD) { - S.Diag(Attr.getParameterLoc(), - diag::err_attribute_cleanup_arg_not_function) - << Attr.getParameterName(); + // gcc only allows for simple identifiers. Since we support more than gcc, we + // will warn the user. + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { + if (DRE->hasQualifier()) + S.Diag(Loc, diag::warn_cleanup_ext); + FD = dyn_cast<FunctionDecl>(DRE->getDecl()); + NI = DRE->getNameInfo(); + if (!FD) { + S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 1 + << NI.getName(); + return; + } + } else if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) { + if (ULE->hasExplicitTemplateArgs()) + S.Diag(Loc, diag::warn_cleanup_ext); + FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true); + NI = ULE->getNameInfo(); + if (!FD) { + S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2 + << NI.getName(); + if (ULE->getType() == S.Context.OverloadTy) + S.NoteAllOverloadCandidates(ULE); + return; + } + } else { + S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 0; return; } if (FD->getNumParams() != 1) { - S.Diag(Attr.getParameterLoc(), - diag::err_attribute_cleanup_func_must_take_one_arg) - << Attr.getParameterName(); + S.Diag(Loc, diag::err_attribute_cleanup_func_must_take_one_arg) + << NI.getName(); return; } @@ -2955,63 +2935,30 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { QualType ParamTy = FD->getParamDecl(0)->getType(); if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(), ParamTy, Ty) != Sema::Compatible) { - S.Diag(Attr.getParameterLoc(), - diag::err_attribute_cleanup_func_arg_incompatible_type) << - Attr.getParameterName() << ParamTy << Ty; + S.Diag(Loc, diag::err_attribute_cleanup_func_arg_incompatible_type) + << NI.getName() << ParamTy << Ty; return; } D->addAttr(::new (S.Context) CleanupAttr(Attr.getRange(), S.Context, FD, Attr.getAttributeSpellingListIndex())); - S.MarkFunctionReferenced(Attr.getParameterLoc(), FD); - S.DiagnoseUseOfDecl(FD, Attr.getParameterLoc()); } /// Handle __attribute__((format_arg((idx)))) attribute based on /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (!checkAttributeNumArgs(S, Attr, 1)) - return; - if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; return; } - // In C++ the implicit 'this' function parameter also counts, and they are - // counted from one. - bool HasImplicitThisParam = isInstanceMethod(D); - unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; - unsigned FirstIdx = 1; - - // checks for the 2nd argument - Expr *IdxExpr = Attr.getArg(0); - llvm::APSInt Idx(32); - if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || - !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) - << "format" << 2 << IdxExpr->getSourceRange(); - return; - } - - if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) - << "format" << 2 << IdxExpr->getSourceRange(); + Expr *IdxExpr = Attr.getArgAsExpr(0); + uint64_t ArgIdx; + if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(), + Attr.getLoc(), 1, IdxExpr, ArgIdx)) return; - } - - unsigned ArgIdx = Idx.getZExtValue() - 1; - - if (HasImplicitThisParam) { - if (ArgIdx == 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_invalid_implicit_this_argument) - << "format_arg" << IdxExpr->getSourceRange(); - return; - } - ArgIdx--; - } // make sure the format string is really a string QualType Ty = getFunctionOrMethodArgType(D, ArgIdx); @@ -3039,8 +2986,14 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } + // We cannot use the ArgIdx returned from checkFunctionOrMethodArgumentIndex + // because that has corrected for the implicit this parameter, and is zero- + // based. The attribute expects what the user wrote explicitly. + llvm::APSInt Val; + IdxExpr->EvaluateAsInt(Val, S.Context); + D->addAttr(::new (S.Context) - FormatArgAttr(Attr.getRange(), S.Context, Idx.getZExtValue(), + FormatArgAttr(Attr.getRange(), S.Context, Val.getZExtValue(), Attr.getAttributeSpellingListIndex())); } @@ -3094,18 +3047,14 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, return; } - if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; - Attr.setInvalid(); - return; - } - Expr *priorityExpr = Attr.getArg(0); + Expr *priorityExpr = Attr.getArgAsExpr(0); llvm::APSInt priority(32); if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() || !priorityExpr->isIntegerConstantExpr(priority, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) - << "init_priority" << priorityExpr->getSourceRange(); + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) + << Attr.getName() << AANT_ArgumentIntegerConstant + << priorityExpr->getSourceRange(); Attr.setInvalid(); return; } @@ -3121,8 +3070,9 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } -FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format, - int FormatIdx, int FirstArg, +FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, + IdentifierInfo *Format, int FormatIdx, + int FirstArg, unsigned AttrSpellingListIndex) { // Check whether we already have an equivalent format attribute. for (specific_attr_iterator<FormatAttr> @@ -3141,22 +3091,16 @@ FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format, } } - return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx, FirstArg, - AttrSpellingListIndex); + return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx, + FirstArg, AttrSpellingListIndex); } /// Handle __attribute__((format(type,idx,firstarg))) attributes based on /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { - - if (!Attr.getParameterName()) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) - << "format" << 1; - return; - } - - if (Attr.getNumArgs() != 2) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3; + if (!Attr.isArgIdent(0)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) + << Attr.getName() << 1 << AANT_ArgumentIdentifier; return; } @@ -3172,11 +3116,15 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; unsigned FirstIdx = 1; - StringRef Format = Attr.getParameterName()->getName(); + IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident; + StringRef Format = II->getName(); // Normalize the argument, __foo__ becomes foo. - if (Format.startswith("__") && Format.endswith("__")) + if (Format.startswith("__") && Format.endswith("__")) { Format = Format.substr(2, Format.size() - 4); + // If we've modified the string name, we need a new identifier for it. + II = &S.Context.Idents.get(Format); + } // Check for supported formats. FormatAttrKind Kind = getFormatAttrKind(Format); @@ -3186,17 +3134,18 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (Kind == InvalidFormat) { S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) - << "format" << Attr.getParameterName()->getName(); + << "format" << II->getName(); return; } // checks for the 2nd argument - Expr *IdxExpr = Attr.getArg(0); + Expr *IdxExpr = Attr.getArgAsExpr(1); llvm::APSInt Idx(32); if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) - << "format" << 2 << IdxExpr->getSourceRange(); + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) + << Attr.getName() << 2 << AANT_ArgumentIntegerConstant + << IdxExpr->getSourceRange(); return; } @@ -3246,12 +3195,13 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { } // check the 3rd argument - Expr *FirstArgExpr = Attr.getArg(1); + Expr *FirstArgExpr = Attr.getArgAsExpr(2); llvm::APSInt FirstArg(32); if (FirstArgExpr->isTypeDependent() || FirstArgExpr->isValueDependent() || !FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) - << "format" << 3 << FirstArgExpr->getSourceRange(); + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) + << Attr.getName() << 3 << AANT_ArgumentIntegerConstant + << FirstArgExpr->getSourceRange(); return; } @@ -3280,7 +3230,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), Format, + FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), II, Idx.getZExtValue(), FirstArg.getZExtValue(), Attr.getAttributeSpellingListIndex()); @@ -3290,11 +3240,6 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { static void handleTransparentUnionAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - - // Try to find the underlying union declaration. RecordDecl *RD = 0; TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D); @@ -3358,37 +3303,30 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, } static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 1)) - return; - - Expr *ArgExpr = Attr.getArg(0); - StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr); - // Make sure that there is a string literal as the annotation's single // argument. - if (!SE) { - S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate"; + StringRef Str; + if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str)) return; - } // Don't duplicate annotations that are already set. for (specific_attr_iterator<AnnotateAttr> i = D->specific_attr_begin<AnnotateAttr>(), e = D->specific_attr_end<AnnotateAttr>(); i != e; ++i) { - if ((*i)->getAnnotation() == SE->getString()) - return; + if ((*i)->getAnnotation() == Str) + return; } D->addAttr(::new (S.Context) - AnnotateAttr(Attr.getRange(), S.Context, SE->getString(), + AnnotateAttr(Attr.getRange(), S.Context, Str, Attr.getAttributeSpellingListIndex())); } static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. if (Attr.getNumArgs() > 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 1; return; } @@ -3398,7 +3336,7 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - Expr *E = Attr.getArg(0); + Expr *E = Attr.getArgAsExpr(0); if (Attr.isPackExpansion() && !E->containsUnexpandedParameterPack()) { S.Diag(Attr.getEllipsisLoc(), diag::err_pack_expansion_without_parameter_packs); @@ -3555,19 +3493,14 @@ void Sema::CheckAlignasUnderalignment(Decl *D) { static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { // This attribute isn't documented, but glibc uses it. It changes // the width of an int or unsigned int to the specified size. - - // Check that there aren't any arguments - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - - - IdentifierInfo *Name = Attr.getParameterName(); - if (!Name) { - S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name); + if (!Attr.isArgIdent(0)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName() + << AANT_ArgumentIdentifier; return; } - - StringRef Str = Attr.getParameterName()->getName(); + + IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident; + StringRef Str = Name->getName(); // Normalize the attribute name, __foo__ becomes foo. if (Str.startswith("__") && Str.endswith("__")) @@ -3639,73 +3572,24 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t // and friends, at least with glibc. - // FIXME: Make sure 32/64-bit integers don't get defined to types of the wrong - // width on unusual platforms. // FIXME: Make sure floating-point mappings are accurate // FIXME: Support XF and TF types - QualType NewTy; - switch (DestWidth) { - case 0: + if (!DestWidth) { S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name; return; - default: + } + + QualType NewTy; + + if (IntegerMode) + NewTy = S.Context.getIntTypeForBitwidth(DestWidth, + OldTy->isSignedIntegerType()); + else + NewTy = S.Context.getRealTypeForBitwidth(DestWidth); + + if (NewTy.isNull()) { S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; return; - case 8: - if (!IntegerMode) { - S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; - return; - } - if (OldTy->isSignedIntegerType()) - NewTy = S.Context.SignedCharTy; - else - NewTy = S.Context.UnsignedCharTy; - break; - case 16: - if (!IntegerMode) { - S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; - return; - } - if (OldTy->isSignedIntegerType()) - NewTy = S.Context.ShortTy; - else - NewTy = S.Context.UnsignedShortTy; - break; - case 32: - if (!IntegerMode) - NewTy = S.Context.FloatTy; - else if (OldTy->isSignedIntegerType()) - NewTy = S.Context.IntTy; - else - NewTy = S.Context.UnsignedIntTy; - break; - case 64: - if (!IntegerMode) - NewTy = S.Context.DoubleTy; - else if (OldTy->isSignedIntegerType()) - if (S.Context.getTargetInfo().getLongWidth() == 64) - NewTy = S.Context.LongTy; - else - NewTy = S.Context.LongLongTy; - else - if (S.Context.getTargetInfo().getLongWidth() == 64) - NewTy = S.Context.UnsignedLongTy; - else - NewTy = S.Context.UnsignedLongLongTy; - break; - case 96: - NewTy = S.Context.LongDoubleTy; - break; - case 128: - if (!IntegerMode) { - S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; - return; - } - if (OldTy->isSignedIntegerType()) - NewTy = S.Context.Int128Ty; - else - NewTy = S.Context.UnsignedInt128Ty; - break; } if (ComplexMode) { @@ -3713,18 +3597,17 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { } // Install the new type. - if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { - // FIXME: preserve existing source info. - TD->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(NewTy)); - } else + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) + TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy); + else cast<ValueDecl>(D)->setType(NewTy); + + D->addAttr(::new (S.Context) + ModeAttr(Attr.getRange(), S.Context, Name, + Attr.getAttributeSpellingListIndex())); } static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (!VD->hasGlobalStorage()) S.Diag(Attr.getLoc(), @@ -3743,11 +3626,6 @@ static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - - if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; @@ -3761,11 +3639,6 @@ static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - - if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; @@ -3779,12 +3652,6 @@ static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D, static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.CUDA) { - // check the attribute arguments. - if (Attr.hasParameterOrArguments()) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; - return; - } - if (!isa<VarDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedVariable; @@ -3803,7 +3670,8 @@ static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.CUDA) { // check the attribute arguments. if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 0; return; } @@ -3823,10 +3691,6 @@ static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) { static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.CUDA) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; @@ -3858,11 +3722,6 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) { static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.CUDA) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - - if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunction; @@ -3879,10 +3738,6 @@ static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) { static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.CUDA) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - if (!isa<VarDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedVariable; @@ -3898,10 +3753,6 @@ static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 0)) - return; - FunctionDecl *Fn = dyn_cast<FunctionDecl>(D); if (Fn == 0) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) @@ -4006,19 +3857,17 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){ - assert(!Attr.isInvalid()); D->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getRange(), S.Context)); } static void handleOpenCLImageAccessAttr(Sema &S, Decl *D, const AttributeList &Attr){ - assert(!Attr.isInvalid()); - - Expr *E = Attr.getArg(0); + Expr *E = Attr.getArgAsExpr(0); llvm::APSInt ArgNum(32); if (E->isTypeDependent() || E->isValueDependent() || !E->isIntegerConstantExpr(ArgNum, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) - << Attr.getName()->getName() << E->getSourceRange(); + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) + << Attr.getName() << AANT_ArgumentIntegerConstant + << E->getSourceRange(); return; } @@ -4032,8 +3881,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, return true; unsigned ReqArgs = attr.getKind() == AttributeList::AT_Pcs ? 1 : 0; - if (attr.getNumArgs() != ReqArgs || attr.getParameterName()) { - Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << ReqArgs; + if (!checkAttributeNumArgs(*this, attr, ReqArgs)) { attr.setInvalid(); return true; } @@ -4055,16 +3903,11 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, CC_C; break; case AttributeList::AT_Pcs: { - Expr *Arg = attr.getArg(0); - StringLiteral *Str = dyn_cast<StringLiteral>(Arg); - if (!Str || !Str->isAscii()) { - Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) - << "pcs" << 1; + StringRef StrRef; + if (!checkStringLiteralArgumentAttr(attr, 0, StrRef)) { attr.setInvalid(); return true; } - - StringRef StrRef = Str->getString(); if (StrRef == "aapcs") { CC = CC_AAPCS; break; @@ -4121,18 +3964,18 @@ bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) { if (Attr.isInvalid()) return true; - if (Attr.getNumArgs() != 1) { - Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + if (!checkAttributeNumArgs(*this, Attr, 1)) { Attr.setInvalid(); return true; } - Expr *NumParamsExpr = Attr.getArg(0); + Expr *NumParamsExpr = Attr.getArgAsExpr(0); llvm::APSInt NumParams(32); if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() || !NumParamsExpr->isIntegerConstantExpr(NumParams, Context)) { - Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) - << "regparm" << NumParamsExpr->getSourceRange(); + Diag(Attr.getLoc(), diag::err_attribute_argument_type) + << Attr.getName() << AANT_ArgumentIntegerConstant + << NumParamsExpr->getSourceRange(); Attr.setInvalid(); return true; } @@ -4170,24 +4013,26 @@ static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){ return; } - Expr *MaxThreadsExpr = Attr.getArg(0); + Expr *MaxThreadsExpr = Attr.getArgAsExpr(0); llvm::APSInt MaxThreads(32); if (MaxThreadsExpr->isTypeDependent() || MaxThreadsExpr->isValueDependent() || !MaxThreadsExpr->isIntegerConstantExpr(MaxThreads, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) - << "launch_bounds" << 1 << MaxThreadsExpr->getSourceRange(); + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) + << Attr.getName() << 1 << AANT_ArgumentIntegerConstant + << MaxThreadsExpr->getSourceRange(); return; } llvm::APSInt MinBlocks(32); if (Attr.getNumArgs() > 1) { - Expr *MinBlocksExpr = Attr.getArg(1); + Expr *MinBlocksExpr = Attr.getArgAsExpr(1); if (MinBlocksExpr->isTypeDependent() || MinBlocksExpr->isValueDependent() || !MinBlocksExpr->isIntegerConstantExpr(MinBlocks, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) - << "launch_bounds" << 2 << MinBlocksExpr->getSourceRange(); + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) + << Attr.getName() << 2 << AANT_ArgumentIntegerConstant + << MinBlocksExpr->getSourceRange(); return; } } @@ -4204,20 +4049,17 @@ static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, const AttributeList &Attr) { - StringRef AttrName = Attr.getName()->getName(); - if (!Attr.getParameterName()) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_identifier) - << Attr.getName() << /* arg num = */ 1; + if (!Attr.isArgIdent(0)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) + << Attr.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier; return; } - - if (Attr.getNumArgs() != 2) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << /* required args = */ 3; + + if (!checkAttributeNumArgs(S, Attr, 3)) return; - } - IdentifierInfo *ArgumentKind = Attr.getParameterName(); + StringRef AttrName = Attr.getName()->getName(); + IdentifierInfo *ArgumentKind = Attr.getArgAsIdent(0)->Ident; if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) @@ -4228,13 +4070,13 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, uint64_t ArgumentIdx; if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName, Attr.getLoc(), 2, - Attr.getArg(0), ArgumentIdx)) + Attr.getArgAsExpr(1), ArgumentIdx)) return; uint64_t TypeTagIdx; if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName, Attr.getLoc(), 3, - Attr.getArg(1), TypeTagIdx)) + Attr.getArgAsExpr(2), TypeTagIdx)) return; bool IsPointer = (AttrName == "pointer_with_type_tag"); @@ -4243,7 +4085,7 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, QualType BufferTy = getFunctionOrMethodArgType(D, ArgumentIdx); if (!BufferTy->isPointerType()) { S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only) - << AttrName; + << Attr.getName(); } } @@ -4255,18 +4097,23 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, const AttributeList &Attr) { - IdentifierInfo *PointerKind = Attr.getParameterName(); - if (!PointerKind) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_identifier) - << "type_tag_for_datatype" << 1; + if (!Attr.isArgIdent(0)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) + << Attr.getName() << 1 << AANT_ArgumentIdentifier; return; } + + if (!checkAttributeNumArgs(S, Attr, 1)) + return; - QualType MatchingCType = S.GetTypeFromParser(Attr.getMatchingCType(), NULL); + IdentifierInfo *PointerKind = Attr.getArgAsIdent(0)->Ident; + TypeSourceInfo *MatchingCTypeLoc = 0; + S.GetTypeFromParser(Attr.getMatchingCType(), &MatchingCTypeLoc); + assert(MatchingCTypeLoc && "no type source info for attribute argument"); D->addAttr(::new (S.Context) TypeTagForDatatypeAttr(Attr.getRange(), S.Context, PointerKind, - MatchingCType, + MatchingCTypeLoc, Attr.getLayoutCompatible(), Attr.getMustBeNull(), Attr.getAttributeSpellingListIndex())); @@ -4411,30 +4258,39 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, const AttributeList &attr) { + const int EP_ObjCMethod = 1; + const int EP_ObjCProperty = 2; + SourceLocation loc = attr.getLoc(); - + QualType resultType; + ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D); if (!method) { - S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) - << SourceRange(loc, loc) << attr.getName() << ExpectedMethod; - return; + ObjCPropertyDecl *property = dyn_cast<ObjCPropertyDecl>(D); + if (!property) { + S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) + << SourceRange(loc, loc) << attr.getName() << ExpectedMethodOrProperty; + return; + } + resultType = property->getType(); } + else + // Check that the method returns a normal pointer. + resultType = method->getResultType(); - // Check that the method returns a normal pointer. - QualType resultType = method->getResultType(); - if (!resultType->isReferenceType() && (!resultType->isPointerType() || resultType->isObjCRetainableType())) { - S.Diag(method->getLocStart(), diag::warn_ns_attribute_wrong_return_type) + S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type) << SourceRange(loc) - << attr.getName() << /*method*/ 1 << /*non-retainable pointer*/ 2; + << attr.getName() << (method ? EP_ObjCMethod : EP_ObjCProperty) + << /*non-retainable pointer*/ 2; // Drop the attribute. return; } - method->addAttr(::new (S.Context) + D->addAttr(::new (S.Context) ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context, attr.getAttributeSpellingListIndex())); } @@ -4512,14 +4368,14 @@ static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D, << Attr.getRange() << Attr.getName() << ExpectedStruct; } - IdentifierInfo *ParmName = Attr.getParameterName(); + IdentifierLoc *Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0; // In Objective-C, verify that the type names an Objective-C type. // We don't want to check this outside of ObjC because people sometimes // do crazy C declarations of Objective-C types. - if (ParmName && S.getLangOpts().ObjC1) { + if (Parm && S.getLangOpts().ObjC1) { // Check for an existing type with this name. - LookupResult R(S, DeclarationName(ParmName), Attr.getParameterLoc(), + LookupResult R(S, DeclarationName(Parm->Ident), Parm->Loc, Sema::LookupOrdinaryName); if (S.LookupName(R, Sc)) { NamedDecl *Target = R.getFoundDecl(); @@ -4531,7 +4387,32 @@ static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D, } D->addAttr(::new (S.Context) - NSBridgedAttr(Attr.getRange(), S.Context, ParmName, + NSBridgedAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0, + Attr.getAttributeSpellingListIndex())); +} + +static void handleObjCBridgeAttr(Sema &S, Scope *Sc, Decl *D, + const AttributeList &Attr) { + if (!isa<RecordDecl>(D)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() + << (S.getLangOpts().CPlusPlus ? ExpectedStructOrUnionOrClass + : ExpectedStructOrUnion); + return; + } + + if (Attr.getNumArgs() != 1) { + S.Diag(D->getLocStart(), diag::err_objc_bridge_not_id); + return; + } + IdentifierLoc *Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0; + if (!Parm) { + S.Diag(D->getLocStart(), diag::err_objc_bridge_not_id); + return; + } + + D->addAttr(::new (S.Context) + ObjCBridgeAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0, Attr.getAttributeSpellingListIndex())); } @@ -4594,66 +4475,55 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, // Microsoft specific attribute handlers. //===----------------------------------------------------------------------===// -static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (S.LangOpts.MicrosoftExt || S.LangOpts.Borland) { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 1)) - return; - - Expr *Arg = Attr.getArg(0); - StringLiteral *Str = dyn_cast<StringLiteral>(Arg); - if (!Str || !Str->isAscii()) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) - << "uuid" << 1; - return; - } +// Check if MS extensions or some other language extensions are enabled. If +// not, issue a diagnostic that the given attribute is unused. +static bool checkMicrosoftExt(Sema &S, const AttributeList &Attr, + bool OtherExtension = false) { + if (S.LangOpts.MicrosoftExt || OtherExtension) + return true; + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); + return false; +} - StringRef StrRef = Str->getString(); +static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!checkMicrosoftExt(S, Attr, S.LangOpts.Borland)) + return; - bool IsCurly = StrRef.size() > 1 && StrRef.front() == '{' && - StrRef.back() == '}'; + StringRef StrRef; + SourceLocation LiteralLoc; + if (!S.checkStringLiteralArgumentAttr(Attr, 0, StrRef, &LiteralLoc)) + return; - // Validate GUID length. - if (IsCurly && StrRef.size() != 38) { - S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); - return; - } - if (!IsCurly && StrRef.size() != 36) { - S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); - return; - } + // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or + // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}", normalize to the former. + if (StrRef.size() == 38 && StrRef.front() == '{' && StrRef.back() == '}') + StrRef = StrRef.drop_front().drop_back(); - // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or - // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" - StringRef::iterator I = StrRef.begin(); - if (IsCurly) // Skip the optional '{' - ++I; + // Validate GUID length. + if (StrRef.size() != 36) { + S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); + return; + } - for (int i = 0; i < 36; ++i) { - if (i == 8 || i == 13 || i == 18 || i == 23) { - if (*I != '-') { - S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); - return; - } - } else if (!isHexDigit(*I)) { - S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); + for (unsigned i = 0; i < 36; ++i) { + if (i == 8 || i == 13 || i == 18 || i == 23) { + if (StrRef[i] != '-') { + S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); return; } - I++; + } else if (!isHexDigit(StrRef[i])) { + S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); + return; } + } - D->addAttr(::new (S.Context) - UuidAttr(Attr.getRange(), S.Context, Str->getString(), - Attr.getAttributeSpellingListIndex())); - } else - S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "uuid"; + D->addAttr(::new (S.Context) UuidAttr(Attr.getRange(), S.Context, StrRef, + Attr.getAttributeSpellingListIndex())); } static void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (!S.LangOpts.MicrosoftExt) { - S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); + if (!checkMicrosoftExt(S, Attr)) return; - } AttributeList::Kind Kind = Attr.getKind(); if (Kind == AttributeList::AT_SingleInheritance) @@ -4674,50 +4544,78 @@ static void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (S.LangOpts.MicrosoftExt) { - AttributeList::Kind Kind = Attr.getKind(); - if (Kind == AttributeList::AT_Ptr32) - D->addAttr( - ::new (S.Context) Ptr32Attr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); - else if (Kind == AttributeList::AT_Ptr64) - D->addAttr( - ::new (S.Context) Ptr64Attr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); - else if (Kind == AttributeList::AT_Win64) - D->addAttr( - ::new (S.Context) Win64Attr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); - } else - S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); + if (!checkMicrosoftExt(S, Attr)) + return; + + AttributeList::Kind Kind = Attr.getKind(); + if (Kind == AttributeList::AT_Win64) + D->addAttr( + ::new (S.Context) Win64Attr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleForceInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (S.LangOpts.MicrosoftExt) - D->addAttr(::new (S.Context) - ForceInlineAttr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); - else - S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); + if (!checkMicrosoftExt(S, Attr)) + return; + D->addAttr(::new (S.Context) + ForceInlineAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); +} + +static void handleSelectAnyAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!checkMicrosoftExt(S, Attr)) + return; + // Check linkage after possibly merging declaratinos. See + // checkAttributesAfterMerging(). + D->addAttr(::new (S.Context) + SelectAnyAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); +} + +/// Handles semantic checking for features that are common to all attributes, +/// such as checking whether a parameter was properly specified, or the correct +/// number of arguments were passed, etc. +static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D, + const AttributeList &Attr) { + // Several attributes carry different semantics than the parsing requires, so + // those are opted out of the common handling. + // + // We also bail on unknown and ignored attributes because those are handled + // as part of the target-specific handling logic. + if (Attr.hasCustomParsing() || + Attr.getKind() == AttributeList::UnknownAttribute || + Attr.getKind() == AttributeList::IgnoredAttribute) + return false; + + // If there are no optional arguments, then checking for the argument count + // is trivial. + if (Attr.getMinArgs() == Attr.getMaxArgs() && + !checkAttributeNumArgs(S, Attr, Attr.getMinArgs())) + return true; + return false; } //===----------------------------------------------------------------------===// // Top Level Sema Entry Points //===----------------------------------------------------------------------===// -static void ProcessNonInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, - const AttributeList &Attr) { - switch (Attr.getKind()) { - case AttributeList::AT_CUDADevice: handleDeviceAttr (S, D, Attr); break; - case AttributeList::AT_CUDAHost: handleHostAttr (S, D, Attr); break; - case AttributeList::AT_Overloadable:handleOverloadableAttr(S, D, Attr); break; - default: - break; - } -} +/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if +/// the attribute applies to decls. If the attribute is a type attribute, just +/// silently ignore it if a GNU attribute. +static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, + const AttributeList &Attr, + bool IncludeCXX11Attributes) { + if (Attr.isInvalid()) + return; + + // Ignore C++11 attributes on declarator chunks: they appertain to the type + // instead. + if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes) + return; + + if (handleCommonAttributeFeatures(S, scope, D, Attr)) + return; -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; @@ -4728,15 +4626,13 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_VectorSize: case AttributeList::AT_NeonVectorType: case AttributeList::AT_NeonPolyVectorType: + case AttributeList::AT_Ptr32: + case AttributeList::AT_Ptr64: + case AttributeList::AT_SPtr: + case AttributeList::AT_UPtr: // Ignore these, these are type attributes, handled by // ProcessTypeAttributes. break; - case AttributeList::AT_CUDADevice: - case AttributeList::AT_CUDAHost: - case AttributeList::AT_Overloadable: - // Ignore, this is a non-inheritable attribute, handled - // by ProcessNonInheritableDeclAttr. - break; case AttributeList::AT_Alias: handleAliasAttr (S, D, Attr); break; case AttributeList::AT_Aligned: handleAlignedAttr (S, D, Attr); break; case AttributeList::AT_AllocSize: handleAllocSizeAttr (S, D, Attr); break; @@ -4757,7 +4653,7 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, handleCXX11NoReturnAttr(S, D, Attr); break; case AttributeList::AT_Deprecated: - handleAttrWithMessage<DeprecatedAttr>(S, D, Attr, "deprecated"); + handleAttrWithMessage<DeprecatedAttr>(S, D, Attr); break; case AttributeList::AT_Destructor: handleDestructorAttr (S, D, Attr); break; case AttributeList::AT_ExtVectorType: @@ -4769,15 +4665,18 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_Format: handleFormatAttr (S, D, Attr); break; case AttributeList::AT_FormatArg: handleFormatArgAttr (S, D, Attr); break; case AttributeList::AT_CUDAGlobal: handleGlobalAttr (S, D, Attr); break; + case AttributeList::AT_CUDADevice: handleDeviceAttr (S, D, Attr); break; + case AttributeList::AT_CUDAHost: handleHostAttr (S, D, Attr); break; case AttributeList::AT_GNUInline: handleGNUInlineAttr (S, D, Attr); break; case AttributeList::AT_CUDALaunchBounds: handleLaunchBoundsAttr(S, D, Attr); break; - case AttributeList::AT_Mode: handleModeAttr (S, D, Attr); break; case AttributeList::AT_Malloc: handleMallocAttr (S, D, Attr); break; case AttributeList::AT_MayAlias: handleMayAliasAttr (S, D, Attr); break; + case AttributeList::AT_Mode: handleModeAttr (S, D, Attr); break; case AttributeList::AT_NoCommon: handleNoCommonAttr (S, D, Attr); break; case AttributeList::AT_NonNull: handleNonNullAttr (S, D, Attr); break; + case AttributeList::AT_Overloadable:handleOverloadableAttr(S, D, Attr); break; case AttributeList::AT_ownership_returns: case AttributeList::AT_ownership_takes: case AttributeList::AT_ownership_holds: @@ -4803,6 +4702,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_NSBridged: handleNSBridgedAttr(S, scope, D, Attr); break; + + case AttributeList::AT_ObjCBridge: + handleObjCBridgeAttr(S, scope, D, Attr); break; case AttributeList::AT_CFAuditedTransfer: case AttributeList::AT_CFUnknownTransfer: @@ -4828,17 +4730,13 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_VecTypeHint: handleVecTypeHint(S, D, Attr); break; - case AttributeList::AT_Endian: - handleEndianAttr(S, D, Attr); - break; - case AttributeList::AT_InitPriority: handleInitPriorityAttr(S, D, Attr); break; case AttributeList::AT_Packed: handlePackedAttr (S, D, Attr); break; case AttributeList::AT_Section: handleSectionAttr (S, D, Attr); break; case AttributeList::AT_Unavailable: - handleAttrWithMessage<UnavailableAttr>(S, D, Attr, "unavailable"); + handleAttrWithMessage<UnavailableAttr>(S, D, Attr); break; case AttributeList::AT_ArcWeakrefUnavailable: handleArcWeakrefUnavailableAttr (S, D, Attr); @@ -4860,6 +4758,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_TypeVisibility: handleVisibilityAttr(S, D, Attr, true); break; + case AttributeList::AT_WarnUnused: + handleWarnUnusedAttr(S, D, Attr); + break; case AttributeList::AT_WarnUnusedResult: handleWarnUnusedResult(S, D, Attr); break; case AttributeList::AT_Weak: handleWeakAttr (S, D, Attr); break; @@ -4909,7 +4810,6 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, break; // Microsoft attributes: - case AttributeList::AT_MsProperty: break; case AttributeList::AT_MsStruct: handleMsStructAttr(S, D, Attr); break; @@ -4922,15 +4822,22 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, handleInheritanceAttr(S, D, Attr); break; case AttributeList::AT_Win64: - case AttributeList::AT_Ptr32: - case AttributeList::AT_Ptr64: handlePortabilityAttr(S, D, Attr); break; case AttributeList::AT_ForceInline: handleForceInlineAttr(S, D, Attr); break; + case AttributeList::AT_SelectAny: + handleSelectAnyAttr(S, D, Attr); + break; // Thread safety attributes: + case AttributeList::AT_AssertExclusiveLock: + handleAssertExclusiveLockAttr(S, D, Attr); + break; + case AttributeList::AT_AssertSharedLock: + handleAssertSharedLockAttr(S, D, Attr); + break; case AttributeList::AT_GuardedVar: handleGuardedVarAttr(S, D, Attr); break; @@ -4995,6 +4902,26 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, handleAcquiredAfterAttr(S, D, Attr); break; + // Consumed analysis attributes. + case AttributeList::AT_Consumable: + handleConsumableAttr(S, D, Attr); + break; + case AttributeList::AT_CallableWhen: + handleCallableWhenAttr(S, D, Attr); + break; + case AttributeList::AT_ParamTypestate: + handleParamTypestateAttr(S, D, Attr); + break; + case AttributeList::AT_ReturnTypestate: + handleReturnTypestateAttr(S, D, Attr); + break; + case AttributeList::AT_SetTypestate: + handleSetTypestateAttr(S, D, Attr); + break; + case AttributeList::AT_TestTypestate: + handleTestTypestateAttr(S, D, Attr); + break; + // Type safety attributes. case AttributeList::AT_ArgumentWithTypeTag: handleArgumentWithTypeTagAttr(S, D, Attr); @@ -5014,42 +4941,18 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, } } -/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if -/// the attribute applies to decls. If the attribute is a type attribute, just -/// silently ignore it if a GNU attribute. -static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, - const AttributeList &Attr, - bool NonInheritable, bool Inheritable, - bool IncludeCXX11Attributes) { - if (Attr.isInvalid()) - return; - - // Ignore C++11 attributes on declarator chunks: they appertain to the type - // instead. - if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes) - return; - - if (NonInheritable) - ProcessNonInheritableDeclAttr(S, scope, D, Attr); - - if (Inheritable) - ProcessInheritableDeclAttr(S, scope, D, Attr); -} - /// ProcessDeclAttributeList - Apply all the decl attributes in the specified /// attribute list to the specified decl, ignoring any type attributes. void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList, - bool NonInheritable, bool Inheritable, bool IncludeCXX11Attributes) { for (const AttributeList* l = AttrList; l; l = l->getNext()) - ProcessDeclAttribute(*this, S, D, *l, NonInheritable, Inheritable, - IncludeCXX11Attributes); + ProcessDeclAttribute(*this, S, D, *l, IncludeCXX11Attributes); // GCC accepts // static int a9 __attribute__((weakref)); // but that looks really pointless. We reject it. - if (Inheritable && D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) { + if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) { Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) << cast<NamedDecl>(D)->getNameAsString(); D->dropAttr<WeakRefAttr>(); @@ -5202,11 +5105,10 @@ void Sema::ProcessPragmaWeak(Scope *S, Decl *D) { /// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in /// it, apply them to D. This is a bit tricky because PD can have attributes /// specified in many different places, and we need to find and apply them all. -void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD, - bool NonInheritable, bool Inheritable) { +void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { // Apply decl attributes from the DeclSpec if present. if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList()) - ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable); + ProcessDeclAttributeList(S, D, Attrs); // Walk the declarator structure, applying decl attributes that were in a type // position to the decl itself. This handles cases like: @@ -5214,12 +5116,11 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD, // when X is a decl attribute. for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) - ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable, - /*IncludeCXX11Attributes=*/false); + ProcessDeclAttributeList(S, D, Attrs, /*IncludeCXX11Attributes=*/false); // Finally, apply any attributes on the decl itself. if (const AttributeList *Attrs = PD.getAttributes()) - ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable); + ProcessDeclAttributeList(S, D, Attrs); } /// Is the given declaration allowed to use a forbidden type? diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp index e6a131a0761c..6b3400adac6e 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp @@ -14,6 +14,7 @@ #include "clang/Sema/SemaInternal.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" @@ -27,6 +28,7 @@ #include "clang/AST/TypeOrdering.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/LiteralSupport.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/CXXFieldCollector.h" #include "clang/Sema/DeclSpec.h" @@ -339,9 +341,7 @@ void Sema::ActOnParamUnparsedDefaultArgument(Decl *param, return; ParmVarDecl *Param = cast<ParmVarDecl>(param); - if (Param) - Param->setUnparsedDefaultArg(); - + Param->setUnparsedDefaultArg(); UnparsedDefaultArgLocs[Param] = ArgLoc; } @@ -352,9 +352,7 @@ void Sema::ActOnParamDefaultArgumentError(Decl *param) { return; ParmVarDecl *Param = cast<ParmVarDecl>(param); - Param->setInvalidDecl(); - UnparsedDefaultArgLocs.erase(Param); } @@ -404,6 +402,17 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { } } +static bool functionDeclHasDefaultArgument(const FunctionDecl *FD) { + for (unsigned NumParams = FD->getNumParams(); NumParams > 0; --NumParams) { + const ParmVarDecl *PVD = FD->getParamDecl(NumParams-1); + if (!PVD->hasDefaultArg()) + return false; + if (!PVD->hasInheritedDefaultArg()) + return true; + } + return false; +} + /// MergeCXXFunctionDecl - Merge two declarations of the same C++ /// function, once we already know that they have the same /// type. Subroutine of MergeFunctionDecl. Returns true if there was an @@ -426,9 +435,9 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, // declaration (not even to the same value). // // C++ [dcl.fct.default]p6: - // Except for member functions of class templates, the default arguments - // in a member function definition that appears outside of the class - // definition are added to the set of default arguments provided by the + // Except for member functions of class templates, the default arguments + // in a member function definition that appears outside of the class + // definition are added to the set of default arguments provided by the // member function declaration in the class definition. for (unsigned p = 0, NumParams = Old->getNumParams(); p < NumParams; ++p) { ParmVarDecl *OldParam = Old->getParamDecl(p); @@ -438,9 +447,18 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, bool NewParamHasDfl = NewParam->hasDefaultArg(); NamedDecl *ND = Old; - if (S && !isDeclInScope(ND, New->getDeclContext(), S)) + + // The declaration context corresponding to the scope is the semantic + // parent, unless this is a local function declaration, in which case + // it is that surrounding function. + DeclContext *ScopeDC = New->getLexicalDeclContext(); + if (!ScopeDC->isFunctionOrMethod()) + ScopeDC = New->getDeclContext(); + if (S && !isDeclInScope(ND, ScopeDC, S) && + !New->getDeclContext()->isRecord()) // Ignore default parameters of old decl if they are not in - // the same scope. + // the same scope and this is not an out-of-line definition of + // a member function. OldParamHasDfl = false; if (OldParamHasDfl && NewParamHasDfl) { @@ -578,6 +596,17 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Invalid = true; } + // C++11 [dcl.fct.default]p4: If a friend declaration specifies a default + // argument expression, that declaration shall be a definition and shall be + // the only declaration of the function or function template in the + // translation unit. + if (Old->getFriendObjectKind() == Decl::FOK_Undeclared && + functionDeclHasDefaultArgument(Old)) { + Diag(New->getLocation(), diag::err_friend_decl_with_def_arg_redeclared); + Diag(Old->getLocation(), diag::note_previous_declaration); + Invalid = true; + } + if (CheckEquivalentExceptionSpec(Old, New)) Invalid = true; @@ -851,7 +880,7 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl, diag::err_constexpr_local_var_non_literal_type, isa<CXXConstructorDecl>(Dcl))) return false; - if (!VD->hasInit()) { + if (!VD->hasInit() && !VD->isCXXForRangeDecl()) { SemaRef.Diag(VD->getLocation(), diag::err_constexpr_local_var_no_init) << isa<CXXConstructorDecl>(Dcl); @@ -897,6 +926,9 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef, FieldDecl *Field, llvm::SmallSet<Decl*, 16> &Inits, bool &Diagnosed) { + if (Field->isInvalidDecl()) + return; + if (Field->isUnnamedBitfield()) return; @@ -925,7 +957,7 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef, /// definition. static bool CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S, - llvm::SmallVectorImpl<SourceLocation> &ReturnStmts, + SmallVectorImpl<SourceLocation> &ReturnStmts, SourceLocation &Cxx1yLoc) { // - its function-body shall be [...] a compound-statement that contains only switch (S->getStmtClass()) { @@ -1192,8 +1224,33 @@ bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *, if (CurDecl && CurDecl->getIdentifier()) return &II == CurDecl->getIdentifier(); - else + return false; +} + +/// \brief Determine whether the identifier II is a typo for the name of +/// the class type currently being defined. If so, update it to the identifier +/// that should have been used. +bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) { + assert(getLangOpts().CPlusPlus && "No class names in C!"); + + if (!getLangOpts().SpellChecking) return false; + + CXXRecordDecl *CurDecl; + if (SS && SS->isSet() && !SS->isInvalid()) { + DeclContext *DC = computeDeclContext(*SS, true); + CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC); + } else + CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext); + + if (CurDecl && CurDecl->getIdentifier() && II != CurDecl->getIdentifier() && + 3 * II->getName().edit_distance(CurDecl->getIdentifier()->getName()) + < II->getLength()) { + II = CurDecl->getIdentifier(); + return true; + } + + return false; } /// \brief Determine whether the given class is a base class of the given @@ -1224,8 +1281,7 @@ static bool findCircularInheritance(const CXXRecordDecl *Class, if (Queue.empty()) return false; - Current = Queue.back(); - Queue.pop_back(); + Current = Queue.pop_back_val(); } return false; @@ -1311,15 +1367,28 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, assert(BaseDecl && "Record type has no declaration"); BaseDecl = BaseDecl->getDefinition(); assert(BaseDecl && "Base type is not incomplete, but has no definition"); - CXXRecordDecl * CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl); + CXXRecordDecl *CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl); assert(CXXBaseDecl && "Base type is not a C++ type"); + // A class which contains a flexible array member is not suitable for use as a + // base class: + // - If the layout determines that a base comes before another base, + // the flexible array member would index into the subsequent base. + // - If the layout determines that base comes before the derived class, + // the flexible array member would index into the derived class. + if (CXXBaseDecl->hasFlexibleArrayMember()) { + Diag(BaseLoc, diag::err_base_class_has_flexible_array_member) + << CXXBaseDecl->getDeclName(); + return 0; + } + // C++ [class]p3: - // If a class is marked final and it appears as a base-type-specifier in + // If a class is marked final and it appears as a base-type-specifier in // base-clause, the program is ill-formed. - if (CXXBaseDecl->hasAttr<FinalAttr>()) { - Diag(BaseLoc, diag::err_class_marked_final_used_as_base) - << CXXBaseDecl->getDeclName(); + if (FinalAttr *FA = CXXBaseDecl->getAttr<FinalAttr>()) { + Diag(BaseLoc, diag::err_class_marked_final_used_as_base) + << CXXBaseDecl->getDeclName() + << FA->isSpelledAsSealed(); Diag(CXXBaseDecl->getLocation(), diag::note_previous_decl) << CXXBaseDecl->getDeclName(); return 0; @@ -1327,7 +1396,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, if (BaseDecl->isInvalidDecl()) Class->setInvalidDecl(); - + // Create the base specifier. return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual, Class->getTagKind() == TTK_Class, @@ -1465,8 +1534,7 @@ void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, CXXBaseSpecifier **Bases, return; AdjustDeclIfTemplate(ClassDecl); - AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), - (CXXBaseSpecifier**)(Bases), NumBases); + AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases, NumBases); } /// \brief Determine whether the type \p Derived is a C++ class that is @@ -1590,26 +1658,28 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, return false; } - // We know that the derived-to-base conversion is ambiguous, and - // we're going to produce a diagnostic. Perform the derived-to-base - // search just one more time to compute all of the possible paths so - // that we can print them out. This is more expensive than any of - // the previous derived-to-base checks we've done, but at this point - // performance isn't as much of an issue. - Paths.clear(); - Paths.setRecordingPaths(true); - bool StillOkay = IsDerivedFrom(Derived, Base, Paths); - assert(StillOkay && "Can only be used with a derived-to-base conversion"); - (void)StillOkay; - - // Build up a textual representation of the ambiguous paths, e.g., - // D -> B -> A, that will be used to illustrate the ambiguous - // conversions in the diagnostic. We only print one of the paths - // to each base class subobject. - std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths); - - Diag(Loc, AmbigiousBaseConvID) - << Derived << Base << PathDisplayStr << Range << Name; + if (AmbigiousBaseConvID) { + // We know that the derived-to-base conversion is ambiguous, and + // we're going to produce a diagnostic. Perform the derived-to-base + // search just one more time to compute all of the possible paths so + // that we can print them out. This is more expensive than any of + // the previous derived-to-base checks we've done, but at this point + // performance isn't as much of an issue. + Paths.clear(); + Paths.setRecordingPaths(true); + bool StillOkay = IsDerivedFrom(Derived, Base, Paths); + assert(StillOkay && "Can only be used with a derived-to-base conversion"); + (void)StillOkay; + + // Build up a textual representation of the ambiguous paths, e.g., + // D -> B -> A, that will be used to illustrate the ambiguous + // conversions in the diagnostic. We only print one of the paths + // to each base class subobject. + std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths); + + Diag(Loc, AmbigiousBaseConvID) + << Derived << Base << PathDisplayStr << Range << Name; + } return true; } @@ -1675,37 +1745,63 @@ bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, } /// CheckOverrideControl - Check C++11 override control semantics. -void Sema::CheckOverrideControl(Decl *D) { +void Sema::CheckOverrideControl(NamedDecl *D) { if (D->isInvalidDecl()) return; - const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D); + // We only care about "override" and "final" declarations. + if (!D->hasAttr<OverrideAttr>() && !D->hasAttr<FinalAttr>()) + return; - // Do we know which functions this declaration might be overriding? - bool OverridesAreKnown = !MD || - (!MD->getParent()->hasAnyDependentBases() && - !MD->getType()->isDependentType()); + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D); - if (!MD || !MD->isVirtual()) { - if (OverridesAreKnown) { + // We can't check dependent instance methods. + if (MD && MD->isInstance() && + (MD->getParent()->hasAnyDependentBases() || + MD->getType()->isDependentType())) + return; + + if (MD && !MD->isVirtual()) { + // If we have a non-virtual method, check if if hides a virtual method. + // (In that case, it's most likely the method has the wrong type.) + SmallVector<CXXMethodDecl *, 8> OverloadedMethods; + FindHiddenVirtualMethods(MD, OverloadedMethods); + + if (!OverloadedMethods.empty()) { if (OverrideAttr *OA = D->getAttr<OverrideAttr>()) { Diag(OA->getLocation(), - diag::override_keyword_only_allowed_on_virtual_member_functions) - << "override" << FixItHint::CreateRemoval(OA->getLocation()); - D->dropAttr<OverrideAttr>(); - } - if (FinalAttr *FA = D->getAttr<FinalAttr>()) { + diag::override_keyword_hides_virtual_member_function) + << "override" << (OverloadedMethods.size() > 1); + } else if (FinalAttr *FA = D->getAttr<FinalAttr>()) { Diag(FA->getLocation(), - diag::override_keyword_only_allowed_on_virtual_member_functions) - << "final" << FixItHint::CreateRemoval(FA->getLocation()); - D->dropAttr<FinalAttr>(); + diag::override_keyword_hides_virtual_member_function) + << (FA->isSpelledAsSealed() ? "sealed" : "final") + << (OverloadedMethods.size() > 1); } + NoteHiddenVirtualMethods(MD, OverloadedMethods); + MD->setInvalidDecl(); + return; } - return; + // Fall through into the general case diagnostic. + // FIXME: We might want to attempt typo correction here. } - if (!OverridesAreKnown) + if (!MD || !MD->isVirtual()) { + if (OverrideAttr *OA = D->getAttr<OverrideAttr>()) { + Diag(OA->getLocation(), + diag::override_keyword_only_allowed_on_virtual_member_functions) + << "override" << FixItHint::CreateRemoval(OA->getLocation()); + D->dropAttr<OverrideAttr>(); + } + if (FinalAttr *FA = D->getAttr<FinalAttr>()) { + Diag(FA->getLocation(), + diag::override_keyword_only_allowed_on_virtual_member_functions) + << (FA->isSpelledAsSealed() ? "sealed" : "final") + << FixItHint::CreateRemoval(FA->getLocation()); + D->dropAttr<FinalAttr>(); + } return; + } // C++11 [class.virtual]p5: // If a virtual function is marked with the virt-specifier override and @@ -1723,11 +1819,13 @@ void Sema::CheckOverrideControl(Decl *D) { /// C++11 [class.virtual]p4. bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New, const CXXMethodDecl *Old) { - if (!Old->hasAttr<FinalAttr>()) + FinalAttr *FA = Old->getAttr<FinalAttr>(); + if (!FA) return false; Diag(New->getLocation(), diag::err_final_function_overridden) - << New->getDeclName(); + << New->getDeclName() + << FA->isSpelledAsSealed(); Diag(Old->getLocation(), diag::note_overridden_virtual_function); return true; } @@ -1933,19 +2031,20 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, if (MSPropertyAttr) { Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth, InitStyle, AS, MSPropertyAttr); + if (!Member) + return 0; isInstField = false; } else { Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth, InitStyle, AS); + assert(Member && "HandleField never returns null"); } - assert(Member && "HandleField never returns null"); } else { assert(InitStyle == ICIS_NoInit || D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static); Member = HandleDeclarator(S, D, TemplateParameterLists); - if (!Member) { + if (!Member) return 0; - } // Non-instance-fields can't have a bitfield. if (BitWidth) { @@ -1974,16 +2073,19 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, Member->setAccess(AS); - // If we have declared a member function template, set the access of the - // templated declaration as well. + // If we have declared a member function template or static data member + // template, set the access of the templated declaration as well. if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member)) FunTmpl->getTemplatedDecl()->setAccess(AS); + else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member)) + VarTmpl->getTemplatedDecl()->setAccess(AS); } if (VS.isOverrideSpecified()) Member->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context)); if (VS.isFinalSpecified()) - Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context)); + Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context, + VS.isFinalSpelledSealed())); if (VS.getLastLocation().isValid()) { // Update the end location of a method that has a virt-specifiers. @@ -2020,57 +2122,71 @@ namespace { class UninitializedFieldVisitor : public EvaluatedExprVisitor<UninitializedFieldVisitor> { Sema &S; - ValueDecl *VD; + // List of Decls to generate a warning on. Also remove Decls that become + // initialized. + llvm::SmallPtrSet<ValueDecl*, 4> &Decls; + // If non-null, add a note to the warning pointing back to the constructor. + const CXXConstructorDecl *Constructor; public: typedef EvaluatedExprVisitor<UninitializedFieldVisitor> Inherited; - UninitializedFieldVisitor(Sema &S, ValueDecl *VD) : Inherited(S.Context), - S(S) { - if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(VD)) - this->VD = IFD->getAnonField(); - else - this->VD = VD; - } - - void HandleExpr(Expr *E) { - if (!E) return; + UninitializedFieldVisitor(Sema &S, + llvm::SmallPtrSet<ValueDecl*, 4> &Decls, + const CXXConstructorDecl *Constructor) + : Inherited(S.Context), S(S), Decls(Decls), + Constructor(Constructor) { } + + void HandleMemberExpr(MemberExpr *ME, bool CheckReferenceOnly) { + if (isa<EnumConstantDecl>(ME->getMemberDecl())) + return; - // Expressions like x(x) sometimes lack the surrounding expressions - // but need to be checked anyways. - HandleValue(E); - Visit(E); - } + // FieldME is the inner-most MemberExpr that is not an anonymous struct + // or union. + MemberExpr *FieldME = ME; - void HandleValue(Expr *E) { - E = E->IgnoreParens(); + Expr *Base = ME; + while (isa<MemberExpr>(Base)) { + ME = cast<MemberExpr>(Base); - if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) { - if (isa<EnumConstantDecl>(ME->getMemberDecl())) + if (isa<VarDecl>(ME->getMemberDecl())) return; - // FieldME is the inner-most MemberExpr that is not an anonymous struct - // or union. - MemberExpr *FieldME = ME; + if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) + if (!FD->isAnonymousStructOrUnion()) + FieldME = ME; - Expr *Base = E; - while (isa<MemberExpr>(Base)) { - ME = cast<MemberExpr>(Base); + Base = ME->getBase(); + } - if (isa<VarDecl>(ME->getMemberDecl())) - return; + if (!isa<CXXThisExpr>(Base)) + return; - if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) - if (!FD->isAnonymousStructOrUnion()) - FieldME = ME; + ValueDecl* FoundVD = FieldME->getMemberDecl(); - Base = ME->getBase(); - } + if (!Decls.count(FoundVD)) + return; - if (VD == FieldME->getMemberDecl() && isa<CXXThisExpr>(Base)) { - unsigned diag = VD->getType()->isReferenceType() - ? diag::warn_reference_field_is_uninit - : diag::warn_field_is_uninit; - S.Diag(FieldME->getExprLoc(), diag) << VD; - } + const bool IsReference = FoundVD->getType()->isReferenceType(); + + // Prevent double warnings on use of unbounded references. + if (IsReference != CheckReferenceOnly) + return; + + unsigned diag = IsReference + ? diag::warn_reference_field_is_uninit + : diag::warn_field_is_uninit; + S.Diag(FieldME->getExprLoc(), diag) << FoundVD; + if (Constructor) + S.Diag(Constructor->getLocation(), + diag::note_uninit_in_this_constructor) + << (Constructor->isDefaultConstructor() && Constructor->isImplicit()); + + } + + void HandleValue(Expr *E) { + E = E->IgnoreParens(); + + if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) { + HandleMemberExpr(ME, false /*CheckReferenceOnly*/); return; } @@ -2102,6 +2218,13 @@ namespace { } } + void VisitMemberExpr(MemberExpr *ME) { + // All uses of unbounded reference fields will warn. + HandleMemberExpr(ME, true /*CheckReferenceOnly*/); + + Inherited::VisitMemberExpr(ME); + } + void VisitImplicitCastExpr(ImplicitCastExpr *E) { if (E->getCastKind() == CK_LValueToRValue) HandleValue(E->getSubExpr()); @@ -2109,6 +2232,16 @@ namespace { Inherited::VisitImplicitCastExpr(E); } + void VisitCXXConstructExpr(CXXConstructExpr *E) { + if (E->getConstructor()->isCopyConstructor()) + if (ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(E->getArg(0))) + if (ICE->getCastKind() == CK_NoOp) + if (MemberExpr *ME = dyn_cast<MemberExpr>(ICE->getSubExpr())) + HandleMemberExpr(ME, false /*CheckReferenceOnly*/); + + Inherited::VisitCXXConstructExpr(E); + } + void VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { Expr *Callee = E->getCallee(); if (isa<MemberExpr>(Callee)) @@ -2116,10 +2249,85 @@ namespace { Inherited::VisitCXXMemberCallExpr(E); } + + void VisitBinaryOperator(BinaryOperator *E) { + // If a field assignment is detected, remove the field from the + // uninitiailized field set. + if (E->getOpcode() == BO_Assign) + if (MemberExpr *ME = dyn_cast<MemberExpr>(E->getLHS())) + if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) + if (!FD->getType()->isReferenceType()) + Decls.erase(FD); + + Inherited::VisitBinaryOperator(E); + } }; - static void CheckInitExprContainsUninitializedFields(Sema &S, Expr *E, - ValueDecl *VD) { - UninitializedFieldVisitor(S, VD).HandleExpr(E); + static void CheckInitExprContainsUninitializedFields( + Sema &S, Expr *E, llvm::SmallPtrSet<ValueDecl*, 4> &Decls, + const CXXConstructorDecl *Constructor) { + if (Decls.size() == 0) + return; + + if (!E) + return; + + if (CXXDefaultInitExpr *Default = dyn_cast<CXXDefaultInitExpr>(E)) { + E = Default->getExpr(); + if (!E) + return; + // In class initializers will point to the constructor. + UninitializedFieldVisitor(S, Decls, Constructor).Visit(E); + } else { + UninitializedFieldVisitor(S, Decls, 0).Visit(E); + } + } + + // Diagnose value-uses of fields to initialize themselves, e.g. + // foo(foo) + // where foo is not also a parameter to the constructor. + // Also diagnose across field uninitialized use such as + // x(y), y(x) + // TODO: implement -Wuninitialized and fold this into that framework. + static void DiagnoseUninitializedFields( + Sema &SemaRef, const CXXConstructorDecl *Constructor) { + + if (SemaRef.getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit, + Constructor->getLocation()) + == DiagnosticsEngine::Ignored) { + return; + } + + if (Constructor->isInvalidDecl()) + return; + + const CXXRecordDecl *RD = Constructor->getParent(); + + // Holds fields that are uninitialized. + llvm::SmallPtrSet<ValueDecl*, 4> UninitializedFields; + + // At the beginning, all fields are uninitialized. + for (DeclContext::decl_iterator I = RD->decls_begin(), E = RD->decls_end(); + I != E; ++I) { + if (FieldDecl *FD = dyn_cast<FieldDecl>(*I)) { + UninitializedFields.insert(FD); + } else if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(*I)) { + UninitializedFields.insert(IFD->getAnonField()); + } + } + + for (CXXConstructorDecl::init_const_iterator FieldInit = + Constructor->init_begin(), + FieldInitEnd = Constructor->init_end(); + FieldInit != FieldInitEnd; ++FieldInit) { + + Expr *InitExpr = (*FieldInit)->getInit(); + + CheckInitExprContainsUninitializedFields( + SemaRef, InitExpr, UninitializedFields, Constructor); + + if (FieldDecl *Field = (*FieldInit)->getAnyMember()) + UninitializedFields.erase(Field); + } } } // namespace @@ -2146,17 +2354,8 @@ Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation InitLoc, return; } - if (getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit, InitLoc) - != DiagnosticsEngine::Ignored) { - CheckInitExprContainsUninitializedFields(*this, InitExpr, FD); - } - ExprResult Init = InitExpr; if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { - if (isa<InitListExpr>(InitExpr) && isStdInitializerList(FD->getType(), 0)) { - Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list) - << /*at end of ctor*/1 << InitExpr->getSourceRange(); - } InitializedEntity Entity = InitializedEntity::InitializeMember(FD); InitializationKind Kind = FD->getInClassInitStyle() == ICIS_ListInit ? InitializationKind::CreateDirectList(InitExpr->getLocStart()) @@ -2254,12 +2453,11 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, const DeclSpec &DS, SourceLocation IdLoc, SourceLocation LParenLoc, - Expr **Args, unsigned NumArgs, + ArrayRef<Expr *> Args, SourceLocation RParenLoc, SourceLocation EllipsisLoc) { Expr *List = new (Context) ParenListExpr(Context, LParenLoc, - llvm::makeArrayRef(Args, NumArgs), - RParenLoc); + Args, RParenLoc); return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, DS, IdLoc, List, EllipsisLoc); } @@ -2269,21 +2467,20 @@ 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: +public: explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl) : ClassDecl(ClassDecl) {} - virtual bool ValidateCandidate(const TypoCorrection &candidate) { + bool ValidateCandidate(const TypoCorrection &candidate) LLVM_OVERRIDE { if (NamedDecl *ND = candidate.getCorrectionDecl()) { if (FieldDecl *Member = dyn_cast<FieldDecl>(ND)) return Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl); - else - return isa<TypeDecl>(ND); + return isa<TypeDecl>(ND); } return false; } - private: +private: CXXRecordDecl *ClassDecl; }; @@ -2389,18 +2586,13 @@ Sema::BuildMemInitializer(Decl *ConstructorD, if (R.empty() && BaseType.isNull() && (Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS, Validator, ClassDecl))) { - std::string CorrectedStr(Corr.getAsString(getLangOpts())); - std::string CorrectedQuotedStr(Corr.getQuoted(getLangOpts())); if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) { // We have found a non-static data member with a similar // name to what was typed; complain and initialize that // 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; - + diagnoseTypo(Corr, + PDiag(diag::err_mem_init_not_member_or_class_suggest) + << MemberOrBase << true); return BuildMemberInitializer(Member, Init, IdLoc); } else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) { const CXXBaseSpecifier *DirectBaseSpec; @@ -2411,12 +2603,13 @@ Sema::BuildMemInitializer(Decl *ConstructorD, // We have found a direct or virtual base class with a // similar name to what was typed; complain and initialize // that base class. - Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest) - << MemberOrBase << false << CorrectedQuotedStr - << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); + diagnoseTypo(Corr, + PDiag(diag::err_mem_init_not_member_or_class_suggest) + << MemberOrBase << false, + PDiag() /*Suppress note, we provide our own.*/); - const CXXBaseSpecifier *BaseSpec = DirectBaseSpec? DirectBaseSpec - : VirtualBaseSpec; + const CXXBaseSpecifier *BaseSpec = DirectBaseSpec ? DirectBaseSpec + : VirtualBaseSpec; Diag(BaseSpec->getLocStart(), diag::note_base_class_specified_here) << BaseSpec->getType() @@ -2480,15 +2673,7 @@ static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member, } } - if (isa<MaterializeTemporaryExpr>(Init->IgnoreParens())) { - // Taking the address of a temporary will be diagnosed as a hard error. - if (IsPointer) - return; - - S.Diag(Init->getExprLoc(), diag::warn_bind_ref_member_to_temporary) - << Member << Init->getSourceRange(); - } else if (const DeclRefExpr *DRE - = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) { + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) { // We only warn when referring to a non-reference parameter declaration. const ParmVarDecl *Parameter = dyn_cast<ParmVarDecl>(DRE->getDecl()); if (!Parameter || Parameter->getType()->isReferenceType()) @@ -2521,10 +2706,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, if (Member->isInvalidDecl()) return true; - // Diagnose value-uses of fields to initialize themselves, e.g. - // foo(foo) - // where foo is not also a parameter to the constructor. - // TODO: implement -Wuninitialized and fold this into that framework. MultiExprArg Args; if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs()); @@ -2535,19 +2716,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, Args = Init; } - if (getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit, IdLoc) - != DiagnosticsEngine::Ignored) - for (unsigned i = 0, e = Args.size(); i != e; ++i) - // FIXME: Warn about the case when other fields are used before being - // initialized. 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 - // fields are used, as they are not yet initialized. - // Right now we are only handling the case where the i'th field uses - // itself in its initializer. - // Also need to take into account that some fields may be initialized by - // in-class initializers, see C++11 [class.base.init]p9. - CheckInitExprContainsUninitializedFields(*this, Args[i], Member); - SourceRange InitRange = Init->getSourceRange(); if (Member->getType()->isDependentType() || Init->isTypeDependent()) { @@ -2559,11 +2727,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, if (isa<InitListExpr>(Init)) { InitList = true; Args = Init; - - if (isStdInitializerList(Member->getType(), 0)) { - Diag(IdLoc, diag::warn_dangling_std_initializer_list) - << /*at end of ctor*/1 << InitRange; - } } // Initialize the member. @@ -2580,6 +2743,8 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, if (MemberInit.isInvalid()) return true; + CheckForDanglingReferenceOrPointer(*this, Member, MemberInit.get(), IdLoc); + // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. @@ -2588,7 +2753,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, return true; Init = MemberInit.get(); - CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc); } if (DirectMember) { @@ -2742,9 +2906,9 @@ 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); + const CXXBaseSpecifier *BaseSpec = DirectBaseSpec; if (!BaseSpec) - BaseSpec = const_cast<CXXBaseSpecifier *>(VirtualBaseSpec); + BaseSpec = VirtualBaseSpec; // Initialize the base. bool InitList = true; @@ -3228,6 +3392,8 @@ static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) { static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info, FieldDecl *Field, IndirectFieldDecl *Indirect = 0) { + if (Field->isInvalidDecl()) + return false; // Overwhelmingly common case: we have a direct initializer for this field. if (CXXCtorInitializer *Init = Info.AllBaseFields.lookup(Field)) @@ -3266,7 +3432,7 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info, // 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). - if (Info.AnyErrorsInInits || Field->isInvalidDecl()) + if (Info.AnyErrorsInInits) return false; CXXCtorInitializer *Init = 0; @@ -3333,7 +3499,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors, for (unsigned i = 0; i < Initializers.size(); i++) { CXXCtorInitializer *Member = Initializers[i]; - + if (Member->isBaseInitializer()) Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member; else @@ -3354,12 +3520,28 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors, if (CXXCtorInitializer *Value = Info.AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) { + // [class.base.init]p7, per DR257: + // A mem-initializer where the mem-initializer-id names a virtual base + // class is ignored during execution of a constructor of any class that + // is not the most derived class. + if (ClassDecl->isAbstract()) { + // FIXME: Provide a fixit to remove the base specifier. This requires + // tracking the location of the associated comma for a base specifier. + Diag(Value->getSourceLocation(), diag::warn_abstract_vbase_init_ignored) + << VBase->getType() << ClassDecl; + DiagnoseAbstractType(ClassDecl); + } + Info.AllToInit.push_back(Value); - } else if (!AnyErrors) { + } else if (!AnyErrors && !ClassDecl->isAbstract()) { + // [class.base.init]p8, per DR257: + // If a given [...] base class is not named by a mem-initializer-id + // [...] and the entity is not a virtual base class of an abstract + // class, then [...] the entity is default-initialized. bool IsInheritedVirtualBase = !DirectVBases.count(VBase); CXXCtorInitializer *CXXBaseInit; if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK, - VBase, IsInheritedVirtualBase, + VBase, IsInheritedVirtualBase, CXXBaseInit)) { HadError = true; continue; @@ -3465,12 +3647,12 @@ static void PopulateKeysForFields(FieldDecl *Field, SmallVectorImpl<const void*> IdealInits.push_back(Field); } -static void *GetKeyForBase(ASTContext &Context, QualType BaseType) { - return const_cast<Type*>(Context.getCanonicalType(BaseType).getTypePtr()); +static const void *GetKeyForBase(ASTContext &Context, QualType BaseType) { + return Context.getCanonicalType(BaseType).getTypePtr(); } -static void *GetKeyForMember(ASTContext &Context, - CXXCtorInitializer *Member) { +static const void *GetKeyForMember(ASTContext &Context, + CXXCtorInitializer *Member) { if (!Member->isAnyMemberInitializer()) return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0)); @@ -3534,7 +3716,7 @@ static void DiagnoseBaseOrMemInitializerOrder( CXXCtorInitializer *PrevInit = 0; for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) { CXXCtorInitializer *Init = Inits[InitIndex]; - void *InitKey = GetKeyForMember(SemaRef.Context, Init); + const void *InitKey = GetKeyForMember(SemaRef.Context, Init); // Scan forward to try to find this initializer in the idealized // initializers list. @@ -3660,7 +3842,7 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl, // Mapping for the duplicate initializers check. // For member initializers, this is keyed with a FieldDecl*. // For base initializers, this is keyed with a Type*. - llvm::DenseMap<void*, CXXCtorInitializer *> Members; + llvm::DenseMap<const void *, CXXCtorInitializer *> Members; // Mapping for the inconsistent anonymous-union initializers check. RedundantUnionMap MemberUnions; @@ -3678,7 +3860,8 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl, CheckRedundantUnionInit(*this, Init, MemberUnions)) HadError = true; } else if (Init->isBaseInitializer()) { - void *Key = GetKeyForBase(Context, QualType(Init->getBaseClass(), 0)); + const void *Key = + GetKeyForBase(Context, QualType(Init->getBaseClass(), 0)); if (CheckRedundantInit(*this, Init, Members[Key])) HadError = true; } else { @@ -3702,6 +3885,8 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl, DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits); SetCtorInitializers(Constructor, AnyErrors, MemInits); + + DiagnoseUninitializedFields(*this, Constructor); } void @@ -3750,7 +3935,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, << Field->getDeclName() << FieldType); - MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + MarkFunctionReferenced(Location, Dtor); DiagnoseUseOfDecl(Dtor, Location); } @@ -3783,7 +3968,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, << Base->getSourceRange(), Context.getTypeDeclType(ClassDecl)); - MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + MarkFunctionReferenced(Location, Dtor); DiagnoseUseOfDecl(Dtor, Location); } @@ -3807,12 +3992,19 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); assert(Dtor && "No dtor found for BaseClassDecl!"); - CheckDestructorAccess(ClassDecl->getLocation(), Dtor, - PDiag(diag::err_access_dtor_vbase) - << VBase->getType(), - Context.getTypeDeclType(ClassDecl)); - - MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + if (CheckDestructorAccess( + ClassDecl->getLocation(), Dtor, + PDiag(diag::err_access_dtor_vbase) + << Context.getTypeDeclType(ClassDecl) << VBase->getType(), + Context.getTypeDeclType(ClassDecl)) == + AR_accessible) { + CheckDerivedToBaseConversion( + Context.getTypeDeclType(ClassDecl), VBase->getType(), + diag::err_access_dtor_vbase, 0, ClassDecl->getLocation(), + SourceRange(), DeclarationName(), 0); + } + + MarkFunctionReferenced(Location, Dtor); DiagnoseUseOfDecl(Dtor, Location); } } @@ -3822,8 +4014,10 @@ void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) { return; if (CXXConstructorDecl *Constructor - = dyn_cast<CXXConstructorDecl>(CDtorDecl)) + = dyn_cast<CXXConstructorDecl>(CDtorDecl)) { SetCtorInitializers(Constructor, /*AnyErrors=*/false); + DiagnoseUninitializedFields(*this, Constructor); + } } bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, @@ -3835,8 +4029,8 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, public: NonAbstractTypeDiagnoser(unsigned DiagID, AbstractDiagSelID SelID) : TypeDiagnoser(DiagID == 0), DiagID(DiagID), SelID(SelID) { } - - virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) { + + void diagnose(Sema &S, SourceLocation Loc, QualType T) LLVM_OVERRIDE { if (Suppressed) return; if (SelID == -1) S.Diag(Loc, DiagID) << T; @@ -3893,6 +4087,12 @@ void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) { if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD)) return; + // If the diagnostic is suppressed, don't emit the notes. We're only + // going to emit them once, so try to attach them to a diagnostic we're + // actually going to show. + if (Diags.isLastDiagnosticIgnored()) + return; + CXXFinalOverriderMap FinalOverriders; RD->getFinalOverriders(FinalOverriders); @@ -4172,9 +4372,12 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { diag::warn_non_virtual_dtor) << Context.getRecordType(Record); } - if (Record->isAbstract() && Record->hasAttr<FinalAttr>()) { - Diag(Record->getLocation(), diag::warn_abstract_final_class); - DiagnoseAbstractType(Record); + if (Record->isAbstract()) { + if (FinalAttr *FA = Record->getAttr<FinalAttr>()) { + Diag(Record->getLocation(), diag::warn_abstract_final_class) + << FA->isSpelledAsSealed(); + DiagnoseAbstractType(Record); + } } if (!Record->isDependentType()) { @@ -4184,7 +4387,7 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { // See if a method overloads virtual methods in a base // class without overriding any. if (!M->isStatic()) - DiagnoseHiddenVirtualMethods(Record, *M); + DiagnoseHiddenVirtualMethods(*M); // Check whether the explicitly-defaulted special members are valid. if (!M->isInvalidDecl() && M->isExplicitlyDefaulted()) @@ -4243,6 +4446,13 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { } } + // Check to see if we're trying to lay out a struct using the ms_struct + // attribute that is dynamic. + if (Record->isMsStruct(Context) && Record->isDynamicClass()) { + Diag(Record->getLocation(), diag::warn_pragma_ms_struct_failed); + Record->dropAttr<MsStructAttr>(); + } + // Declare inheriting constructors. We do this eagerly here because: // - The standard requires an eager diagnostic for conflicting inheriting // constructors from different classes. @@ -4278,6 +4488,7 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, // C++11 [dcl.constexpr]p4: // In the definition of a constexpr constructor [...] + bool Ctor = true; switch (CSM) { case Sema::CXXDefaultConstructor: // Since default constructor lookup is essentially trivial (and cannot @@ -4295,6 +4506,12 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, case Sema::CXXCopyAssignment: case Sema::CXXMoveAssignment: + if (!S.getLangOpts().CPlusPlus1y) + return false; + // In C++1y, we need to perform overload resolution. + Ctor = false; + break; + case Sema::CXXDestructor: case Sema::CXXInvalid: return false; @@ -4307,15 +4524,22 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, // If we squint, this is guaranteed, since exactly one non-static data member // will be initialized (if the constructor isn't deleted), we just don't know // which one. - if (ClassDecl->isUnion()) + if (Ctor && ClassDecl->isUnion()) return true; // -- the class shall not have any virtual base classes; - if (ClassDecl->getNumVBases()) + if (Ctor && ClassDecl->getNumVBases()) + return false; + + // C++1y [class.copy]p26: + // -- [the class] is a literal type, and + if (!Ctor && !ClassDecl->isLiteral()) return false; // -- every constructor involved in initializing [...] base class // sub-objects shall be a constexpr constructor; + // -- the assignment operator selected to copy/move each direct base + // class is a constexpr function, and for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(), BEnd = ClassDecl->bases_end(); B != BEnd; ++B) { @@ -4331,6 +4555,9 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, // [...] shall be a constexpr constructor; // -- every non-static data member and base class sub-object shall be // initialized + // -- for each non-stastic data member of X that is of class type (or array + // thereof), the assignment operator selected to copy/move that member is + // a constexpr function for (RecordDecl::field_iterator F = ClassDecl->field_begin(), FEnd = ClassDecl->field_end(); F != FEnd; ++F) { @@ -4380,6 +4607,21 @@ updateExceptionSpec(Sema &S, FunctionDecl *FD, const FunctionProtoType *FPT, FPT->getArgTypes(), EPI)); } +static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S, + CXXMethodDecl *MD) { + FunctionProtoType::ExtProtoInfo EPI; + + // Build an exception specification pointing back at this member. + EPI.ExceptionSpecType = EST_Unevaluated; + EPI.ExceptionSpecDecl = MD; + + // Set the calling convention to the default for C++ instance methods. + EPI.ExtInfo = EPI.ExtInfo.withCallingConv( + S.Context.getDefaultCallingConvention(/*IsVariadic=*/false, + /*IsCXXMethod=*/true)); + return EPI; +} + void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD) { const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); if (FPT->getExceptionSpecType() != EST_Unevaluated) @@ -4461,7 +4703,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { // A defaulted special member cannot have cv-qualifiers. if (Type->getTypeQuals()) { Diag(MD->getLocation(), diag::err_defaulted_special_member_quals) - << (CSM == CXXMoveAssignment); + << (CSM == CXXMoveAssignment) << getLangOpts().CPlusPlus1y; HadError = true; } } @@ -4506,13 +4748,16 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { // would have been implicitly declared as constexpr, // Do not apply this rule to members of class templates, since core issue 1358 // makes such functions always instantiate to constexpr functions. For - // non-constructors, this is checked elsewhere. + // functions which cannot be constexpr (for non-constructors in C++11 and for + // destructors in C++1y), this is checked elsewhere. bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, RD, CSM, HasConstParam); - if (isa<CXXConstructorDecl>(MD) && MD->isConstexpr() && !Constexpr && + if ((getLangOpts().CPlusPlus1y ? !isa<CXXDestructorDecl>(MD) + : isa<CXXConstructorDecl>(MD)) && + MD->isConstexpr() && !Constexpr && MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { Diag(MD->getLocStart(), diag::err_incorrect_defaulted_constexpr) << CSM; - // FIXME: Explain why the constructor can't be constexpr. + // FIXME: Explain why the special member can't be constexpr. HadError = true; } @@ -4573,7 +4818,9 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { void Sema::CheckExplicitlyDefaultedMemberExceptionSpec( CXXMethodDecl *MD, const FunctionProtoType *SpecifiedType) { // Compute the implicit exception specification. - FunctionProtoType::ExtProtoInfo EPI; + CallingConv CC = Context.getDefaultCallingConvention(/*IsVariadic=*/false, + /*IsCXXMethod=*/true); + FunctionProtoType::ExtProtoInfo EPI(CC); computeImplicitExceptionSpec(*this, MD->getLocation(), MD).getEPI(EPI); const FunctionProtoType *ImplicitType = cast<FunctionProtoType>( Context.getFunctionType(Context.VoidTy, None, EPI)); @@ -4586,14 +4833,28 @@ void Sema::CheckExplicitlyDefaultedMemberExceptionSpec( SpecifiedType, MD->getLocation()); } -void Sema::CheckDelayedExplicitlyDefaultedMemberExceptionSpecs() { - for (unsigned I = 0, N = DelayedDefaultedMemberExceptionSpecs.size(); - I != N; ++I) - CheckExplicitlyDefaultedMemberExceptionSpec( - DelayedDefaultedMemberExceptionSpecs[I].first, - DelayedDefaultedMemberExceptionSpecs[I].second); +void Sema::CheckDelayedMemberExceptionSpecs() { + SmallVector<std::pair<const CXXDestructorDecl *, const CXXDestructorDecl *>, + 2> Checks; + SmallVector<std::pair<CXXMethodDecl *, const FunctionProtoType *>, 2> Specs; - DelayedDefaultedMemberExceptionSpecs.clear(); + std::swap(Checks, DelayedDestructorExceptionSpecChecks); + std::swap(Specs, DelayedDefaultedMemberExceptionSpecs); + + // Perform any deferred checking of exception specifications for virtual + // destructors. + for (unsigned i = 0, e = Checks.size(); i != e; ++i) { + const CXXDestructorDecl *Dtor = Checks[i].first; + assert(!Dtor->getParent()->isDependentType() && + "Should not ever add destructors of templates into the list."); + CheckOverridingFunctionExceptionSpec(Dtor, Checks[i].second); + } + + // Check that any explicitly-defaulted methods have exception specifications + // compatible with their implicit exception specifications. + for (unsigned I = 0, N = Specs.size(); I != N; ++I) + CheckExplicitlyDefaultedMemberExceptionSpec(Specs[I].first, + Specs[I].second); } namespace { @@ -4652,6 +4913,10 @@ struct SpecialMemberDeletionInfo { // cv-qualifiers on class members don't affect default ctor / dtor calls. if (CSM == Sema::CXXDefaultConstructor || CSM == Sema::CXXDestructor) Quals = 0; + // cv-qualifiers on class members affect the type of both '*this' and the + // argument for an assignment. + if (IsAssignment) + TQ |= Quals; return S.LookupSpecialMember(Class, CSM, ConstArg || (Quals & Qualifiers::Const), VolatileArg || (Quals & Qualifiers::Volatile), @@ -5015,10 +5280,15 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, SMI.shouldDeleteForBase(BI)) return true; - for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), - BE = RD->vbases_end(); BI != BE; ++BI) - if (SMI.shouldDeleteForBase(BI)) - return true; + // Per DR1611, do not consider virtual bases of constructors of abstract + // classes, since we are not going to construct them. + if (!RD->isAbstract() || !SMI.IsConstructor) { + for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), + BE = RD->vbases_end(); + BI != BE; ++BI) + if (SMI.shouldDeleteForBase(BI)) + return true; + } for (CXXRecordDecl::field_iterator FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI) @@ -5310,9 +5580,9 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, bool ConstArg = false; - // C++11 [class.copy]p12, p25: - // A [special member] is trivial if its declared parameter type is the same - // as if it had been implicitly declared [...] + // C++11 [class.copy]p12, p25: [DR1593] + // A [special member] is trivial if [...] its parameter-type-list is + // equivalent to the parameter-type-list of an implicit declaration [...] switch (CSM) { case CXXDefaultConstructor: case CXXDestructor: @@ -5356,11 +5626,6 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, llvm_unreachable("not a special member"); } - // FIXME: We require that the parameter-declaration-clause is equivalent to - // that of an implicit declaration, not just that the declared parameter type - // matches, in order to prevent absuridities like a function simultaneously - // being a trivial copy constructor and a non-trivial default constructor. - // This issue has not yet been assigned a core issue number. if (MD->getMinRequiredArguments() < MD->getNumParams()) { if (Diagnose) Diag(MD->getParamDecl(MD->getMinRequiredArguments())->getLocation(), @@ -5524,12 +5789,10 @@ static void AddMostOverridenMethods(const CXXMethodDecl *MD, AddMostOverridenMethods(*I, Methods); } -/// \brief See if a method overloads virtual methods in a base class without +/// \brief Check if a method overloads virtual methods in a base class without /// overriding any. -void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { - if (Diags.getDiagnosticLevel(diag::warn_overloaded_virtual, - MD->getLocation()) == DiagnosticsEngine::Ignored) - return; +void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD, + SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) { if (!MD->getDeclName().isIdentifier()) return; @@ -5542,6 +5805,7 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { // Keep the base methods that were overriden or introduced in the subclass // by 'using' in a set. A base method not in this set is hidden. + CXXRecordDecl *DC = MD->getParent(); DeclContext::lookup_result R = DC->lookup(MD->getDeclName()); for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { NamedDecl *ND = *I; @@ -5551,18 +5815,38 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { AddMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods); } - if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths) && - !Data.OverloadedMethods.empty()) { + if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths)) + OverloadedMethods = Data.OverloadedMethods; +} + +void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD, + SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) { + for (unsigned i = 0, e = OverloadedMethods.size(); i != e; ++i) { + CXXMethodDecl *overloadedMD = OverloadedMethods[i]; + PartialDiagnostic PD = PDiag( + diag::note_hidden_overloaded_virtual_declared_here) << overloadedMD; + HandleFunctionTypeMismatch(PD, MD->getType(), overloadedMD->getType()); + Diag(overloadedMD->getLocation(), PD); + } +} + +/// \brief Diagnose methods which overload virtual methods in a base class +/// without overriding any. +void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) { + if (MD->isInvalidDecl()) + return; + + if (Diags.getDiagnosticLevel(diag::warn_overloaded_virtual, + MD->getLocation()) == DiagnosticsEngine::Ignored) + return; + + SmallVector<CXXMethodDecl *, 8> OverloadedMethods; + FindHiddenVirtualMethods(MD, OverloadedMethods); + if (!OverloadedMethods.empty()) { Diag(MD->getLocation(), diag::warn_overloaded_virtual) - << MD << (Data.OverloadedMethods.size() > 1); + << MD << (OverloadedMethods.size() > 1); - for (unsigned i = 0, e = Data.OverloadedMethods.size(); i != e; ++i) { - CXXMethodDecl *overloadedMD = Data.OverloadedMethods[i]; - PartialDiagnostic PD = PDiag( - diag::note_hidden_overloaded_virtual_declared_here) << overloadedMD; - HandleFunctionTypeMismatch(PD, MD->getType(), overloadedMD->getType()); - Diag(overloadedMD->getLocation(), PD); - } + NoteHiddenVirtualMethods(MD, OverloadedMethods); } } @@ -5877,7 +6161,7 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { CXXRecordDecl *RD = Destructor->getParent(); - if (Destructor->isVirtual()) { + if (!Destructor->getOperatorDelete() && Destructor->isVirtual()) { SourceLocation Loc; if (!Destructor->isImplicit()) @@ -5891,6 +6175,10 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { Context.DeclarationNames.getCXXOperatorName(OO_Delete); if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete)) return true; + // If there's no class-specific operator delete, look up the global + // non-array delete. + if (!OperatorDelete) + OperatorDelete = FindUsualDeallocationFunction(Loc, true, Name); MarkFunctionReferenced(Loc, OperatorDelete); @@ -6029,8 +6317,8 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, if (SC == SC_Static) { if (!D.isInvalidType()) Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member) - << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc()) - << SourceRange(D.getIdentifierLoc()); + << SourceRange(D.getDeclSpec().getStorageClassSpecLoc()) + << D.getName().getSourceRange(); D.setInvalidType(); SC = SC_None; } @@ -6541,11 +6829,10 @@ 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()) { +public: + bool ValidateCandidate(const TypoCorrection &candidate) LLVM_OVERRIDE { + if (NamedDecl *ND = candidate.getCorrectionDecl()) return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND); - } return false; } }; @@ -6561,21 +6848,19 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc, if (TypoCorrection Corrected = S.CorrectTypo(R.getLookupNameInfo(), 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(Corrected.getCorrectionRange(), - 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; - + if (DeclContext *DC = S.computeDeclContext(SS, false)) { + std::string CorrectedStr(Corrected.getAsString(S.getLangOpts())); + bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && + Ident->getName().equals(CorrectedStr); + S.diagnoseTypo(Corrected, + S.PDiag(diag::err_using_directive_member_suggest) + << Ident << DC << DroppedSpecifier << SS.getRange(), + S.PDiag(diag::note_namespace_defined_here)); + } else { + S.diagnoseTypo(Corrected, + S.PDiag(diag::err_using_directive_suggest) << Ident, + S.PDiag(diag::note_namespace_defined_here)); + } R.addDecl(Corrected.getCorrectionDecl()); return true; } @@ -6649,7 +6934,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, IdentLoc, Named, CommonAncestor); if (IsUsingDirectiveInToplevelContext(CurContext) && - !SourceMgr.isFromMainFile(SourceMgr.getExpansionLoc(IdentLoc))) { + !SourceMgr.isInMainFile(SourceMgr.getExpansionLoc(IdentLoc))) { Diag(IdentLoc, diag::warn_using_directive_in_header); } @@ -6668,7 +6953,7 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { // 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()); + DeclContext *Ctx = S->getEntity(); if (Ctx && !Ctx->isFunctionOrMethod()) Ctx->addDecl(UDir); else @@ -6685,7 +6970,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, CXXScopeSpec &SS, UnqualifiedId &Name, AttributeList *AttrList, - bool IsTypeName, + bool HasTypenameKeyword, SourceLocation TypenameLoc) { assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); @@ -6727,13 +7012,10 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, return 0; // Warn about access declarations. - // TODO: store that the declaration was written without 'using' and - // talk about access decls instead of using decls in the - // diagnostics. if (!HasUsingKeyword) { - UsingLoc = Name.getLocStart(); - - Diag(UsingLoc, diag::warn_access_decl_deprecated) + Diag(Name.getLocStart(), + getLangOpts().CPlusPlus11 ? diag::err_access_decl + : diag::warn_access_decl_deprecated) << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using "); } @@ -6744,7 +7026,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS, TargetNameInfo, AttrList, /* IsInstantiation */ false, - IsTypeName, TypenameLoc); + HasTypenameKeyword, TypenameLoc); if (UD) PushOnScopeChains(UD, S, /*AddToContext*/ false); @@ -6754,20 +7036,15 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, /// \brief Determine whether a using declaration considers the given /// declarations as "equivalent", e.g., if they are redeclarations of /// the same entity or are both typedefs of the same type. -static bool -IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2, - bool &SuppressRedeclaration) { - if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) { - SuppressRedeclaration = false; +static bool +IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2) { + if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) return true; - } if (TypedefNameDecl *TD1 = dyn_cast<TypedefNameDecl>(D1)) - if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2)) { - SuppressRedeclaration = true; + if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2)) return Context.hasSameType(TD1->getUnderlyingType(), TD2->getUnderlyingType()); - } return false; } @@ -6776,7 +7053,8 @@ IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2, /// Determines whether to create a using shadow decl for a particular /// decl, given the set of decls existing prior to this using lookup. bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, - const LookupResult &Previous) { + const LookupResult &Previous, + UsingShadowDecl *&PrevShadow) { // Diagnose finding a decl which is not from a base class of the // current class. We do this now because there are cases where this // function will silently decide not to build a shadow decl, which @@ -6836,16 +7114,22 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, // FIXME: but we might be increasing its access, in which case we // should redeclare it. NamedDecl *NonTag = 0, *Tag = 0; + bool FoundEquivalentDecl = false; for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); I != E; ++I) { NamedDecl *D = (*I)->getUnderlyingDecl(); - bool Result; - if (IsEquivalentForUsingDecl(Context, D, Target, Result)) - return Result; + if (IsEquivalentForUsingDecl(Context, D, Target)) { + if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(*I)) + PrevShadow = Shadow; + FoundEquivalentDecl = true; + } (isa<TagDecl>(D) ? Tag : NonTag) = D; } + if (FoundEquivalentDecl) + return false; + if (Target->isFunctionOrFunctionTemplate()) { FunctionDecl *FD; if (isa<FunctionTemplateDecl>(Target)) @@ -6904,7 +7188,8 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, /// Builds a shadow declaration corresponding to a 'using' declaration. UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S, UsingDecl *UD, - NamedDecl *Orig) { + NamedDecl *Orig, + UsingShadowDecl *PrevDecl) { // If we resolved to another shadow declaration, just coalesce them. NamedDecl *Target = Orig; @@ -6912,16 +7197,18 @@ UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S, Target = cast<UsingShadowDecl>(Target)->getTargetDecl(); assert(!isa<UsingShadowDecl>(Target) && "nested shadow declaration"); } - + UsingShadowDecl *Shadow = UsingShadowDecl::Create(Context, CurContext, UD->getLocation(), UD, Target); UD->addShadowDecl(Shadow); - + Shadow->setAccess(UD->getAccess()); if (Orig->isInvalidDecl() || UD->isInvalidDecl()) Shadow->setInvalidDecl(); - + + Shadow->setPreviousDecl(PrevDecl); + if (S) PushOnScopeChains(Shadow, S); else @@ -6979,6 +7266,42 @@ void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) { // be possible for this to happen, because...? } +namespace { +class UsingValidatorCCC : public CorrectionCandidateCallback { +public: + UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation, + bool RequireMember) + : HasTypenameKeyword(HasTypenameKeyword), + IsInstantiation(IsInstantiation), RequireMember(RequireMember) {} + + bool ValidateCandidate(const TypoCorrection &Candidate) LLVM_OVERRIDE { + NamedDecl *ND = Candidate.getCorrectionDecl(); + + // Keywords are not valid here. + if (!ND || isa<NamespaceDecl>(ND)) + return false; + + if (RequireMember && !isa<FieldDecl>(ND) && !isa<CXXMethodDecl>(ND) && + !isa<TypeDecl>(ND)) + return false; + + // Completely unqualified names are invalid for a 'using' declaration. + if (Candidate.WillReplaceSpecifier() && !Candidate.getCorrectionSpecifier()) + return false; + + if (isa<TypeDecl>(ND)) + return HasTypenameKeyword || !IsInstantiation; + + return !HasTypenameKeyword; + } + +private: + bool HasTypenameKeyword; + bool IsInstantiation; + bool RequireMember; +}; +} // end anonymous namespace + /// Builds a using declaration. /// /// \param IsInstantiation - Whether this call arises from an @@ -6990,7 +7313,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, const DeclarationNameInfo &NameInfo, AttributeList *AttrList, bool IsInstantiation, - bool IsTypeName, + bool HasTypenameKeyword, SourceLocation TypenameLoc) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); SourceLocation IdentLoc = NameInfo.getLoc(); @@ -7025,7 +7348,8 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, } // Check for invalid redeclarations. - if (CheckUsingDeclRedeclaration(UsingLoc, IsTypeName, SS, IdentLoc, Previous)) + if (CheckUsingDeclRedeclaration(UsingLoc, HasTypenameKeyword, + SS, IdentLoc, Previous)) return 0; // Check for bad qualifiers. @@ -7036,7 +7360,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, NamedDecl *D; NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); if (!LookupContext) { - if (IsTypeName) { + if (HasTypenameKeyword) { // FIXME: not all declaration name kinds are legal here D = UnresolvedUsingTypenameDecl::Create(Context, CurContext, UsingLoc, TypenameLoc, @@ -7048,7 +7372,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, } } else { D = UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc, - NameInfo, IsTypeName); + NameInfo, HasTypenameKeyword); } D->setAccess(AS); CurContext->addDecl(D); @@ -7088,11 +7412,27 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, LookupQualifiedName(R, LookupContext); + // Try to correct typos if possible. if (R.empty()) { - Diag(IdentLoc, diag::err_no_member) - << NameInfo.getName() << LookupContext << SS.getRange(); - UD->setInvalidDecl(); - return UD; + UsingValidatorCCC CCC(HasTypenameKeyword, IsInstantiation, + CurContext->isRecord()); + if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(), + R.getLookupKind(), S, &SS, CCC)){ + // We reject any correction for which ND would be NULL. + NamedDecl *ND = Corrected.getCorrectionDecl(); + R.setLookupName(Corrected.getCorrection()); + R.addDecl(ND); + // We reject candidates where DroppedSpecifier == true, hence the + // literal '0' below. + diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest) + << NameInfo.getName() << LookupContext << 0 + << SS.getRange()); + } else { + Diag(IdentLoc, diag::err_no_member) + << NameInfo.getName() << LookupContext << SS.getRange(); + UD->setInvalidDecl(); + return UD; + } } if (R.isAmbiguous()) { @@ -7100,7 +7440,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, return UD; } - if (IsTypeName) { + if (HasTypenameKeyword) { // If we asked for a typename and got a non-type decl, error out. if (!R.getAsSingle<TypeDecl>()) { Diag(IdentLoc, diag::err_using_typename_non_type); @@ -7132,8 +7472,9 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, } for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { - if (!CheckUsingShadowDecl(UD, *I, Previous)) - BuildUsingShadowDecl(S, UD, *I); + UsingShadowDecl *PrevDecl = 0; + if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl)) + BuildUsingShadowDecl(S, UD, *I, PrevDecl); } return UD; @@ -7141,7 +7482,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, /// Additional checks for a using declaration referring to a constructor name. bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) { - assert(!UD->isTypeName() && "expecting a constructor name"); + assert(!UD->hasTypename() && "expecting a constructor name"); const Type *SourceType = UD->getQualifier()->getAsType(); assert(SourceType && @@ -7162,7 +7503,7 @@ bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) { if (BaseIt == BaseE) { // Did not find SourceType in the bases. - Diag(UD->getUsingLocation(), + Diag(UD->getUsingLoc(), diag::err_using_decl_constructor_not_in_direct_base) << UD->getNameInfo().getSourceRange() << QualType(SourceType, 0) << TargetClass; @@ -7179,7 +7520,7 @@ bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) { /// redeclaration. Note that this is checking only for the using decl /// itself, not for any ill-formedness among the UsingShadowDecls. bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, - bool isTypeName, + bool HasTypenameKeyword, const CXXScopeSpec &SS, SourceLocation NameLoc, const LookupResult &Prev) { @@ -7202,7 +7543,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, bool DTypename; NestedNameSpecifier *DQual; if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) { - DTypename = UD->isTypeName(); + DTypename = UD->hasTypename(); DQual = UD->getQualifier(); } else if (UnresolvedUsingValueDecl *UD = dyn_cast<UnresolvedUsingValueDecl>(D)) { @@ -7216,7 +7557,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, // using decls differ if one says 'typename' and the other doesn't. // FIXME: non-dependent using decls? - if (isTypeName != DTypename) continue; + if (HasTypenameKeyword != DTypename) continue; // using decls differ if they name different scopes (but note that // template instantiation can cause this check to trigger when it @@ -7498,7 +7839,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, if (Invalid) NewDecl->setInvalidDecl(); else if (OldDecl) - NewDecl->setPreviousDeclaration(OldDecl); + NewDecl->setPreviousDecl(OldDecl); NewND = NewDecl; } else { @@ -7788,9 +8129,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( DefaultCon->setImplicit(); // Build an exception specification pointing back at this constructor. - FunctionProtoType::ExtProtoInfo EPI; - EPI.ExceptionSpecType = EST_Unevaluated; - EPI.ExceptionSpecDecl = DefaultCon; + FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, DefaultCon); DefaultCon->setType(Context.getFunctionType(Context.VoidTy, None, EPI)); // We don't need to use SpecialMemberIsTrivial here; triviality for default @@ -7833,18 +8172,19 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, SourceLocation Loc = Constructor->getLocation(); Constructor->setBody(new (Context) CompoundStmt(Loc)); - Constructor->setUsed(); + Constructor->markUsed(Context); MarkVTableUsed(CurrentLocation, ClassDecl); if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(Constructor); } + + DiagnoseUninitializedFields(*this, Constructor); } void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) { - // Check that any explicitly-defaulted methods have exception specifications - // compatible with their implicit exception specifications. - CheckDelayedExplicitlyDefaultedMemberExceptionSpecs(); + // Perform any delayed checks on exception specifications. + CheckDelayedMemberExceptionSpecs(); } namespace { @@ -7887,8 +8227,8 @@ private: /// constructors. struct InheritingConstructorsForType { InheritingConstructor NonTemplate; - llvm::SmallVector< - std::pair<TemplateParameterList*, InheritingConstructor>, 4> Templates; + SmallVector<std::pair<TemplateParameterList *, InheritingConstructor>, 4> + Templates; InheritingConstructor &getEntry(Sema &S, const CXXConstructorDecl *Ctor) { if (FunctionTemplateDecl *FTD = Ctor->getDescribedFunctionTemplate()) { @@ -8171,7 +8511,7 @@ void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation, SourceLocation Loc = Constructor->getLocation(); Constructor->setBody(new (Context) CompoundStmt(Loc)); - Constructor->setUsed(); + Constructor->markUsed(Context); MarkVTableUsed(CurrentLocation, ClassDecl); if (ASTMutationListener *L = getASTMutationListener()) { @@ -8252,9 +8592,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { Destructor->setImplicit(); // Build an exception specification pointing back at this destructor. - FunctionProtoType::ExtProtoInfo EPI; - EPI.ExceptionSpecType = EST_Unevaluated; - EPI.ExceptionSpecDecl = Destructor; + FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, Destructor); Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI)); AddOverriddenMethods(ClassDecl, Destructor); @@ -8305,8 +8643,7 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, SourceLocation Loc = Destructor->getLocation(); Destructor->setBody(new (Context) CompoundStmt(Loc)); - Destructor->setImplicitlyDefined(true); - Destructor->setUsed(); + Destructor->markUsed(Context); MarkVTableUsed(CurrentLocation, ClassDecl); if (ASTMutationListener *L = getASTMutationListener()) { @@ -8320,23 +8657,11 @@ void Sema::ActOnFinishCXXMemberDecls() { // If the context is an invalid C++ class, just suppress these checks. if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(CurContext)) { if (Record->isInvalidDecl()) { + DelayedDefaultedMemberExceptionSpecs.clear(); DelayedDestructorExceptionSpecChecks.clear(); return; } } - - // Perform any deferred checking of exception specifications for virtual - // destructors. - for (unsigned i = 0, e = DelayedDestructorExceptionSpecChecks.size(); - i != e; ++i) { - const CXXDestructorDecl *Dtor = - DelayedDestructorExceptionSpecChecks[i].first; - assert(!Dtor->getParent()->isDependentType() && - "Should not ever add destructors of templates into the list."); - CheckOverridingFunctionExceptionSpec(Dtor, - DelayedDestructorExceptionSpecChecks[i].second); - } - DelayedDestructorExceptionSpecChecks.clear(); } void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, @@ -8368,13 +8693,144 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, // needs to be done somewhere else. } +namespace { +/// \brief An abstract base class for all helper classes used in building the +// copy/move operators. These classes serve as factory functions and help us +// avoid using the same Expr* in the AST twice. +class ExprBuilder { + ExprBuilder(const ExprBuilder&) LLVM_DELETED_FUNCTION; + ExprBuilder &operator=(const ExprBuilder&) LLVM_DELETED_FUNCTION; + +protected: + static Expr *assertNotNull(Expr *E) { + assert(E && "Expression construction must not fail."); + return E; + } + +public: + ExprBuilder() {} + virtual ~ExprBuilder() {} + + virtual Expr *build(Sema &S, SourceLocation Loc) const = 0; +}; + +class RefBuilder: public ExprBuilder { + VarDecl *Var; + QualType VarType; + +public: + virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE { + return assertNotNull(S.BuildDeclRefExpr(Var, VarType, VK_LValue, Loc).take()); + } + + RefBuilder(VarDecl *Var, QualType VarType) + : Var(Var), VarType(VarType) {} +}; + +class ThisBuilder: public ExprBuilder { +public: + virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE { + return assertNotNull(S.ActOnCXXThis(Loc).takeAs<Expr>()); + } +}; + +class CastBuilder: public ExprBuilder { + const ExprBuilder &Builder; + QualType Type; + ExprValueKind Kind; + const CXXCastPath &Path; + +public: + virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE { + return assertNotNull(S.ImpCastExprToType(Builder.build(S, Loc), Type, + CK_UncheckedDerivedToBase, Kind, + &Path).take()); + } + + CastBuilder(const ExprBuilder &Builder, QualType Type, ExprValueKind Kind, + const CXXCastPath &Path) + : Builder(Builder), Type(Type), Kind(Kind), Path(Path) {} +}; + +class DerefBuilder: public ExprBuilder { + const ExprBuilder &Builder; + +public: + virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE { + return assertNotNull( + S.CreateBuiltinUnaryOp(Loc, UO_Deref, Builder.build(S, Loc)).take()); + } + + DerefBuilder(const ExprBuilder &Builder) : Builder(Builder) {} +}; + +class MemberBuilder: public ExprBuilder { + const ExprBuilder &Builder; + QualType Type; + CXXScopeSpec SS; + bool IsArrow; + LookupResult &MemberLookup; + +public: + virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE { + return assertNotNull(S.BuildMemberReferenceExpr( + Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(), 0, + MemberLookup, 0).take()); + } + + MemberBuilder(const ExprBuilder &Builder, QualType Type, bool IsArrow, + LookupResult &MemberLookup) + : Builder(Builder), Type(Type), IsArrow(IsArrow), + MemberLookup(MemberLookup) {} +}; + +class MoveCastBuilder: public ExprBuilder { + const ExprBuilder &Builder; + +public: + virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE { + return assertNotNull(CastForMoving(S, Builder.build(S, Loc))); + } + + MoveCastBuilder(const ExprBuilder &Builder) : Builder(Builder) {} +}; + +class LvalueConvBuilder: public ExprBuilder { + const ExprBuilder &Builder; + +public: + virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE { + return assertNotNull( + S.DefaultLvalueConversion(Builder.build(S, Loc)).take()); + } + + LvalueConvBuilder(const ExprBuilder &Builder) : Builder(Builder) {} +}; + +class SubscriptBuilder: public ExprBuilder { + const ExprBuilder &Base; + const ExprBuilder &Index; + +public: + virtual Expr *build(Sema &S, SourceLocation Loc) const + LLVM_OVERRIDE { + return assertNotNull(S.CreateBuiltinArraySubscriptExpr( + Base.build(S, Loc), Loc, Index.build(S, Loc), Loc).take()); + } + + SubscriptBuilder(const ExprBuilder &Base, const ExprBuilder &Index) + : Base(Base), Index(Index) {} +}; + +} // end anonymous namespace + /// When generating a defaulted copy or move assignment operator, if a field /// should be copied with __builtin_memcpy rather than via explicit assignments, /// do so. This optimization only applies for arrays of scalars, and for arrays /// of class type where the selected copy/move-assignment operator is trivial. static StmtResult buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T, - Expr *To, Expr *From) { + const ExprBuilder &ToB, const ExprBuilder &FromB) { // Compute the size of the memory buffer to be copied. QualType SizeType = S.Context.getSizeType(); llvm::APInt Size(S.Context.getTypeSize(SizeType), @@ -8383,9 +8839,11 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T, // Take the address of the field references for "from" and "to". We // directly construct UnaryOperators here because semantic analysis // does not permit us to take the address of an xvalue. + Expr *From = FromB.build(S, Loc); From = new (S.Context) UnaryOperator(From, UO_AddrOf, S.Context.getPointerType(From->getType()), VK_RValue, OK_Ordinary, Loc); + Expr *To = ToB.build(S, Loc); To = new (S.Context) UnaryOperator(To, UO_AddrOf, S.Context.getPointerType(To->getType()), VK_RValue, OK_Ordinary, Loc); @@ -8451,7 +8909,7 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T, /// if a memcpy should be used instead. static StmtResult buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, - Expr *To, Expr *From, + const ExprBuilder &To, const ExprBuilder &From, bool CopyingBaseSubobject, bool Copying, unsigned Depth = 0) { // C++11 [class.copy]p28: @@ -8524,8 +8982,8 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, // Create the reference to operator=. ExprResult OpEqualRef - = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS, - /*TemplateKWLoc=*/SourceLocation(), + = S.BuildMemberReferenceExpr(To.build(S, Loc), T, Loc, /*isArrow=*/false, + SS, /*TemplateKWLoc=*/SourceLocation(), /*FirstQualifierInScope=*/0, OpLookup, /*TemplateArgs=*/0, @@ -8535,9 +8993,10 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, // Build the call to the assignment operator. + Expr *FromInst = From.build(S, Loc); ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0, OpEqualRef.takeAs<Expr>(), - Loc, &From, 1, Loc); + Loc, FromInst, Loc); if (Call.isInvalid()) return StmtError(); @@ -8556,7 +9015,8 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, // operator is used. const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T); if (!ArrayTy) { - ExprResult Assignment = S.CreateBuiltinBinOp(Loc, BO_Assign, To, From); + ExprResult Assignment = S.CreateBuiltinBinOp( + Loc, BO_Assign, To.build(S, Loc), From.build(S, Loc)); if (Assignment.isInvalid()) return StmtError(); return S.ActOnExprStmt(Assignment); @@ -8589,31 +9049,28 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0); IterationVar->setInit(IntegerLiteral::Create(S.Context, Zero, SizeType, Loc)); - // Create a reference to the iteration variable; we'll use this several - // times throughout. - Expr *IterationVarRef - = 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!"); + // Creates a reference to the iteration variable. + RefBuilder IterationVarRef(IterationVar, SizeType); + LvalueConvBuilder IterationVarRefRVal(IterationVarRef); // Create the DeclStmt that holds the iteration variable. Stmt *InitStmt = new (S.Context) DeclStmt(DeclGroupRef(IterationVar),Loc,Loc); // Subscript the "from" and "to" expressions with the iteration variable. - From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc, - IterationVarRefRVal, - Loc)); - To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc, - IterationVarRefRVal, - Loc)); - if (!Copying) // Cast to rvalue - From = CastForMoving(S, From); + SubscriptBuilder FromIndexCopy(From, IterationVarRefRVal); + MoveCastBuilder FromIndexMove(FromIndexCopy); + const ExprBuilder *FromIndex; + if (Copying) + FromIndex = &FromIndexCopy; + else + FromIndex = &FromIndexMove; + + SubscriptBuilder ToIndex(To, IterationVarRefRVal); // Build the copy/move for an individual element of the array. StmtResult Copy = buildSingleCopyAssignRecursively(S, Loc, ArrayTy->getElementType(), - To, From, CopyingBaseSubobject, + ToIndex, *FromIndex, CopyingBaseSubobject, Copying, Depth + 1); // Bail out if copying fails or if we determined that we should use memcpy. if (Copy.isInvalid() || !Copy.get()) @@ -8623,15 +9080,15 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, llvm::APInt Upper = ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType)); Expr *Comparison - = new (S.Context) BinaryOperator(IterationVarRefRVal, + = new (S.Context) BinaryOperator(IterationVarRefRVal.build(S, Loc), IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), BO_NE, S.Context.BoolTy, VK_RValue, OK_Ordinary, Loc, false); // Create the pre-increment of the iteration variable. Expr *Increment - = new (S.Context) UnaryOperator(IterationVarRef, UO_PreInc, SizeType, - VK_LValue, OK_Ordinary, Loc); + = new (S.Context) UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc, + SizeType, VK_LValue, OK_Ordinary, Loc); // Construct the loop that copies all elements of this array. return S.ActOnForStmt(Loc, Loc, InitStmt, @@ -8642,7 +9099,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, static StmtResult buildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, - Expr *To, Expr *From, + const ExprBuilder &To, const ExprBuilder &From, bool CopyingBaseSubobject, bool Copying) { // Maybe we should use a memcpy? if (T->isArrayType() && !T.isConstQualified() && !T.isVolatileQualified() && @@ -8736,29 +9193,31 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { QualType ArgType = Context.getTypeDeclType(ClassDecl); QualType RetType = Context.getLValueReferenceType(ArgType); - if (ClassDecl->implicitCopyAssignmentHasConstParam()) + bool Const = ClassDecl->implicitCopyAssignmentHasConstParam(); + if (Const) ArgType = ArgType.withConst(); ArgType = Context.getLValueReferenceType(ArgType); + bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, + CXXCopyAssignment, + Const); + // An implicitly-declared copy assignment operator is an inline public // member of its class. DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationNameInfo NameInfo(Name, ClassLoc); - CXXMethodDecl *CopyAssignment - = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), - /*TInfo=*/0, - /*StorageClass=*/SC_None, - /*isInline=*/true, /*isConstexpr=*/false, - SourceLocation()); + CXXMethodDecl *CopyAssignment = + CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), + /*TInfo=*/ 0, /*StorageClass=*/ SC_None, + /*isInline=*/ true, Constexpr, SourceLocation()); CopyAssignment->setAccess(AS_public); CopyAssignment->setDefaulted(); CopyAssignment->setImplicit(); // Build an exception specification pointing back at this member. - FunctionProtoType::ExtProtoInfo EPI; - EPI.ExceptionSpecType = EST_Unevaluated; - EPI.ExceptionSpecDecl = CopyAssignment; + FunctionProtoType::ExtProtoInfo EPI = + getImplicitMethodEPI(*this, CopyAssignment); CopyAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI)); // Add the parameter to the operator. @@ -8775,11 +9234,6 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { ? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment) : ClassDecl->hasTrivialCopyAssignment()); - // 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)) SetDeclDeleted(CopyAssignment, ClassLoc); @@ -8793,6 +9247,58 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { return CopyAssignment; } +/// Diagnose an implicit copy operation for a class which is odr-used, but +/// which is deprecated because the class has a user-declared copy constructor, +/// copy assignment operator, or destructor. +static void diagnoseDeprecatedCopyOperation(Sema &S, CXXMethodDecl *CopyOp, + SourceLocation UseLoc) { + assert(CopyOp->isImplicit()); + + CXXRecordDecl *RD = CopyOp->getParent(); + CXXMethodDecl *UserDeclaredOperation = 0; + + // In Microsoft mode, assignment operations don't affect constructors and + // vice versa. + if (RD->hasUserDeclaredDestructor()) { + UserDeclaredOperation = RD->getDestructor(); + } else if (!isa<CXXConstructorDecl>(CopyOp) && + RD->hasUserDeclaredCopyConstructor() && + !S.getLangOpts().MicrosoftMode) { + // Find any user-declared copy constructor. + for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(), + E = RD->ctor_end(); I != E; ++I) { + if (I->isCopyConstructor()) { + UserDeclaredOperation = *I; + break; + } + } + assert(UserDeclaredOperation); + } else if (isa<CXXConstructorDecl>(CopyOp) && + RD->hasUserDeclaredCopyAssignment() && + !S.getLangOpts().MicrosoftMode) { + // Find any user-declared move assignment operator. + for (CXXRecordDecl::method_iterator I = RD->method_begin(), + E = RD->method_end(); I != E; ++I) { + if (I->isCopyAssignmentOperator()) { + UserDeclaredOperation = *I; + break; + } + } + assert(UserDeclaredOperation); + } + + if (UserDeclaredOperation) { + S.Diag(UserDeclaredOperation->getLocation(), + diag::warn_deprecated_copy_operation) + << RD << /*copy assignment*/!isa<CXXConstructorDecl>(CopyOp) + << /*destructor*/isa<CXXDestructorDecl>(UserDeclaredOperation); + S.Diag(UseLoc, diag::note_member_synthesized_at) + << (isa<CXXConstructorDecl>(CopyOp) ? Sema::CXXCopyConstructor + : Sema::CXXCopyAssignment) + << RD; + } +} + void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, CXXMethodDecl *CopyAssignOperator) { assert((CopyAssignOperator->isDefaulted() && @@ -8808,8 +9314,15 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, CopyAssignOperator->setInvalidDecl(); return; } - - CopyAssignOperator->setUsed(); + + // C++11 [class.copy]p18: + // The [definition of an implicitly declared copy assignment operator] is + // deprecated if the class has a user-declared copy constructor or a + // user-declared destructor. + if (getLangOpts().CPlusPlus11 && CopyAssignOperator->isImplicit()) + diagnoseDeprecatedCopyOperation(*this, CopyAssignOperator, CurrentLocation); + + CopyAssignOperator->markUsed(Context); SynthesizedFunctionScope Scope(*this, CopyAssignOperator); DiagnosticErrorTrap Trap(Diags); @@ -8838,15 +9351,11 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, // Our location for everything implicitly-generated. SourceLocation Loc = CopyAssignOperator->getLocation(); - // Construct a reference to the "other" object. We'll be using this - // throughout the generated ASTs. - Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, VK_LValue, Loc).take(); - assert(OtherRef && "Reference to parameter cannot fail!"); - - // Construct the "this" pointer. We'll be using this throughout the generated - // ASTs. - Expr *This = ActOnCXXThis(Loc).takeAs<Expr>(); - assert(This && "Reference to this cannot fail!"); + // Builds a DeclRefExpr for the "other" object. + RefBuilder OtherRef(Other, OtherRefType); + + // Builds the "this" pointer. + ThisBuilder This; // Assign base classes. bool Invalid = false; @@ -8865,24 +9374,19 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, // Construct the "from" expression, which is an implicit cast to the // appropriately-qualified base type. - Expr *From = OtherRef; - From = ImpCastExprToType(From, Context.getQualifiedType(BaseType, OtherQuals), - CK_UncheckedDerivedToBase, - VK_LValue, &BasePath).take(); + CastBuilder From(OtherRef, Context.getQualifiedType(BaseType, OtherQuals), + VK_LValue, BasePath); // Dereference "this". - ExprResult To = CreateBuiltinUnaryOp(Loc, UO_Deref, This); - - // Implicitly cast "this" to the appropriately-qualified base type. - To = ImpCastExprToType(To.take(), - Context.getCVRQualifiedType(BaseType, - CopyAssignOperator->getTypeQualifiers()), - CK_UncheckedDerivedToBase, - VK_LValue, &BasePath); + DerefBuilder DerefThis(This); + CastBuilder To(DerefThis, + Context.getCVRQualifiedType( + BaseType, CopyAssignOperator->getTypeQualifiers()), + VK_LValue, BasePath); // Build the copy. StmtResult Copy = buildSingleCopyAssign(*this, Loc, BaseType, - To.get(), From, + To, From, /*CopyingBaseSubobject=*/true, /*Copying=*/true); if (Copy.isInvalid()) { @@ -8902,7 +9406,12 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, Field != FieldEnd; ++Field) { if (Field->isUnnamedBitfield()) continue; - + + if (Field->isInvalidDecl()) { + Invalid = true; + continue; + } + // Check for members of reference type; we can't copy those. if (Field->getType()->isReferenceType()) { Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) @@ -8943,20 +9452,14 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, LookupMemberName); MemberLookup.addDecl(*Field); MemberLookup.resolveKind(); - ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType, - Loc, /*IsArrow=*/false, - SS, SourceLocation(), 0, - MemberLookup, 0); - ExprResult To = BuildMemberReferenceExpr(This, This->getType(), - Loc, /*IsArrow=*/true, - SS, SourceLocation(), 0, - MemberLookup, 0); - assert(!From.isInvalid() && "Implicit field reference cannot fail"); - assert(!To.isInvalid() && "Implicit field reference cannot fail"); + + MemberBuilder From(OtherRef, OtherRefType, /*IsArrow=*/false, MemberLookup); + + MemberBuilder To(This, getCurrentThisType(), /*IsArrow=*/true, MemberLookup); // Build the copy of this field. StmtResult Copy = buildSingleCopyAssign(*this, Loc, FieldType, - To.get(), From.get(), + To, From, /*CopyingBaseSubobject=*/false, /*Copying=*/true); if (Copy.isInvalid()) { @@ -8972,7 +9475,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, if (!Invalid) { // Add a "return *this;" - ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This); + ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc)); StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get()); if (Return.isInvalid()) @@ -9067,120 +9570,13 @@ Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXMethodDecl *MD) { 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 (BaseClass->hasNonTrivialMoveAssignment()) - 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 || !ClassDecl->getDefinition() || ClassDecl->isInvalidDecl()) - return true; - - if (Type.isTriviallyCopyableType(S.Context)) - return true; - - if (IsConstructor) { - // FIXME: Need this because otherwise hasMoveConstructor isn't guaranteed to - // give the right answer. - if (ClassDecl->needsImplicitMoveConstructor()) - S.DeclareImplicitMoveConstructor(ClassDecl); - return ClassDecl->hasMoveConstructor(); - } - - // FIXME: Need this because otherwise hasMoveAssignment isn't guaranteed to - // give the right answer. - if (ClassDecl->needsImplicitMoveAssignment()) - S.DeclareImplicitMoveAssignment(ClassDecl); - return ClassDecl->hasMoveAssignment(); -} - -/// 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()); DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveAssignment); if (DSM.isAlreadyBeingDeclared()) return 0; - // [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. @@ -9188,26 +9584,26 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { QualType RetType = Context.getLValueReferenceType(ArgType); ArgType = Context.getRValueReferenceType(ArgType); + bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, + CXXMoveAssignment, + false); + // An implicitly-declared move assignment operator is an inline public // member of its class. DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationNameInfo NameInfo(Name, ClassLoc); - CXXMethodDecl *MoveAssignment - = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), - /*TInfo=*/0, - /*StorageClass=*/SC_None, - /*isInline=*/true, - /*isConstexpr=*/false, - SourceLocation()); + CXXMethodDecl *MoveAssignment = + CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), + /*TInfo=*/0, /*StorageClass=*/SC_None, + /*isInline=*/true, Constexpr, SourceLocation()); MoveAssignment->setAccess(AS_public); MoveAssignment->setDefaulted(); MoveAssignment->setImplicit(); // Build an exception specification pointing back at this member. - FunctionProtoType::ExtProtoInfo EPI; - EPI.ExceptionSpecType = EST_Unevaluated; - EPI.ExceptionSpecDecl = MoveAssignment; + FunctionProtoType::ExtProtoInfo EPI = + getImplicitMethodEPI(*this, MoveAssignment); MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI)); // Add the parameter to the operator. @@ -9224,18 +9620,9 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { ? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment) : ClassDecl->hasTrivialMoveAssignment()); - // C++0x [class.copy]p9: - // 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: - // [...] - // - the move assignment operator would not be implicitly defined as - // deleted. 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(); - return 0; + ClassDecl->setImplicitMoveAssignmentIsDeleted(); + SetDeclDeleted(MoveAssignment, ClassLoc); } // Note that we have added this copy-assignment operator. @@ -9248,6 +9635,94 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { return MoveAssignment; } +/// Check if we're implicitly defining a move assignment operator for a class +/// with virtual bases. Such a move assignment might move-assign the virtual +/// base multiple times. +static void checkMoveAssignmentForRepeatedMove(Sema &S, CXXRecordDecl *Class, + SourceLocation CurrentLocation) { + assert(!Class->isDependentContext() && "should not define dependent move"); + + // Only a virtual base could get implicitly move-assigned multiple times. + // Only a non-trivial move assignment can observe this. We only want to + // diagnose if we implicitly define an assignment operator that assigns + // two base classes, both of which move-assign the same virtual base. + if (Class->getNumVBases() == 0 || Class->hasTrivialMoveAssignment() || + Class->getNumBases() < 2) + return; + + llvm::SmallVector<CXXBaseSpecifier *, 16> Worklist; + typedef llvm::DenseMap<CXXRecordDecl*, CXXBaseSpecifier*> VBaseMap; + VBaseMap VBases; + + for (CXXRecordDecl::base_class_iterator BI = Class->bases_begin(), + BE = Class->bases_end(); + BI != BE; ++BI) { + Worklist.push_back(&*BI); + while (!Worklist.empty()) { + CXXBaseSpecifier *BaseSpec = Worklist.pop_back_val(); + CXXRecordDecl *Base = BaseSpec->getType()->getAsCXXRecordDecl(); + + // If the base has no non-trivial move assignment operators, + // we don't care about moves from it. + if (!Base->hasNonTrivialMoveAssignment()) + continue; + + // If there's nothing virtual here, skip it. + if (!BaseSpec->isVirtual() && !Base->getNumVBases()) + continue; + + // If we're not actually going to call a move assignment for this base, + // or the selected move assignment is trivial, skip it. + Sema::SpecialMemberOverloadResult *SMOR = + S.LookupSpecialMember(Base, Sema::CXXMoveAssignment, + /*ConstArg*/false, /*VolatileArg*/false, + /*RValueThis*/true, /*ConstThis*/false, + /*VolatileThis*/false); + if (!SMOR->getMethod() || SMOR->getMethod()->isTrivial() || + !SMOR->getMethod()->isMoveAssignmentOperator()) + continue; + + if (BaseSpec->isVirtual()) { + // We're going to move-assign this virtual base, and its move + // assignment operator is not trivial. If this can happen for + // multiple distinct direct bases of Class, diagnose it. (If it + // only happens in one base, we'll diagnose it when synthesizing + // that base class's move assignment operator.) + CXXBaseSpecifier *&Existing = + VBases.insert(std::make_pair(Base->getCanonicalDecl(), BI)) + .first->second; + if (Existing && Existing != BI) { + S.Diag(CurrentLocation, diag::warn_vbase_moved_multiple_times) + << Class << Base; + S.Diag(Existing->getLocStart(), diag::note_vbase_moved_here) + << (Base->getCanonicalDecl() == + Existing->getType()->getAsCXXRecordDecl()->getCanonicalDecl()) + << Base << Existing->getType() << Existing->getSourceRange(); + S.Diag(BI->getLocStart(), diag::note_vbase_moved_here) + << (Base->getCanonicalDecl() == + BI->getType()->getAsCXXRecordDecl()->getCanonicalDecl()) + << Base << BI->getType() << BaseSpec->getSourceRange(); + + // Only diagnose each vbase once. + Existing = 0; + } + } else { + // Only walk over bases that have defaulted move assignment operators. + // We assume that any user-provided move assignment operator handles + // the multiple-moves-of-vbase case itself somehow. + if (!SMOR->getMethod()->isDefaulted()) + continue; + + // We're going to move the base classes of Base. Add them to the list. + for (CXXRecordDecl::base_class_iterator BI = Base->bases_begin(), + BE = Base->bases_end(); + BI != BE; ++BI) + Worklist.push_back(&*BI); + } + } + } +} + void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, CXXMethodDecl *MoveAssignOperator) { assert((MoveAssignOperator->isDefaulted() && @@ -9264,7 +9739,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, return; } - MoveAssignOperator->setUsed(); + MoveAssignOperator->markUsed(Context); SynthesizedFunctionScope Scope(*this, MoveAssignOperator); DiagnosticErrorTrap Trap(Diags); @@ -9277,6 +9752,10 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, // are assigned, in the order in which they were declared in the class // definition. + // Issue a warning if our implicit move assignment operator will move + // from a virtual base more than once. + checkMoveAssignmentForRepeatedMove(*this, ClassDecl, CurrentLocation); + // The statements that form the synthesized function body. SmallVector<Stmt*, 8> Statements; @@ -9284,28 +9763,32 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, ParmVarDecl *Other = MoveAssignOperator->getParamDecl(0); QualType OtherRefType = Other->getType()-> getAs<RValueReferenceType>()->getPointeeType(); - assert(OtherRefType.getQualifiers() == 0 && + assert(!OtherRefType.getQualifiers() && "Bad argument type of defaulted move assignment"); // Our location for everything implicitly-generated. SourceLocation Loc = MoveAssignOperator->getLocation(); - // Construct a reference to the "other" object. We'll be using this - // throughout the generated ASTs. - Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, VK_LValue, Loc).take(); - assert(OtherRef && "Reference to parameter cannot fail!"); + // Builds a reference to the "other" object. + RefBuilder OtherRef(Other, OtherRefType); // Cast to rvalue. - OtherRef = CastForMoving(*this, OtherRef); + MoveCastBuilder MoveOther(OtherRef); - // Construct the "this" pointer. We'll be using this throughout the generated - // ASTs. - Expr *This = ActOnCXXThis(Loc).takeAs<Expr>(); - assert(This && "Reference to this cannot fail!"); + // Builds the "this" pointer. + ThisBuilder This; // Assign base classes. bool Invalid = false; for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), E = ClassDecl->bases_end(); Base != E; ++Base) { + // C++11 [class.copy]p28: + // It is unspecified whether subobjects representing virtual base classes + // are assigned more than once by the implicitly-defined copy assignment + // operator. + // FIXME: Do not assign to a vbase that will be assigned by some other base + // class. For a move-assignment, this can result in the vbase being moved + // multiple times. + // Form the assignment: // static_cast<Base*>(this)->Base::operator=(static_cast<Base&&>(other)); QualType BaseType = Base->getType().getUnqualifiedType(); @@ -9319,23 +9802,20 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, // Construct the "from" expression, which is an implicit cast to the // appropriately-qualified base type. - Expr *From = OtherRef; - From = ImpCastExprToType(From, BaseType, CK_UncheckedDerivedToBase, - VK_XValue, &BasePath).take(); + CastBuilder From(OtherRef, BaseType, VK_XValue, BasePath); // Dereference "this". - ExprResult To = CreateBuiltinUnaryOp(Loc, UO_Deref, This); + DerefBuilder DerefThis(This); // Implicitly cast "this" to the appropriately-qualified base type. - To = ImpCastExprToType(To.take(), - Context.getCVRQualifiedType(BaseType, - MoveAssignOperator->getTypeQualifiers()), - CK_UncheckedDerivedToBase, - VK_LValue, &BasePath); + CastBuilder To(DerefThis, + Context.getCVRQualifiedType( + BaseType, MoveAssignOperator->getTypeQualifiers()), + VK_LValue, BasePath); // Build the move. StmtResult Move = buildSingleCopyAssign(*this, Loc, BaseType, - To.get(), From, + To, From, /*CopyingBaseSubobject=*/true, /*Copying=*/false); if (Move.isInvalid()) { @@ -9356,6 +9836,11 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, if (Field->isUnnamedBitfield()) continue; + if (Field->isInvalidDecl()) { + Invalid = true; + continue; + } + // Check for members of reference type; we can't move those. if (Field->getType()->isReferenceType()) { Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) @@ -9391,29 +9876,22 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, } // Build references to the field in the object we're copying from and to. - CXXScopeSpec SS; // Intentionally empty LookupResult MemberLookup(*this, Field->getDeclName(), Loc, LookupMemberName); MemberLookup.addDecl(*Field); MemberLookup.resolveKind(); - ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType, - Loc, /*IsArrow=*/false, - SS, SourceLocation(), 0, - MemberLookup, 0); - ExprResult To = BuildMemberReferenceExpr(This, This->getType(), - Loc, /*IsArrow=*/true, - SS, SourceLocation(), 0, - MemberLookup, 0); - assert(!From.isInvalid() && "Implicit field reference cannot fail"); - assert(!To.isInvalid() && "Implicit field reference cannot fail"); - - assert(!From.get()->isLValue() && // could be xvalue or prvalue + MemberBuilder From(MoveOther, OtherRefType, + /*IsArrow=*/false, MemberLookup); + MemberBuilder To(This, getCurrentThisType(), + /*IsArrow=*/true, MemberLookup); + + assert(!From.build(*this, Loc)->isLValue() && // could be xvalue or prvalue "Member reference with rvalue base must be rvalue except for reference " "members, which aren't allowed for move assignment."); // Build the move of this field. StmtResult Move = buildSingleCopyAssign(*this, Loc, FieldType, - To.get(), From.get(), + To, From, /*CopyingBaseSubobject=*/false, /*Copying=*/false); if (Move.isInvalid()) { @@ -9429,7 +9907,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, if (!Invalid) { // Add a "return *this;" - ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This); + ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc)); StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get()); if (Return.isInvalid()) @@ -9557,9 +10035,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( CopyConstructor->setDefaulted(); // Build an exception specification pointing back at this member. - FunctionProtoType::ExtProtoInfo EPI; - EPI.ExceptionSpecType = EST_Unevaluated; - EPI.ExceptionSpecDecl = CopyConstructor; + FunctionProtoType::ExtProtoInfo EPI = + getImplicitMethodEPI(*this, CopyConstructor); CopyConstructor->setType( Context.getFunctionType(Context.VoidTy, ArgType, EPI)); @@ -9576,11 +10053,6 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor) : ClassDecl->hasTrivialCopyConstructor()); - // 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)) SetDeclDeleted(CopyConstructor, ClassLoc); @@ -9605,6 +10077,13 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, CXXRecordDecl *ClassDecl = CopyConstructor->getParent(); assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor"); + // C++11 [class.copy]p7: + // The [definition of an implicitly declared copy constructor] is + // deprecated if the class has a user-declared copy assignment operator + // or a user-declared destructor. + if (getLangOpts().CPlusPlus11 && CopyConstructor->isImplicit()) + diagnoseDeprecatedCopyOperation(*this, CopyConstructor, CurrentLocation); + SynthesizedFunctionScope Scope(*this, CopyConstructor); DiagnosticErrorTrap Trap(Diags); @@ -9615,15 +10094,12 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, CopyConstructor->setInvalidDecl(); } else { Sema::CompoundScopeRAII CompoundScope(*this); - CopyConstructor->setBody(ActOnCompoundStmt(CopyConstructor->getLocation(), - CopyConstructor->getLocation(), - MultiStmtArg(), - /*isStmtExpr=*/false) - .takeAs<Stmt>()); - CopyConstructor->setImplicitlyDefined(true); + CopyConstructor->setBody(ActOnCompoundStmt( + CopyConstructor->getLocation(), CopyConstructor->getLocation(), None, + /*isStmtExpr=*/ false).takeAs<Stmt>()); } - - CopyConstructor->setUsed(); + + CopyConstructor->markUsed(Context); if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(CopyConstructor); } @@ -9696,29 +10172,12 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXMethodDecl *MD) { 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()); DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveConstructor); if (DSM.isAlreadyBeingDeclared()) return 0; - // [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; - } - QualType ClassType = Context.getTypeDeclType(ClassDecl); QualType ArgType = Context.getRValueReferenceType(ClassType); @@ -9732,7 +10191,7 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationNameInfo NameInfo(Name, ClassLoc); - // C++0x [class.copy]p11: + // C++11 [class.copy]p11: // An implicitly-declared copy/move constructor is an inline public // member of its class. CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create( @@ -9743,9 +10202,8 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( MoveConstructor->setDefaulted(); // Build an exception specification pointing back at this member. - FunctionProtoType::ExtProtoInfo EPI; - EPI.ExceptionSpecType = EST_Unevaluated; - EPI.ExceptionSpecDecl = MoveConstructor; + FunctionProtoType::ExtProtoInfo EPI = + getImplicitMethodEPI(*this, MoveConstructor); MoveConstructor->setType( Context.getFunctionType(Context.VoidTy, ArgType, EPI)); @@ -9762,16 +10220,9 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor) : ClassDecl->hasTrivialMoveConstructor()); - // C++0x [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: - // [...] - // - the move constructor would not be implicitly defined as deleted. if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) { - // Cache this result so that we don't try to generate this over and over - // on every lookup, leaking memory and wasting time. - ClassDecl->setFailedImplicitMoveConstructor(); - return 0; + ClassDecl->setImplicitMoveConstructorIsDeleted(); + SetDeclDeleted(MoveConstructor, ClassLoc); } // Note that we have declared this constructor. @@ -9805,15 +10256,12 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, MoveConstructor->setInvalidDecl(); } else { Sema::CompoundScopeRAII CompoundScope(*this); - MoveConstructor->setBody(ActOnCompoundStmt(MoveConstructor->getLocation(), - MoveConstructor->getLocation(), - MultiStmtArg(), - /*isStmtExpr=*/false) - .takeAs<Stmt>()); - MoveConstructor->setImplicitlyDefined(true); + MoveConstructor->setBody(ActOnCompoundStmt( + MoveConstructor->getLocation(), MoveConstructor->getLocation(), None, + /*isStmtExpr=*/ false).takeAs<Stmt>()); } - MoveConstructor->setUsed(); + MoveConstructor->markUsed(Context); if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(MoveConstructor); @@ -9821,64 +10269,96 @@ 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)).front()); - CallOperator->setReferenced(); - CallOperator->setUsed(); + return FD->isDeleted() && FD->isDefaulted() && isa<CXXMethodDecl>(FD); } void Sema::DefineImplicitLambdaToFunctionPointerConversion( - SourceLocation CurrentLocation, - CXXConversionDecl *Conv) -{ + SourceLocation CurrentLocation, + CXXConversionDecl *Conv) { CXXRecordDecl *Lambda = Conv->getParent(); + CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator(); + // If we are defining a specialization of a conversion to function-ptr + // cache the deduced template arguments for this specialization + // so that we can use them to retrieve the corresponding call-operator + // and static-invoker. + const TemplateArgumentList *DeducedTemplateArgs = 0; + - // Make sure that the lambda call operator is marked used. - markLambdaCallOperatorUsed(*this, Lambda); - - Conv->setUsed(); - + // Retrieve the corresponding call-operator specialization. + if (Lambda->isGenericLambda()) { + assert(Conv->isFunctionTemplateSpecialization()); + FunctionTemplateDecl *CallOpTemplate = + CallOp->getDescribedFunctionTemplate(); + DeducedTemplateArgs = Conv->getTemplateSpecializationArgs(); + void *InsertPos = 0; + FunctionDecl *CallOpSpec = CallOpTemplate->findSpecialization( + DeducedTemplateArgs->data(), + DeducedTemplateArgs->size(), + InsertPos); + assert(CallOpSpec && + "Conversion operator must have a corresponding call operator"); + CallOp = cast<CXXMethodDecl>(CallOpSpec); + } + // Mark the call operator referenced (and add to pending instantiations + // if necessary). + // For both the conversion and static-invoker template specializations + // we construct their body's in this function, so no need to add them + // to the PendingInstantiations. + MarkFunctionReferenced(CurrentLocation, CallOp); + SynthesizedFunctionScope Scope(*this, Conv); DiagnosticErrorTrap Trap(Diags); + + // Retreive the static invoker... + CXXMethodDecl *Invoker = Lambda->getLambdaStaticInvoker(); + // ... and get the corresponding specialization for a generic lambda. + if (Lambda->isGenericLambda()) { + assert(DeducedTemplateArgs && + "Must have deduced template arguments from Conversion Operator"); + FunctionTemplateDecl *InvokeTemplate = + Invoker->getDescribedFunctionTemplate(); + void *InsertPos = 0; + FunctionDecl *InvokeSpec = InvokeTemplate->findSpecialization( + DeducedTemplateArgs->data(), + DeducedTemplateArgs->size(), + InsertPos); + assert(InvokeSpec && + "Must have a corresponding static invoker specialization"); + Invoker = cast<CXXMethodDecl>(InvokeSpec); + } + // Construct the body of the conversion function { return __invoke; }. + Expr *FunctionRef = BuildDeclRefExpr(Invoker, Invoker->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, + Conv->getLocation(), + Conv->getLocation())); + + Conv->markUsed(Context); + Conv->setReferenced(); - // Return the address of the __invoke function. - DeclarationName InvokeName = &Context.Idents.get("__invoke"); - CXXMethodDecl *Invoke - = cast<CXXMethodDecl>(Lambda->lookup(InvokeName).front()); - 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, - 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(Conv->getLocation())); - + Invoker->markUsed(Context); + Invoker->setReferenced(); + Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation())); + if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(Conv); - L->CompletedImplicitDefinition(Invoke); - } + L->CompletedImplicitDefinition(Invoker); + } } + + void Sema::DefineImplicitLambdaToBlockPointerConversion( SourceLocation CurrentLocation, CXXConversionDecl *Conv) { - Conv->setUsed(); + assert(!Conv->getParent()->isGenericLambda()); + + Conv->markUsed(Context); SynthesizedFunctionScope Scope(*this, Conv); DiagnosticErrorTrap Trap(Diags); @@ -10057,12 +10537,14 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply; SmallVector<Expr *, 8> AllArgs; bool Invalid = GatherArgumentsForCall(Loc, Constructor, - Proto, 0, Args, NumArgs, AllArgs, + Proto, 0, + llvm::makeArrayRef(Args, NumArgs), + AllArgs, CallType, AllowExplicit, IsListInitialization); ConvertedArgs.append(AllArgs.begin(), AllArgs.end()); - DiagnoseSentinelCalls(Constructor, Loc, AllArgs.data(), AllArgs.size()); + DiagnoseSentinelCalls(Constructor, Loc, AllArgs); CheckConstructorCall(Constructor, llvm::makeArrayRef<const Expr *>(AllArgs.data(), @@ -10356,11 +10838,12 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { if (!TpDecl) TpDecl = FnDecl->getPrimaryTemplate(); - // template <char...> type operator "" name() is the only valid template - // signature, and the only valid signature with no parameters. + // template <char...> type operator "" name() and + // template <class T, T...> type operator "" name() are the only valid + // template signatures, and the only valid signatures with no parameters. if (TpDecl) { if (FnDecl->param_size() == 0) { - // Must have only one template parameter + // Must have one or two template parameters TemplateParameterList *Params = TpDecl->getTemplateParameters(); if (Params->size() == 1) { NonTypeTemplateParmDecl *PmDecl = @@ -10370,6 +10853,27 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { if (PmDecl && PmDecl->isTemplateParameterPack() && Context.hasSameType(PmDecl->getType(), Context.CharTy)) Valid = true; + } else if (Params->size() == 2) { + TemplateTypeParmDecl *PmType = + dyn_cast<TemplateTypeParmDecl>(Params->getParam(0)); + NonTypeTemplateParmDecl *PmArgs = + dyn_cast<NonTypeTemplateParmDecl>(Params->getParam(1)); + + // The second template parameter must be a parameter pack with the + // first template parameter as its type. + if (PmType && PmArgs && + !PmType->isTemplateParameterPack() && + PmArgs->isTemplateParameterPack()) { + const TemplateTypeParmType *TArgs = + PmArgs->getType()->getAs<TemplateTypeParmType>(); + if (TArgs && TArgs->getDepth() == PmType->getDepth() && + TArgs->getIndex() == PmType->getIndex()) { + Valid = true; + if (ActiveTemplateInstantiations.empty()) + Diag(FnDecl->getLocation(), + diag::ext_string_literal_operator_template); + } + } } } } else if (FnDecl->param_size()) { @@ -10383,7 +10887,7 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { if (Context.hasSameType(T, Context.UnsignedLongLongTy) || Context.hasSameType(T, Context.LongDoubleTy) || Context.hasSameType(T, Context.CharTy) || - Context.hasSameType(T, Context.WCharTy) || + Context.hasSameType(T, Context.WideCharTy) || Context.hasSameType(T, Context.Char16Ty) || Context.hasSameType(T, Context.Char32Ty)) { if (++Param == FnDecl->param_end()) @@ -10413,7 +10917,7 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { // const char *, const wchar_t*, const char16_t*, and const char32_t* // are allowed as the first parameter to a two-parameter function if (!(Context.hasSameType(T, Context.CharTy) || - Context.hasSameType(T, Context.WCharTy) || + Context.hasSameType(T, Context.WideCharTy) || Context.hasSameType(T, Context.Char16Ty) || Context.hasSameType(T, Context.Char32Ty))) goto FinishedParams; @@ -10452,7 +10956,8 @@ FinishedParams: // 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); + Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved) + << NumericLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName); } return false; @@ -10599,13 +11104,13 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, EnterExpressionEvaluationContext scope(*this, PotentiallyEvaluated); // C++ [except.handle]p16: - // The object declared in an exception-declaration or, if the - // exception-declaration does not specify a name, a temporary (12.2) is + // The object declared in an exception-declaration or, if the + // exception-declaration does not specify a name, a temporary (12.2) is // copy-initialized (8.5) from the exception object. [...] // The object is destroyed when the handler exits, after the destruction // of any automatic objects initialized within the handler. // - // We just pretend to initialize the object with itself, then make sure + // We just pretend to initialize the object with itself, then make sure // it can be destroyed later. QualType initType = ExDeclType; @@ -10623,7 +11128,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, else { // If the constructor used was non-trivial, set this as the // "initializer". - CXXConstructExpr *construct = cast<CXXConstructExpr>(result.take()); + CXXConstructExpr *construct = result.takeAs<CXXConstructExpr>(); if (!construct->getConstructor()->isTrivial()) { Expr *init = MaybeCreateExprWithCleanups(construct); ExDecl->setInit(init); @@ -10826,13 +11331,10 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, bool isExplicitSpecialization = false; bool Invalid = false; - if (TemplateParameterList *TemplateParams - = MatchTemplateParametersToScopeSpecifier(TagLoc, NameLoc, SS, - TempParamLists.data(), - TempParamLists.size(), - /*friend*/ true, - isExplicitSpecialization, - Invalid)) { + if (TemplateParameterList *TemplateParams = + MatchTemplateParametersToScopeSpecifier( + TagLoc, NameLoc, SS, TempParamLists, /*friend*/ true, + isExplicitSpecialization, Invalid)) { if (TemplateParams->size() > 0) { // This is a declaration of a class template. if (Invalid) @@ -10916,6 +11418,8 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, // Handle the case of a templated-scope friend class. e.g. // template <class T> class A<T>::B; // FIXME: we don't support these right now. + Diag(NameLoc, diag::warn_template_qualified_friend_unsupported) + << SS.getScopeRep() << SS.getRange() << cast<CXXRecordDecl>(CurContext); ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind); QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name); TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); @@ -11080,28 +11584,61 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); - // FIXME: there are different rules in local classes + // There are five cases here. + // - There's no scope specifier and we're in a local class. Only look + // for functions declared in the immediately-enclosing block scope. + // We recover from invalid scope qualifiers as if they just weren't there. + FunctionDecl *FunctionContainingLocalClass = 0; + if ((SS.isInvalid() || !SS.isSet()) && + (FunctionContainingLocalClass = + cast<CXXRecordDecl>(CurContext)->isLocalClass())) { + // C++11 [class.friend]p11: + // If a friend declaration appears in a local class and the name + // specified is an unqualified name, a prior declaration is + // looked up without considering scopes that are outside the + // innermost enclosing non-class scope. For a friend function + // declaration, if there is no prior declaration, the program is + // ill-formed. + + // Find the innermost enclosing non-class scope. This is the block + // scope containing the local class definition (or for a nested class, + // the outer local class). + DCScope = S->getFnParent(); + + // Look up the function name in the scope. + Previous.clear(LookupLocalFriendName); + LookupName(Previous, S, /*AllowBuiltinCreation*/false); + + if (!Previous.empty()) { + // All possible previous declarations must have the same context: + // either they were declared at block scope or they are members of + // one of the enclosing local classes. + DC = Previous.getRepresentativeDecl()->getDeclContext(); + } else { + // This is ill-formed, but provide the context that we would have + // declared the function in, if we were permitted to, for error recovery. + DC = FunctionContainingLocalClass; + } + adjustContextForLocalExternDecl(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 + // unqualified, and the function has namespace scope. + if (D.isFunctionDefinition()) { + Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class); + } - // There are four cases here. // - There's no scope specifier, in which case we just go to the // appropriate scope and look for a function or function template // there as appropriate. - // Recover from invalid scope qualifiers as if they just weren't there. - if (SS.isInvalid() || !SS.isSet()) { - // C++0x [namespace.memdef]p3: + } else if (SS.isInvalid() || !SS.isSet()) { + // C++11 [namespace.memdef]p3: // If the name in a friend declaration is neither qualified nor // a template-id and the declaration is a function or an // elaborated-type-specifier, the lookup to determine whether // the entity has been previously declared shall not consider // any scopes outside the innermost enclosing namespace. - // C++0x [class.friend]p11: - // If a friend declaration appears in a local class and the name - // specified is an unqualified name, a prior declaration is - // looked up without considering scopes that are outside the - // innermost enclosing non-class scope. For a friend function - // declaration, if there is no prior declaration, the program is - // ill-formed. - bool isLocal = cast<CXXRecordDecl>(CurContext)->isLocalClass(); bool isTemplateId = D.getName().getKind() == UnqualifiedId::IK_TemplateId; // Find the appropriate context according to the above. @@ -11124,10 +11661,6 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, while (true) { LookupQualifiedName(Previous, LookupDC); - // TODO: decide what we think about using declarations. - if (isLocal) - break; - if (!Previous.empty()) { DC = LookupDC; break; @@ -11142,15 +11675,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, } 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 - // unqualified, and the function has namespace scope. - if (isLocal && D.isFunctionDefinition()) { - Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class); - } - + // - There's a non-dependent scope specifier, in which case we // compute it and do a previous lookup there for a function // or function template. @@ -11242,15 +11767,18 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, FakeDCScope.setEntity(DC); DCScope = &FakeDCScope; } - + bool AddToScope = true; NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous, TemplateParams, AddToScope); if (!ND) return 0; - assert(ND->getDeclContext() == DC); assert(ND->getLexicalDeclContext() == CurContext); + // If we performed typo correction, we might have added a scope specifier + // and changed the decl context. + DC = ND->getDeclContext(); + // Add the function declaration to the appropriate lookup tables, // adjusting the redeclarations list as necessary. We don't // want to do this yet if the friending class is dependent. @@ -11281,6 +11809,18 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, else FD = cast<FunctionDecl>(ND); + // C++11 [dcl.fct.default]p4: If a friend declaration specifies a + // default argument expression, that declaration shall be a definition + // and shall be the only declaration of the function or function + // template in the translation unit. + if (functionDeclHasDefaultArgument(FD)) { + if (FunctionDecl *OldFD = FD->getPreviousDecl()) { + Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_redeclared); + Diag(OldFD->getLocation(), diag::note_previous_declaration); + } else if (!D.isFunctionDefinition()) + Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_must_be_def); + } + // Mark templated-scope function declarations as unsupported. if (FD->getNumTemplateParameterLists()) FrD->setUnsupportedFriend(true); @@ -11346,7 +11886,8 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { CXXSpecialMember Member = getSpecialMember(MD); if (Member == CXXInvalid) { - Diag(DefaultLoc, diag::err_default_special_members); + if (!MD->isInvalidDecl()) + Diag(DefaultLoc, diag::err_default_special_members); return; } @@ -11374,47 +11915,29 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { ResolveExceptionSpec(DefaultLoc, MD->getType()->castAs<FunctionProtoType>()); + if (MD->isInvalidDecl()) + return; + switch (Member) { - case CXXDefaultConstructor: { - CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD); - if (!CD->isInvalidDecl()) - DefineImplicitDefaultConstructor(DefaultLoc, CD); + case CXXDefaultConstructor: + DefineImplicitDefaultConstructor(DefaultLoc, + cast<CXXConstructorDecl>(MD)); break; - } - - case CXXCopyConstructor: { - CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD); - if (!CD->isInvalidDecl()) - DefineImplicitCopyConstructor(DefaultLoc, CD); + case CXXCopyConstructor: + DefineImplicitCopyConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD)); break; - } - - case CXXCopyAssignment: { - if (!MD->isInvalidDecl()) - DefineImplicitCopyAssignment(DefaultLoc, MD); + case CXXCopyAssignment: + DefineImplicitCopyAssignment(DefaultLoc, MD); break; - } - - case CXXDestructor: { - CXXDestructorDecl *DD = cast<CXXDestructorDecl>(MD); - if (!DD->isInvalidDecl()) - DefineImplicitDestructor(DefaultLoc, DD); + case CXXDestructor: + DefineImplicitDestructor(DefaultLoc, cast<CXXDestructorDecl>(MD)); break; - } - - case CXXMoveConstructor: { - CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD); - if (!CD->isInvalidDecl()) - DefineImplicitMoveConstructor(DefaultLoc, CD); + case CXXMoveConstructor: + DefineImplicitMoveConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD)); break; - } - - case CXXMoveAssignment: { - if (!MD->isInvalidDecl()) - DefineImplicitMoveAssignment(DefaultLoc, MD); + case CXXMoveAssignment: + DefineImplicitMoveAssignment(DefaultLoc, MD); break; - } - case CXXInvalid: llvm_unreachable("Invalid special member."); } @@ -11454,27 +11977,11 @@ bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New, if (NewCC == OldCC) return false; - // If either of the calling conventions are set to "default", we need to pick - // something more sensible based on the target. This supports code where the - // one method explicitly sets thiscall, and another has no explicit calling - // convention. - CallingConv Default = - Context.getTargetInfo().getDefaultCallingConv(TargetInfo::CCMT_Member); - if (NewCC == CC_Default) - NewCC = Default; - if (OldCC == CC_Default) - OldCC = Default; - - // If the calling conventions still don't match, then report the error - if (NewCC != OldCC) { - Diag(New->getLocation(), - diag::err_conflicting_overriding_cc_attributes) - << New->getDeclName() << New->getType() << Old->getType(); - Diag(Old->getLocation(), diag::note_overridden_virtual_function); - return true; - } - - return false; + Diag(New->getLocation(), + diag::err_conflicting_overriding_cc_attributes) + << New->getDeclName() << New->getType() << Old->getType(); + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + return true; } bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, @@ -11595,13 +12102,13 @@ bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) { } /// \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(); +static bool isStaticDataMember(const Decl *D) { + if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D)) + return Var->isStaticDataMember(); + + return false; } + /// 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. @@ -11744,19 +12251,14 @@ bool Sema::DefineUsedVTables() { // vtable even though we're using it. const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(Class); if (KeyFunction && !KeyFunction->hasBody()) { - switch (KeyFunction->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - case TSK_ExplicitInstantiationDeclaration: - // The key function is in another translation unit. - DefineVTable = false; - break; - - case TSK_ExplicitInstantiationDefinition: - case TSK_ImplicitInstantiation: - // We will be instantiating the key function. - break; - } + // The key function is in another translation unit. + DefineVTable = false; + TemplateSpecializationKind TSK = + KeyFunction->getTemplateSpecializationKind(); + assert(TSK != TSK_ExplicitInstantiationDefinition && + TSK != TSK_ImplicitInstantiation && + "Instantiations don't have key functions"); + (void)TSK; } else if (!KeyFunction) { // If we have a class with no key function that is the subject // of an explicit instantiation declaration, suppress the @@ -11799,7 +12301,7 @@ bool Sema::DefineUsedVTables() { Consumer.HandleVTable(Class, VTablesUsed[Canonical]); // Optionally warn if we're emitting a weak vtable. - if (Class->hasExternalLinkage() && + if (Class->isExternallyVisible() && Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { const FunctionDecl *KeyFunctionDef = 0; if (!KeyFunction || @@ -11920,8 +12422,6 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor, llvm::SmallSet<CXXConstructorDecl*, 4> &Invalid, llvm::SmallSet<CXXConstructorDecl*, 4> &Current, Sema &S) { - llvm::SmallSet<CXXConstructorDecl*, 4>::iterator CI = Current.begin(), - CE = Current.end(); if (Ctor->isInvalidDecl()) return; @@ -11946,8 +12446,7 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor, // We know that beyond here, we aren't chaining into a cycle. if (!Target || !Target->isDelegatingConstructor() || Target->isInvalidDecl() || Valid.count(TCanonical)) { - for (CI = Current.begin(), CE = Current.end(); CI != CE; ++CI) - Valid.insert(*CI); + Valid.insert(Current.begin(), Current.end()); Current.clear(); // We've hit a cycle. } else if (TCanonical == Canonical || Invalid.count(TCanonical) || @@ -11974,8 +12473,7 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor, } } - for (CI = Current.begin(), CE = Current.end(); CI != CE; ++CI) - Invalid.insert(*CI); + Invalid.insert(Current.begin(), Current.end()); Current.clear(); } else { DelegatingCycleHelper(Target, Valid, Invalid, Current, S); @@ -11986,16 +12484,15 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor, void Sema::CheckDelegatingCtorCycles() { llvm::SmallSet<CXXConstructorDecl*, 4> Valid, Invalid, Current; - llvm::SmallSet<CXXConstructorDecl*, 4>::iterator CI = Current.begin(), - CE = Current.end(); - for (DelegatingCtorDeclsType::iterator I = DelegatingCtorDecls.begin(ExternalSource), E = DelegatingCtorDecls.end(); I != E; ++I) DelegatingCycleHelper(*I, Valid, Invalid, Current, *this); - for (CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI) + for (llvm::SmallSet<CXXConstructorDecl *, 4>::iterator CI = Invalid.begin(), + CE = Invalid.end(); + CI != CE; ++CI) (*CI)->setInvalidDecl(); } @@ -12211,8 +12708,7 @@ Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) { if (D->hasAttr<CUDADeviceAttr>()) { if (D->hasAttr<CUDAHostAttr>()) return CFT_HostDevice; - else - return CFT_Device; + return CFT_Device; } return CFT_Host; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp index f33e7bcb1671..f44fb3251141 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp @@ -324,15 +324,15 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { PushOnScopeChains(MDecl->getSelfDecl(), FnBodyScope); PushOnScopeChains(MDecl->getCmdDecl(), FnBodyScope); + // The ObjC parser requires parameter names so there's no need to check. + CheckParmsForFunctionDef(MDecl->param_begin(), MDecl->param_end(), + /*CheckParameterNames=*/false); + // Introduce all of the other parameters into this scope. for (ObjCMethodDecl::param_iterator PI = MDecl->param_begin(), E = MDecl->param_end(); PI != E; ++PI) { ParmVarDecl *Param = (*PI); if (!Param->isInvalidDecl() && - RequireCompleteType(Param->getLocation(), Param->getType(), - diag::err_typecheck_decl_incomplete_type)) - Param->setInvalidDecl(); - if (!Param->isInvalidDecl() && getLangOpts().ObjCAutoRefCount && !HasExplicitOwnershipAttr(*this, Param)) Diag(Param->getLocation(), diag::warn_arc_strong_pointer_objc_pointer) << @@ -350,7 +350,7 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { case OMF_release: case OMF_autorelease: Diag(MDecl->getLocation(), diag::err_arc_illegal_method_def) - << MDecl->getSelector(); + << 0 << MDecl->getSelector(); break; case OMF_None: @@ -459,6 +459,23 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, // Create a declaration to describe this @interface. ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); + + if (PrevIDecl && PrevIDecl->getIdentifier() != ClassName) { + // A previous decl with a different name is because of + // @compatibility_alias, for example: + // \code + // @class NewImage; + // @compatibility_alias OldImage NewImage; + // \endcode + // A lookup for 'OldImage' will return the 'NewImage' decl. + // + // In such a case use the real declaration name, instead of the alias one, + // otherwise we will break IdentifierResolver and redecls-chain invariants. + // FIXME: If necessary, add a bit to indicate that this ObjCInterfaceDecl + // has been aliased. + ClassName = PrevIDecl->getIdentifier(); + } + ObjCInterfaceDecl *IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName, PrevIDecl, ClassLoc); @@ -494,11 +511,9 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, if (TypoCorrection Corrected = CorrectTypo( DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope, NULL, Validator)) { + diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest) + << SuperName << ClassName); PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>(); - Diag(SuperLoc, diag::err_undef_superclass_suggest) - << SuperName << ClassName << PrevDecl->getDeclName(); - Diag(PrevDecl->getLocation(), diag::note_previous_decl) - << PrevDecl->getDeclName(); } } @@ -575,6 +590,29 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, return ActOnObjCContainerStartDefinition(IDecl); } +/// ActOnTypedefedProtocols - this action finds protocol list as part of the +/// typedef'ed use for a qualified super class and adds them to the list +/// of the protocols. +void Sema::ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs, + IdentifierInfo *SuperName, + SourceLocation SuperLoc) { + if (!SuperName) + return; + NamedDecl* IDecl = LookupSingleName(TUScope, SuperName, SuperLoc, + LookupOrdinaryName); + if (!IDecl) + return; + + if (const TypedefNameDecl *TDecl = dyn_cast_or_null<TypedefNameDecl>(IDecl)) { + QualType T = TDecl->getUnderlyingType(); + if (T->isObjCObjectType()) + if (const ObjCObjectType *OPT = T->getAs<ObjCObjectType>()) + for (ObjCObjectType::qual_iterator I = OPT->qual_begin(), + E = OPT->qual_end(); I != E; ++I) + ProtocolRefs.push_back(*I); + } +} + /// ActOnCompatibilityAlias - this action is called after complete parsing of /// a \@compatibility_alias declaration. It sets up the alias relationships. Decl *Sema::ActOnCompatibilityAlias(SourceLocation AtLoc, @@ -586,10 +624,7 @@ Decl *Sema::ActOnCompatibilityAlias(SourceLocation AtLoc, NamedDecl *ADecl = LookupSingleName(TUScope, AliasName, AliasLocation, LookupOrdinaryName, ForRedeclaration); if (ADecl) { - if (isa<ObjCCompatibleAliasDecl>(ADecl)) - Diag(AliasLocation, diag::warn_previous_alias_decl); - else - Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName; + Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName; Diag(ADecl->getLocation(), diag::note_previous_declaration); return 0; } @@ -732,12 +767,9 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, TypoCorrection Corrected = CorrectTypo( DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second), LookupObjCProtocolName, TUScope, NULL, Validator); - if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) { - Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest) - << ProtocolId[i].first << Corrected.getCorrection(); - Diag(PDecl->getLocation(), diag::note_previous_decl) - << PDecl->getDeclName(); - } + if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) + diagnoseTypo(Corrected, PDiag(diag::err_undeclared_protocol_suggest) + << ProtocolId[i].first); } if (!PDecl) { @@ -819,7 +851,7 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, DeclsInGroup.push_back(PDecl); } - return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false); + return BuildDeclaratorGroup(DeclsInGroup, false); } Decl *Sema:: @@ -935,6 +967,7 @@ Decl *Sema::ActOnStartCategoryImplementation( << CatName; Diag(CatIDecl->getImplementation()->getLocation(), diag::note_previous_definition); + CDecl->setInvalidDecl(); } else { CatIDecl->setImplementation(CDecl); // Warn on implementating category of deprecated class under @@ -954,7 +987,7 @@ Decl *Sema::ActOnStartClassImplementation( IdentifierInfo *ClassName, SourceLocation ClassLoc, IdentifierInfo *SuperClassname, SourceLocation SuperClassLoc) { - ObjCInterfaceDecl* IDecl = 0; + ObjCInterfaceDecl *IDecl = 0; // Check for another declaration kind with the same name. NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName, @@ -966,24 +999,19 @@ Decl *Sema::ActOnStartClassImplementation( RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), diag::warn_undef_interface); } else { - // We did not find anything with the name ClassName; try to correct for + // We did not find anything with the name ClassName; try to correct for // typos in the class name. ObjCInterfaceValidatorCCC Validator; - if (TypoCorrection Corrected = CorrectTypo( - DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope, - 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; - Diag(IDecl->getLocation(), diag::note_previous_decl) << CorrectedName - << FixItHint::CreateReplacement(ClassLoc, CorrectedName.getAsString()); - IDecl = 0; + TypoCorrection Corrected = + CorrectTypo(DeclarationNameInfo(ClassName, ClassLoc), + LookupOrdinaryName, TUScope, NULL, Validator); + if (Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) { + // Suggest the (potentially) correct interface name. Don't provide a + // code-modification hint or use the typo name for recovery, because + // this is just a warning. The program may actually be correct. + diagnoseTypo(Corrected, + PDiag(diag::warn_undef_interface_suggest) << ClassName, + /*ErrorRecovery*/false); } else { Diag(ClassLoc, diag::warn_undef_interface) << ClassName; } @@ -1056,6 +1084,7 @@ Decl *Sema::ActOnStartClassImplementation( Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName; Diag(IDecl->getImplementation()->getLocation(), diag::note_previous_definition); + IMPDecl->setInvalidDecl(); } else { // add it to the list. IDecl->setImplementation(IMPDecl); PushOnScopeChains(IMPDecl, TUScope); @@ -1084,7 +1113,7 @@ Sema::ActOnFinishObjCImplementation(Decl *ObjCImpDecl, ArrayRef<Decl *> Decls) { DeclsInGroup.push_back(ObjCImpDecl); - return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false); + return BuildDeclaratorGroup(DeclsInGroup, false); } void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, @@ -1124,6 +1153,19 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, Diag(ClsIvar->getLocation(), diag::note_previous_definition); continue; } + // Check class extensions (unnamed categories) for duplicate ivars. + for (ObjCInterfaceDecl::visible_extensions_iterator + Ext = IDecl->visible_extensions_begin(), + ExtEnd = IDecl->visible_extensions_end(); + Ext != ExtEnd; ++Ext) { + ObjCCategoryDecl *CDecl = *Ext; + if (const ObjCIvarDecl *ClsExtIvar = + CDecl->getIvarDecl(ImplIvar->getIdentifier())) { + Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration); + Diag(ClsExtIvar->getLocation(), diag::note_previous_definition); + continue; + } + } // Instance ivar to Implementation's DeclContext. ImplIvar->setLexicalDeclContext(ImpDecl); IDecl->makeDeclVisibleInContext(ImplIvar); @@ -1469,8 +1511,8 @@ static bool checkMethodFamilyMismatch(Sema &S, ObjCMethodDecl *impl, reasonSelector = R_NonObjectReturn; } - S.Diag(impl->getLocation(), errorID) << familySelector << reasonSelector; - S.Diag(decl->getLocation(), noteID) << familySelector << reasonSelector; + S.Diag(impl->getLocation(), errorID) << int(familySelector) << int(reasonSelector); + S.Diag(decl->getLocation(), noteID) << int(familySelector) << int(reasonSelector); return true; } @@ -1689,9 +1731,8 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, // implemented in the implementation class. If so, their types match. for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(), E = CDecl->instmeth_end(); I != E; ++I) { - if (InsMapSeen.count((*I)->getSelector())) - continue; - InsMapSeen.insert((*I)->getSelector()); + if (!InsMapSeen.insert((*I)->getSelector())) + continue; if (!(*I)->isPropertyAccessor() && !InsMap.count((*I)->getSelector())) { if (ImmediateClass) @@ -1718,11 +1759,11 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, // Check and see if class methods in class interface have been // implemented in the implementation class. If so, their types match. - for (ObjCInterfaceDecl::classmeth_iterator - I = CDecl->classmeth_begin(), E = CDecl->classmeth_end(); I != E; ++I) { - if (ClsMapSeen.count((*I)->getSelector())) - continue; - ClsMapSeen.insert((*I)->getSelector()); + for (ObjCInterfaceDecl::classmeth_iterator I = CDecl->classmeth_begin(), + E = CDecl->classmeth_end(); + I != E; ++I) { + if (!ClsMapSeen.insert((*I)->getSelector())) + continue; if (!ClsMap.count((*I)->getSelector())) { if (ImmediateClass) WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl, @@ -1742,6 +1783,16 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, } } + if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl> (CDecl)) { + // Also, check for methods declared in protocols inherited by + // this protocol. + for (ObjCProtocolDecl::protocol_iterator + PI = PD->protocol_begin(), E = PD->protocol_end(); PI != E; ++PI) + MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, + IMPDecl, (*PI), IncompleteImpl, false, + WarnCategoryMethodImpl); + } + if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) { // when checking that methods in implementation match their declaration, // i.e. when WarnCategoryMethodImpl is false, check declarations in class @@ -1901,13 +1952,6 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, NamedDecl *PrevDecl = LookupSingleName(TUScope, IdentList[i], IdentLocs[i], LookupOrdinaryName, ForRedeclaration); - if (PrevDecl && PrevDecl->isTemplateParameter()) { - // Maybe we will complain about the shadowed template parameter. - DiagnoseTemplateParameterShadow(AtClassLoc, PrevDecl); - // Just pretend that we didn't see the previous declaration. - PrevDecl = 0; - } - if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { // GCC apparently allows the following idiom: // @@ -1936,17 +1980,35 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, // Create a declaration to describe this forward declaration. ObjCInterfaceDecl *PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); + + IdentifierInfo *ClassName = IdentList[i]; + if (PrevIDecl && PrevIDecl->getIdentifier() != ClassName) { + // A previous decl with a different name is because of + // @compatibility_alias, for example: + // \code + // @class NewImage; + // @compatibility_alias OldImage NewImage; + // \endcode + // A lookup for 'OldImage' will return the 'NewImage' decl. + // + // In such a case use the real declaration name, instead of the alias one, + // otherwise we will break IdentifierResolver and redecls-chain invariants. + // FIXME: If necessary, add a bit to indicate that this ObjCInterfaceDecl + // has been aliased. + ClassName = PrevIDecl->getIdentifier(); + } + ObjCInterfaceDecl *IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc, - IdentList[i], PrevIDecl, IdentLocs[i]); + ClassName, PrevIDecl, IdentLocs[i]); IDecl->setAtEndRange(IdentLocs[i]); PushOnScopeChains(IDecl, TUScope); CheckObjCDeclScope(IDecl); DeclsInGroup.push_back(IDecl); } - - return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false); + + return BuildDeclaratorGroup(DeclsInGroup, false); } static bool tryMatchRecordTypes(ASTContext &Context, @@ -2093,6 +2155,10 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method) { // signature. ObjCMethodList *Previous = List; for (; List; Previous = List, List = List->getNext()) { + // If we are building a module, keep all of the methods. + if (getLangOpts().Modules && !getLangOpts().CurrentModule.empty()) + continue; + if (!MatchTwoMethodDeclarations(Method, List->Method)) continue; @@ -2182,7 +2248,7 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, // Gather the non-hidden methods. ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second; - llvm::SmallVector<ObjCMethodDecl *, 4> Methods; + SmallVector<ObjCMethodDecl *, 4> Methods; for (ObjCMethodList *M = &MethList; M; M = M->getNext()) { if (M->Method && !M->Method->isHidden()) { // If we're not supposed to warn about mismatches, we're done. @@ -2269,7 +2335,140 @@ ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) { return 0; } -/// DiagnoseDuplicateIvars - +static void +HelperSelectorsForTypoCorrection( + SmallVectorImpl<const ObjCMethodDecl *> &BestMethod, + StringRef Typo, const ObjCMethodDecl * Method) { + const unsigned MaxEditDistance = 1; + unsigned BestEditDistance = MaxEditDistance + 1; + std::string MethodName = Method->getSelector().getAsString(); + + unsigned MinPossibleEditDistance = abs((int)MethodName.size() - (int)Typo.size()); + if (MinPossibleEditDistance > 0 && + Typo.size() / MinPossibleEditDistance < 1) + return; + unsigned EditDistance = Typo.edit_distance(MethodName, true, MaxEditDistance); + if (EditDistance > MaxEditDistance) + return; + if (EditDistance == BestEditDistance) + BestMethod.push_back(Method); + else if (EditDistance < BestEditDistance) { + BestMethod.clear(); + BestMethod.push_back(Method); + } +} + +static bool HelperIsMethodInObjCType(Sema &S, Selector Sel, + QualType ObjectType) { + if (ObjectType.isNull()) + return true; + if (S.LookupMethodInObjectType(Sel, ObjectType, true/*Instance method*/)) + return true; + return S.LookupMethodInObjectType(Sel, ObjectType, false/*Class method*/) != 0; +} + +const ObjCMethodDecl * +Sema::SelectorsForTypoCorrection(Selector Sel, + QualType ObjectType) { + unsigned NumArgs = Sel.getNumArgs(); + SmallVector<const ObjCMethodDecl *, 8> Methods; + bool ObjectIsId = true, ObjectIsClass = true; + if (ObjectType.isNull()) + ObjectIsId = ObjectIsClass = false; + else if (!ObjectType->isObjCObjectPointerType()) + return 0; + else if (const ObjCObjectPointerType *ObjCPtr = + ObjectType->getAsObjCInterfacePointerType()) { + ObjectType = QualType(ObjCPtr->getInterfaceType(), 0); + ObjectIsId = ObjectIsClass = false; + } + else if (ObjectType->isObjCIdType() || ObjectType->isObjCQualifiedIdType()) + ObjectIsClass = false; + else if (ObjectType->isObjCClassType() || ObjectType->isObjCQualifiedClassType()) + ObjectIsId = false; + else + return 0; + + for (GlobalMethodPool::iterator b = MethodPool.begin(), + e = MethodPool.end(); b != e; b++) { + // instance methods + for (ObjCMethodList *M = &b->second.first; M; M=M->getNext()) + if (M->Method && + (M->Method->getSelector().getNumArgs() == NumArgs) && + (M->Method->getSelector() != Sel)) { + if (ObjectIsId) + Methods.push_back(M->Method); + else if (!ObjectIsClass && + HelperIsMethodInObjCType(*this, M->Method->getSelector(), ObjectType)) + Methods.push_back(M->Method); + } + // class methods + for (ObjCMethodList *M = &b->second.second; M; M=M->getNext()) + if (M->Method && + (M->Method->getSelector().getNumArgs() == NumArgs) && + (M->Method->getSelector() != Sel)) { + if (ObjectIsClass) + Methods.push_back(M->Method); + else if (!ObjectIsId && + HelperIsMethodInObjCType(*this, M->Method->getSelector(), ObjectType)) + Methods.push_back(M->Method); + } + } + + SmallVector<const ObjCMethodDecl *, 8> SelectedMethods; + for (unsigned i = 0, e = Methods.size(); i < e; i++) { + HelperSelectorsForTypoCorrection(SelectedMethods, + Sel.getAsString(), Methods[i]); + } + return (SelectedMethods.size() == 1) ? SelectedMethods[0] : NULL; +} + +static void +HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S, + ObjCMethodList &MethList) { + ObjCMethodList *M = &MethList; + ObjCMethodDecl *TargetMethod = M->Method; + while (TargetMethod && + isa<ObjCImplDecl>(TargetMethod->getDeclContext())) { + M = M->getNext(); + TargetMethod = M ? M->Method : 0; + } + if (!TargetMethod) + return; + bool FirstTime = true; + for (M = M->getNext(); M; M=M->getNext()) { + ObjCMethodDecl *MatchingMethodDecl = M->Method; + if (isa<ObjCImplDecl>(MatchingMethodDecl->getDeclContext())) + continue; + if (!S.MatchTwoMethodDeclarations(TargetMethod, + MatchingMethodDecl, Sema::MMS_loose)) { + if (FirstTime) { + FirstTime = false; + S.Diag(TargetMethod->getLocation(), diag::warning_multiple_selectors) + << TargetMethod->getSelector(); + } + S.Diag(MatchingMethodDecl->getLocation(), diag::note_also_found); + } + } +} + +void Sema::DiagnoseMismatchedMethodsInGlobalPool() { + unsigned DIAG = diag::warning_multiple_selectors; + if (Diags.getDiagnosticLevel(DIAG, SourceLocation()) + == DiagnosticsEngine::Ignored) + return; + for (GlobalMethodPool::iterator b = MethodPool.begin(), + e = MethodPool.end(); b != e; b++) { + // first, instance methods + ObjCMethodList &InstMethList = b->second.first; + HelperToDiagnoseMismatchedMethodsInGlobalPool(*this, InstMethList); + // second, class methods + ObjCMethodList &ClsMethList = b->second.second; + HelperToDiagnoseMismatchedMethodsInGlobalPool(*this, ClsMethList); + } +} + +/// DiagnoseDuplicateIvars - /// Check for duplicate ivars in the entire class at the start of /// \@implementation. This becomes necesssary because class extension can /// add ivars to a class in random order which will not be known until @@ -2313,13 +2512,9 @@ Sema::ObjCContainerKind Sema::getObjCContainerKind() const { } } -// Note: For class/category implemenations, allMethods/allProperties is -// always null. -Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, - Decl **allMethods, unsigned allNum, - Decl **allProperties, unsigned pNum, - DeclGroupPtrTy *allTUVars, unsigned tuvNum) { - +// Note: For class/category implementations, allMethods is always null. +Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods, + ArrayRef<DeclGroupPtrTy> allTUVars) { if (getObjCContainerKind() == Sema::OCK_None) return 0; @@ -2337,7 +2532,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap; llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap; - for (unsigned i = 0; i < allNum; i++ ) { + for (unsigned i = 0, e = allMethods.size(); i != e; i++ ) { ObjCMethodDecl *Method = cast_or_null<ObjCMethodDecl>(allMethods[i]); @@ -2504,8 +2699,8 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, } if (isInterfaceDeclKind) { // Reject invalid vardecls. - for (unsigned i = 0; i != tuvNum; i++) { - DeclGroupRef DG = allTUVars[i].getAsVal<DeclGroupRef>(); + for (unsigned i = 0, e = allTUVars.size(); i != e; i++) { + DeclGroupRef DG = allTUVars[i].get(); for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) if (VarDecl *VDecl = dyn_cast<VarDecl>(*I)) { if (!VDecl->hasExternalStorage()) @@ -2515,8 +2710,8 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, } ActOnObjCContainerFinishDefinition(); - for (unsigned i = 0; i != tuvNum; i++) { - DeclGroupRef DG = allTUVars[i].getAsVal<DeclGroupRef>(); + for (unsigned i = 0, e = allTUVars.size(); i != e; i++) { + DeclGroupRef DG = allTUVars[i].get(); for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) (*I)->setTopLevelDeclInObjCContainer(); Consumer.HandleTopLevelDeclInObjCContainer(DG); @@ -2911,14 +3106,9 @@ Decl *Sema::ActOnMethodDeclaration( if (ReturnType) { resultDeclType = GetTypeFromParser(ReturnType, &ResultTInfo); - // Methods cannot return interface types. All ObjC objects are - // passed by reference. - if (resultDeclType->isObjCObjectType()) { - Diag(MethodLoc, diag::err_object_cannot_be_passed_returned_by_value) - << 0 << resultDeclType; + if (CheckFunctionReturnType(resultDeclType, MethodLoc)) return 0; - } - + HasRelatedResultType = (resultDeclType == Context.getObjCInstanceType()); } else { // get the type for "id". resultDeclType = Context.getObjCIdType(); @@ -2945,7 +3135,7 @@ Decl *Sema::ActOnMethodDeclaration( QualType ArgType; TypeSourceInfo *DI; - if (ArgInfo[i].Type == 0) { + if (!ArgInfo[i].Type) { ArgType = Context.getObjCIdType(); DI = 0; } else { @@ -3001,14 +3191,8 @@ Decl *Sema::ActOnMethodDeclaration( else // Perform the default array/function conversions (C99 6.7.5.3p[7,8]). ArgType = Context.getAdjustedParameterType(ArgType); - if (ArgType->isObjCObjectType()) { - Diag(Param->getLocation(), - diag::err_object_cannot_be_passed_returned_by_value) - << 1 << ArgType; - Param->setInvalidDecl(); - } + Param->setDeclContext(ObjCMethod); - Params.push_back(Param); } @@ -3034,6 +3218,12 @@ Decl *Sema::ActOnMethodDeclaration( if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface()) IMD = IDecl->lookupMethod(ObjCMethod->getSelector(), ObjCMethod->isInstanceMethod()); + if (IMD && IMD->hasAttr<ObjCRequiresSuperAttr>() && + !ObjCMethod->hasAttr<ObjCRequiresSuperAttr>()) { + // merge the attribute into implementation. + ObjCMethod->addAttr( + new (Context) ObjCRequiresSuperAttr(ObjCMethod->getLocation(), Context)); + } if (ObjCMethod->hasAttrs() && containsInvalidMethodImplAttribute(IMD, ObjCMethod->getAttrs())) { SourceLocation MethodLoc = IMD->getLocation(); @@ -3052,6 +3242,8 @@ Decl *Sema::ActOnMethodDeclaration( Diag(ObjCMethod->getLocation(), diag::err_duplicate_method_decl) << ObjCMethod->getDeclName(); Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + ObjCMethod->setInvalidDecl(); + return ObjCMethod; } // If this Objective-C method does not have a related result type, but we @@ -3290,6 +3482,8 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() { ReferencedSelectors[Sels[I].first] = Sels[I].second; } + DiagnoseMismatchedMethodsInGlobalPool(); + // Warning will be issued only when selector table is // generated (which means there is at lease one implementation // in the TU). This is to match gcc's behavior. @@ -3305,3 +3499,43 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() { } return; } + +ObjCIvarDecl * +Sema::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method, + const ObjCPropertyDecl *&PDecl) const { + + const ObjCInterfaceDecl *IDecl = Method->getClassInterface(); + if (!IDecl) + return 0; + Method = IDecl->lookupMethod(Method->getSelector(), true); + if (!Method || !Method->isPropertyAccessor()) + return 0; + if ((PDecl = Method->findPropertyDecl())) { + if (!PDecl->getDeclContext()) + return 0; + // Make sure property belongs to accessor's class and not to + // one of its super classes. + if (const ObjCInterfaceDecl *CID = + dyn_cast<ObjCInterfaceDecl>(PDecl->getDeclContext())) + if (CID != IDecl) + return 0; + return PDecl->getPropertyIvarDecl(); + } + return 0; +} + +void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S) { + if (S->hasUnrecoverableErrorOccurred() || !S->isInObjcMethodScope()) + return; + + const ObjCMethodDecl *CurMethod = getCurMethodDecl(); + if (!CurMethod) + return; + const ObjCPropertyDecl *PDecl; + const ObjCIvarDecl *IV = GetIvarBackingPropertyAccessor(CurMethod, PDecl); + if (IV && !IV->getBackingIvarReferencedInAccessor()) { + Diag(getCurMethodDecl()->getLocation(), diag::warn_unused_property_backing_ivar) + << IV->getDeclName(); + Diag(PDecl->getLocation(), diag::note_property_declare); + } +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp index 1a5f4824d091..3e8f324027dc 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp @@ -181,13 +181,13 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { return false; } - // The failure was something other than an empty exception + // The failure was something other than an missing exception // specification; return an error. - if (!MissingExceptionSpecification && !MissingEmptyExceptionSpecification) + if (!MissingExceptionSpecification) return true; const FunctionProtoType *NewProto = - New->getType()->getAs<FunctionProtoType>(); + New->getType()->castAs<FunctionProtoType>(); // The new function declaration is only missing an empty exception // specification "throw()". If the throw() specification came from a @@ -203,123 +203,94 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { Old->isExternC()) { FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); EPI.ExceptionSpecType = EST_DynamicNone; - QualType NewType = - Context.getFunctionType(NewProto->getResultType(), - ArrayRef<QualType>(NewProto->arg_type_begin(), - NewProto->getNumArgs()), - EPI); + QualType NewType = Context.getFunctionType(NewProto->getResultType(), + NewProto->getArgTypes(), EPI); New->setType(NewType); return false; } - if (MissingExceptionSpecification && NewProto) { - const FunctionProtoType *OldProto = - Old->getType()->getAs<FunctionProtoType>(); - - FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); - EPI.ExceptionSpecType = OldProto->getExceptionSpecType(); - if (EPI.ExceptionSpecType == EST_Dynamic) { - EPI.NumExceptions = OldProto->getNumExceptions(); - EPI.Exceptions = OldProto->exception_begin(); - } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { - // FIXME: We can't just take the expression from the old prototype. It - // likely contains references to the old prototype's parameters. - } - - // Update the type of the function with the appropriate exception - // specification. - QualType NewType = - Context.getFunctionType(NewProto->getResultType(), - ArrayRef<QualType>(NewProto->arg_type_begin(), - NewProto->getNumArgs()), - EPI); - New->setType(NewType); - - // If exceptions are disabled, suppress the warning about missing - // exception specifications for new and delete operators. - if (!getLangOpts().CXXExceptions) { - switch (New->getDeclName().getCXXOverloadedOperator()) { - case OO_New: - case OO_Array_New: - case OO_Delete: - case OO_Array_Delete: - if (New->getDeclContext()->isTranslationUnit()) - return false; - break; - - default: - break; - } - } - - // Warn about the lack of exception specification. - SmallString<128> ExceptionSpecString; - llvm::raw_svector_ostream OS(ExceptionSpecString); - switch (OldProto->getExceptionSpecType()) { - case EST_DynamicNone: - OS << "throw()"; - break; + const FunctionProtoType *OldProto = + Old->getType()->castAs<FunctionProtoType>(); + + FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); + EPI.ExceptionSpecType = OldProto->getExceptionSpecType(); + if (EPI.ExceptionSpecType == EST_Dynamic) { + EPI.NumExceptions = OldProto->getNumExceptions(); + EPI.Exceptions = OldProto->exception_begin(); + } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { + // FIXME: We can't just take the expression from the old prototype. It + // likely contains references to the old prototype's parameters. + } - case EST_Dynamic: { - OS << "throw("; - bool OnFirstException = true; - for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(), - EEnd = OldProto->exception_end(); - E != EEnd; - ++E) { - if (OnFirstException) - OnFirstException = false; - else - OS << ", "; - - OS << E->getAsString(getPrintingPolicy()); - } - OS << ")"; - break; + // Update the type of the function with the appropriate exception + // specification. + QualType NewType = Context.getFunctionType(NewProto->getResultType(), + NewProto->getArgTypes(), EPI); + New->setType(NewType); + + // Warn about the lack of exception specification. + SmallString<128> ExceptionSpecString; + llvm::raw_svector_ostream OS(ExceptionSpecString); + switch (OldProto->getExceptionSpecType()) { + case EST_DynamicNone: + OS << "throw()"; + break; + + case EST_Dynamic: { + OS << "throw("; + bool OnFirstException = true; + for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(), + EEnd = OldProto->exception_end(); + E != EEnd; + ++E) { + if (OnFirstException) + OnFirstException = false; + else + OS << ", "; + + OS << E->getAsString(getPrintingPolicy()); } + OS << ")"; + break; + } - case EST_BasicNoexcept: - OS << "noexcept"; - break; - - case EST_ComputedNoexcept: - OS << "noexcept("; - OldProto->getNoexceptExpr()->printPretty(OS, 0, getPrintingPolicy()); - OS << ")"; - break; + case EST_BasicNoexcept: + OS << "noexcept"; + break; - default: - llvm_unreachable("This spec type is compatible with none."); - } - OS.flush(); + case EST_ComputedNoexcept: + OS << "noexcept("; + OldProto->getNoexceptExpr()->printPretty(OS, 0, getPrintingPolicy()); + OS << ")"; + break; - SourceLocation FixItLoc; - if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) { - TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens(); - if (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>()) - FixItLoc = PP.getLocForEndOfToken(FTLoc.getLocalRangeEnd()); - } - - if (FixItLoc.isInvalid()) - Diag(New->getLocation(), diag::warn_missing_exception_specification) - << New << OS.str(); - else { - // FIXME: This will get more complicated with C++0x - // late-specified return types. - Diag(New->getLocation(), diag::warn_missing_exception_specification) - << New << OS.str() - << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str()); - } + default: + llvm_unreachable("This spec type is compatible with none."); + } + OS.flush(); - if (!Old->getLocation().isInvalid()) - Diag(Old->getLocation(), diag::note_previous_declaration); + SourceLocation FixItLoc; + if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) { + TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens(); + if (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>()) + FixItLoc = PP.getLocForEndOfToken(FTLoc.getLocalRangeEnd()); + } - return false; + if (FixItLoc.isInvalid()) + Diag(New->getLocation(), diag::warn_missing_exception_specification) + << New << OS.str(); + else { + // FIXME: This will get more complicated with C++0x + // late-specified return types. + Diag(New->getLocation(), diag::warn_missing_exception_specification) + << New << OS.str() + << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str()); } - Diag(New->getLocation(), DiagID); - Diag(Old->getLocation(), diag::note_previous_declaration); - return true; + if (!Old->getLocation().isInvalid()) + Diag(Old->getLocation(), diag::note_previous_declaration); + + return false; } /// CheckEquivalentExceptionSpec - Check if the two types have equivalent @@ -819,11 +790,8 @@ static CanThrowResult canSubExprsThrow(Sema &S, const Expr *CE) { return R; } -static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, - const Decl *D, - bool NullThrows = true) { - if (!D) - return NullThrows ? CT_Can : CT_Cannot; +static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D) { + assert(D && "Expected decl"); // See if we can get a function type from the decl somehow. const ValueDecl *VD = dyn_cast<ValueDecl>(D); @@ -927,8 +895,10 @@ CanThrowResult Sema::canThrow(const Expr *E) { CT = CT_Dependent; else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens())) CT = CT_Cannot; - else + else if (CE->getCalleeDecl()) CT = canCalleeThrow(*this, E, CE->getCalleeDecl()); + else + CT = CT_Can; if (CT == CT_Can) return CT; return mergeCanThrow(CT, canSubExprsThrow(*this, E)); @@ -974,7 +944,9 @@ CanThrowResult Sema::canThrow(const Expr *E) { cast<CXXDeleteExpr>(E)->getOperatorDelete()); if (const RecordType *RT = DTy->getAs<RecordType>()) { const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - CT = mergeCanThrow(CT, canCalleeThrow(*this, E, RD->getDestructor())); + const CXXDestructorDecl *DD = RD->getDestructor(); + if (DD) + CT = mergeCanThrow(CT, canCalleeThrow(*this, E, DD)); } if (CT == CT_Can) return CT; @@ -1012,6 +984,7 @@ CanThrowResult Sema::canThrow(const Expr *E) { case Expr::CompoundLiteralExprClass: case Expr::CXXConstCastExprClass: case Expr::CXXReinterpretCastExprClass: + case Expr::CXXStdInitializerListExprClass: case Expr::DesignatedInitExprClass: case Expr::ExprWithCleanupsClass: case Expr::ExtVectorElementExprClass: @@ -1022,6 +995,7 @@ CanThrowResult Sema::canThrow(const Expr *E) { case Expr::ParenExprClass: case Expr::ParenListExprClass: case Expr::ShuffleVectorExprClass: + case Expr::ConvertVectorExprClass: case Expr::VAArgExprClass: return canSubExprsThrow(*this, E); @@ -1052,7 +1026,7 @@ CanThrowResult Sema::canThrow(const Expr *E) { case Expr::ChooseExprClass: if (E->isTypeDependent() || E->isValueDependent()) return CT_Dependent; - return canThrow(cast<ChooseExpr>(E)->getChosenSubExpr(Context)); + return canThrow(cast<ChooseExpr>(E)->getChosenSubExpr()); case Expr::GenericSelectionExprClass: if (cast<GenericSelectionExpr>(E)->isResultDependent()) diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp index a9179fd48892..e1f65f4a4e1b 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -15,6 +15,7 @@ #include "TreeTransform.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" @@ -140,11 +141,13 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, return Result; } -/// \brief Emit a note explaining that this function is deleted or unavailable. +/// \brief Emit a note explaining that this function is deleted. void Sema::NoteDeletedFunction(FunctionDecl *Decl) { + assert(Decl->isDeleted()); + CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Decl); - if (Method && Method->isDeleted() && !Method->isDeletedAsWritten()) { + if (Method && Method->isDeleted() && Method->isDefaulted()) { // If the method was explicitly defaulted, point at that declaration. if (!Method->isImplicit()) Diag(Decl->getLocation(), diag::note_implicitly_deleted); @@ -158,8 +161,23 @@ void Sema::NoteDeletedFunction(FunctionDecl *Decl) { return; } + if (CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Decl)) { + if (CXXConstructorDecl *BaseCD = + const_cast<CXXConstructorDecl*>(CD->getInheritedConstructor())) { + Diag(Decl->getLocation(), diag::note_inherited_deleted_here); + if (BaseCD->isDeleted()) { + NoteDeletedFunction(BaseCD); + } else { + // FIXME: An explanation of why exactly it can't be inherited + // would be nice. + Diag(BaseCD->getLocation(), diag::note_cannot_inherit); + } + return; + } + } + Diag(Decl->getLocation(), diag::note_unavailable_here) - << 1 << Decl->isDeleted(); + << 1 << true; } /// \brief Determine whether a FunctionDecl was ever declared with an @@ -197,11 +215,11 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S, return; if (!Current->isInlined()) return; - if (Current->getLinkage() != ExternalLinkage) + if (!Current->isExternallyVisible()) return; - + // Check if the decl has internal linkage. - if (D->getLinkage() != InternalLinkage) + if (D->getFormalLinkage() != InternalLinkage) return; // Downgrade from ExtWarn to Extension if @@ -212,7 +230,7 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S, // This last can give us false negatives, but it's better than warning on // wrappers for simple C library functions. const FunctionDecl *UsedFn = dyn_cast<FunctionDecl>(D); - bool DowngradeWarning = S.getSourceManager().isFromMainFile(Loc); + bool DowngradeWarning = S.getSourceManager().isInMainFile(Loc); if (!DowngradeWarning && UsedFn) DowngradeWarning = UsedFn->isInlined() || UsedFn->hasAttr<ConstAttr>(); @@ -228,7 +246,7 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S, } void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) { - const FunctionDecl *First = Cur->getFirstDeclaration(); + const FunctionDecl *First = Cur->getFirstDecl(); // Suggest "static" on the function, if possible. if (!hasAnyExplicitStorageClass(First)) { @@ -255,7 +273,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, 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 + SuppressedDiagnosticsMap::iterator Pos = SuppressedDiagnostics.find(D->getCanonicalDecl()); if (Pos != SuppressedDiagnostics.end()) { SmallVectorImpl<PartialDiagnosticAt> &Suppressed = Pos->second; @@ -316,7 +334,7 @@ std::string Sema::getDeletedOrUnavailableSuffix(const FunctionDecl *FD) { /// if so, it checks that the requirements of the sentinel are /// satisfied. void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, - Expr **args, unsigned numArgs) { + ArrayRef<Expr *> Args) { const SentinelAttr *attr = D->getAttr<SentinelAttr>(); if (!attr) return; @@ -370,14 +388,14 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, // If there aren't enough arguments for all the formal parameters, // the sentinel, and the args after the sentinel, complain. - if (numArgs < numFormalParams + numArgsAfterSentinel + 1) { + if (Args.size() < numFormalParams + numArgsAfterSentinel + 1) { Diag(Loc, diag::warn_not_enough_argument) << D->getDeclName(); - Diag(D->getLocation(), diag::note_sentinel_here) << calleeType; + Diag(D->getLocation(), diag::note_sentinel_here) << int(calleeType); return; } // Otherwise, find the sentinel expression. - Expr *sentinelExpr = args[numArgs - numArgsAfterSentinel - 1]; + Expr *sentinelExpr = Args[Args.size() - numArgsAfterSentinel - 1]; if (!sentinelExpr) return; if (sentinelExpr->isValueDependent()) return; if (Context.isSentinelNullExpr(sentinelExpr)) return; @@ -398,12 +416,12 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, NullValue = "(void*) 0"; if (MissingNilLoc.isInvalid()) - Diag(Loc, diag::warn_missing_sentinel) << calleeType; + Diag(Loc, diag::warn_missing_sentinel) << int(calleeType); else Diag(MissingNilLoc, diag::warn_missing_sentinel) - << calleeType + << int(calleeType) << FixItHint::CreateInsertion(MissingNilLoc, ", " + NullValue); - Diag(D->getLocation(), diag::note_sentinel_here) << calleeType; + Diag(D->getLocation(), diag::note_sentinel_here) << int(calleeType); } SourceRange Sema::getExprRange(Expr *E) const { @@ -725,6 +743,17 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) { /// when we're in an unevaluated context. Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) { if (Ty->isIncompleteType()) { + // C++11 [expr.call]p7: + // After these conversions, if the argument does not have arithmetic, + // enumeration, pointer, pointer to member, or class type, the program + // is ill-formed. + // + // Since we've already performed array-to-pointer and function-to-pointer + // decay, the only such type in C++ is cv void. This also handles + // initializer lists as variadic arguments. + if (Ty->isVoidType()) + return VAK_Invalid; + if (Ty->isObjCObjectType()) return VAK_Invalid; return VAK_Valid; @@ -747,35 +776,50 @@ Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) { if (getLangOpts().ObjCAutoRefCount && Ty->isObjCLifetimeType()) return VAK_Valid; - return VAK_Invalid; + + if (Ty->isObjCObjectType()) + return VAK_Invalid; + + // FIXME: In C++11, these cases are conditionally-supported, meaning we're + // permitted to reject them. We should consider doing so. + return VAK_Undefined; } -bool Sema::variadicArgumentPODCheck(const Expr *E, VariadicCallType CT) { +void Sema::checkVariadicArgument(const Expr *E, VariadicCallType CT) { // Don't allow one to pass an Objective-C interface to a vararg. - const QualType & Ty = E->getType(); + const QualType &Ty = E->getType(); + VarArgKind VAK = isValidVarArgType(Ty); // Complain about passing non-POD types through varargs. - switch (isValidVarArgType(Ty)) { + switch (VAK) { case VAK_Valid: break; + case VAK_ValidInCXX11: - DiagRuntimeBehavior(E->getLocStart(), 0, + DiagRuntimeBehavior( + E->getLocStart(), 0, PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg) - << E->getType() << CT); + << E->getType() << CT); break; - case VAK_Invalid: { - if (Ty->isObjCObjectType()) - return DiagRuntimeBehavior(E->getLocStart(), 0, - PDiag(diag::err_cannot_pass_objc_interface_to_vararg) - << Ty << CT); - return DiagRuntimeBehavior(E->getLocStart(), 0, - PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) - << getLangOpts().CPlusPlus11 << Ty << CT); - } + case VAK_Undefined: + DiagRuntimeBehavior( + E->getLocStart(), 0, + PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) + << getLangOpts().CPlusPlus11 << Ty << CT); + break; + + case VAK_Invalid: + if (Ty->isObjCObjectType()) + DiagRuntimeBehavior( + E->getLocStart(), 0, + PDiag(diag::err_cannot_pass_objc_interface_to_vararg) + << Ty << CT); + else + Diag(E->getLocStart(), diag::err_cannot_pass_to_vararg) + << isa<InitListExpr>(E) << Ty << CT; + break; } - // c++ rules are enforced elsewhere. - return false; } /// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but @@ -805,7 +849,7 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, // Diagnostics regarding non-POD argument types are // emitted along with format string checking in Sema::CheckFunctionCall(). - if (isValidVarArgType(E->getType()) == VAK_Invalid) { + if (isValidVarArgType(E->getType()) == VAK_Undefined) { // Turn this into a trap. CXXScopeSpec SS; SourceLocation TemplateKWLoc; @@ -1230,25 +1274,23 @@ Sema::ActOnGenericSelectionExpr(SourceLocation KeyLoc, SourceLocation DefaultLoc, SourceLocation RParenLoc, Expr *ControllingExpr, - MultiTypeArg ArgTypes, - MultiExprArg ArgExprs) { + ArrayRef<ParsedType> ArgTypes, + ArrayRef<Expr *> ArgExprs) { unsigned NumAssocs = ArgTypes.size(); assert(NumAssocs == ArgExprs.size()); - ParsedType *ParsedTypes = ArgTypes.data(); - Expr **Exprs = ArgExprs.data(); - TypeSourceInfo **Types = new TypeSourceInfo*[NumAssocs]; for (unsigned i = 0; i < NumAssocs; ++i) { - if (ParsedTypes[i]) - (void) GetTypeFromParser(ParsedTypes[i], &Types[i]); + if (ArgTypes[i]) + (void) GetTypeFromParser(ArgTypes[i], &Types[i]); else Types[i] = 0; } ExprResult ER = CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc, - ControllingExpr, Types, Exprs, - NumAssocs); + ControllingExpr, + llvm::makeArrayRef(Types, NumAssocs), + ArgExprs); delete [] Types; return ER; } @@ -1258,9 +1300,10 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, SourceLocation DefaultLoc, SourceLocation RParenLoc, Expr *ControllingExpr, - TypeSourceInfo **Types, - Expr **Exprs, - unsigned NumAssocs) { + ArrayRef<TypeSourceInfo *> Types, + ArrayRef<Expr *> Exprs) { + unsigned NumAssocs = Types.size(); + assert(NumAssocs == Exprs.size()); if (ControllingExpr->getType()->isPlaceholderType()) { ExprResult result = CheckPlaceholderExpr(ControllingExpr); if (result.isInvalid()) return ExprError(); @@ -1328,8 +1371,7 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, if (IsResultDependent) return Owned(new (Context) GenericSelectionExpr( Context, KeyLoc, ControllingExpr, - llvm::makeArrayRef(Types, NumAssocs), - llvm::makeArrayRef(Exprs, NumAssocs), + Types, Exprs, DefaultLoc, RParenLoc, ContainsUnexpandedParameterPack)); SmallVector<unsigned, 1> CompatIndices; @@ -1352,7 +1394,7 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_multi_match) << ControllingExpr->getSourceRange() << ControllingExpr->getType() << (unsigned) CompatIndices.size(); - for (SmallVector<unsigned, 1>::iterator I = CompatIndices.begin(), + for (SmallVectorImpl<unsigned>::iterator I = CompatIndices.begin(), E = CompatIndices.end(); I != E; ++I) { Diag(Types[*I]->getTypeLoc().getBeginLoc(), diag::note_compat_assoc) @@ -1384,8 +1426,7 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, return Owned(new (Context) GenericSelectionExpr( Context, KeyLoc, ControllingExpr, - llvm::makeArrayRef(Types, NumAssocs), - llvm::makeArrayRef(Exprs, NumAssocs), + Types, Exprs, DefaultLoc, RParenLoc, ContainsUnexpandedParameterPack, ResultIndex)); } @@ -1421,7 +1462,8 @@ static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope, LookupResult R(S, OpName, UDSuffixLoc, Sema::LookupOrdinaryName); if (S.LookupLiteralOperator(Scope, R, llvm::makeArrayRef(ArgTy, Args.size()), - /*AllowRawAndTemplate*/false) == Sema::LOLR_Error) + /*AllowRaw*/false, /*AllowTemplate*/false, + /*AllowStringTemplate*/false) == Sema::LOLR_Error) return ExprError(); return S.BuildLiteralOperatorCall(R, OpNameInfo, Args, LitEndLoc); @@ -1446,36 +1488,39 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks, for (unsigned i = 0; i != NumStringToks; ++i) StringTokLocs.push_back(StringToks[i].getLocation()); - QualType StrTy = Context.CharTy; - if (Literal.isWide()) - StrTy = Context.getWCharType(); - else if (Literal.isUTF16()) - StrTy = Context.Char16Ty; - else if (Literal.isUTF32()) - StrTy = Context.Char32Ty; - else if (Literal.isPascal()) - StrTy = Context.UnsignedCharTy; - + QualType CharTy = Context.CharTy; StringLiteral::StringKind Kind = StringLiteral::Ascii; - if (Literal.isWide()) + if (Literal.isWide()) { + CharTy = Context.getWideCharType(); Kind = StringLiteral::Wide; - else if (Literal.isUTF8()) + } else if (Literal.isUTF8()) { Kind = StringLiteral::UTF8; - else if (Literal.isUTF16()) + } else if (Literal.isUTF16()) { + CharTy = Context.Char16Ty; Kind = StringLiteral::UTF16; - else if (Literal.isUTF32()) + } else if (Literal.isUTF32()) { + CharTy = Context.Char32Ty; Kind = StringLiteral::UTF32; + } else if (Literal.isPascal()) { + CharTy = Context.UnsignedCharTy; + } + QualType CharTyConst = CharTy; // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings) - StrTy.addConst(); + CharTyConst.addConst(); // Get an array type for the string, according to C99 6.4.5. This includes // the nul terminator character as well as the string length for pascal // strings. - StrTy = Context.getConstantArrayType(StrTy, + QualType StrTy = Context.getConstantArrayType(CharTyConst, llvm::APInt(32, Literal.GetNumStringChars()+1), - ArrayType::Normal, 0); + ArrayType::Normal, 0); + + // OpenCL v1.1 s6.5.3: a string literal is in the constant address space. + if (getLangOpts().OpenCL) { + StrTy = Context.getAddrSpaceQualType(StrTy, LangAS::opencl_constant); + } // Pass &StringTokLocs[0], StringTokLocs.size() to factory! StringLiteral *Lit = StringLiteral::Create(Context, Literal.GetString(), @@ -1498,12 +1543,57 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks, // 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()); + + DeclarationName OpName = + Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix); + DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc); + OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc); + + QualType ArgTy[] = { + Context.getArrayDecayedType(StrTy), SizeType + }; + + LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName); + switch (LookupLiteralOperator(UDLScope, R, ArgTy, + /*AllowRaw*/false, /*AllowTemplate*/false, + /*AllowStringTemplate*/true)) { + + case LOLR_Cooked: { + llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars()); + IntegerLiteral *LenArg = IntegerLiteral::Create(Context, Len, SizeType, + StringTokLocs[0]); + Expr *Args[] = { Lit, LenArg }; + + return BuildLiteralOperatorCall(R, OpNameInfo, Args, StringTokLocs.back()); + } + + case LOLR_StringTemplate: { + TemplateArgumentListInfo ExplicitArgs; + + unsigned CharBits = Context.getIntWidth(CharTy); + bool CharIsUnsigned = CharTy->isUnsignedIntegerType(); + llvm::APSInt Value(CharBits, CharIsUnsigned); + + TemplateArgument TypeArg(CharTy); + TemplateArgumentLocInfo TypeArgInfo(Context.getTrivialTypeSourceInfo(CharTy)); + ExplicitArgs.addArgument(TemplateArgumentLoc(TypeArg, TypeArgInfo)); + + for (unsigned I = 0, N = Lit->getLength(); I != N; ++I) { + Value = Lit->getCodeUnit(I); + TemplateArgument Arg(Context, Value, CharTy); + TemplateArgumentLocInfo ArgInfo; + ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo)); + } + return BuildLiteralOperatorCall(R, OpNameInfo, None, StringTokLocs.back(), + &ExplicitArgs); + } + case LOLR_Raw: + case LOLR_Template: + llvm_unreachable("unexpected literal operator lookup result"); + case LOLR_Error: + return ExprError(); + } + llvm_unreachable("unexpected literal operator lookup result"); } ExprResult @@ -1519,7 +1609,8 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, ExprResult Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, const DeclarationNameInfo &NameInfo, - const CXXScopeSpec *SS, NamedDecl *FoundD) { + const CXXScopeSpec *SS, NamedDecl *FoundD, + const TemplateArgumentListInfo *TemplateArgs) { if (getLangOpts().CUDA) if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext)) if (const FunctionDecl *Callee = dyn_cast<FunctionDecl>(D)) { @@ -1536,14 +1627,28 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, bool refersToEnclosingScope = (CurContext != D->getDeclContext() && - D->getDeclContext()->isFunctionOrMethod()); - - DeclRefExpr *E = DeclRefExpr::Create(Context, - SS ? SS->getWithLocInContext(Context) - : NestedNameSpecifierLoc(), - SourceLocation(), - D, refersToEnclosingScope, - NameInfo, Ty, VK, FoundD); + D->getDeclContext()->isFunctionOrMethod()) || + (isa<VarDecl>(D) && + cast<VarDecl>(D)->isInitCapture()); + + DeclRefExpr *E; + if (isa<VarTemplateSpecializationDecl>(D)) { + VarTemplateSpecializationDecl *VarSpec = + cast<VarTemplateSpecializationDecl>(D); + + E = DeclRefExpr::Create( + Context, + SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(), + VarSpec->getTemplateKeywordLoc(), D, refersToEnclosingScope, + NameInfo.getLoc(), Ty, VK, FoundD, TemplateArgs); + } else { + assert(!TemplateArgs && "No template arguments for non-variable" + " template specialization referrences"); + E = DeclRefExpr::Create( + Context, + SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(), + SourceLocation(), D, refersToEnclosingScope, NameInfo, Ty, VK, FoundD); + } MarkDeclRefReferenced(E); @@ -1553,7 +1658,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, E->getLocStart()); if (Level != DiagnosticsEngine::Ignored) - getCurFunction()->recordUseOfWeak(E); + recordUseOfEvaluatedWeak(E); } // Just in case we're building an illegal pointer-to-member. @@ -1602,7 +1707,7 @@ Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id, bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, CorrectionCandidateCallback &CCC, TemplateArgumentListInfo *ExplicitTemplateArgs, - llvm::ArrayRef<Expr *> Args) { + ArrayRef<Expr *> Args) { DeclarationName Name = R.getLookupName(); unsigned diagnostic = diag::err_undeclared_var_use; @@ -1722,10 +1827,14 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, if (S && (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS, CCC))) { std::string CorrectedStr(Corrected.getAsString(getLangOpts())); - std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); + bool DroppedSpecifier = + Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr; R.setLookupName(Corrected.getCorrection()); - if (NamedDecl *ND = Corrected.getCorrectionDecl()) { + bool AcceptableWithRecovery = false; + bool AcceptableWithoutRecovery = false; + NamedDecl *ND = Corrected.getCorrectionDecl(); + if (ND) { if (Corrected.isOverloaded()) { OverloadCandidateSet OCS(R.getNameLoc()); OverloadCandidateSet::iterator Best; @@ -1743,63 +1852,49 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, Args, OCS); } switch (OCS.BestViableFunction(*this, R.getNameLoc(), Best)) { - case OR_Success: - ND = Best->Function; - break; - default: - break; + case OR_Success: + ND = Best->Function; + Corrected.setCorrectionDecl(ND); + break; + default: + // FIXME: Arbitrarily pick the first declaration for the note. + Corrected.setCorrectionDecl(ND); + break; } } R.addDecl(ND); - if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) { - if (SS.isEmpty()) - Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr - << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); - else - Diag(R.getNameLoc(), diag::err_no_member_suggest) - << Name << computeDeclContext(SS, false) << CorrectedQuotedStr - << SS.getRange() - << FixItHint::CreateReplacement(Corrected.getCorrectionRange(), - CorrectedStr); - unsigned diag = isa<ImplicitParamDecl>(ND) - ? diag::note_implicit_param_decl - : diag::note_previous_decl; - - Diag(ND->getLocation(), diag) - << CorrectedQuotedStr; - - // Tell the callee to try to recover. - return false; - } - - if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) { - // FIXME: If we ended up with a typo for a type name or - // Objective-C class name, we're in trouble because the parser - // is in the wrong place to recover. Suggest the typo - // correction, but don't make it a fix-it since we're not going - // to recover well anyway. - if (SS.isEmpty()) - Diag(R.getNameLoc(), diagnostic_suggest) - << Name << CorrectedQuotedStr; - else - Diag(R.getNameLoc(), diag::err_no_member_suggest) - << Name << computeDeclContext(SS, false) << CorrectedQuotedStr - << SS.getRange(); - - // Don't try to recover; it won't work. - return true; - } + AcceptableWithRecovery = + isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND); + // FIXME: If we ended up with a typo for a type name or + // Objective-C class name, we're in trouble because the parser + // is in the wrong place to recover. Suggest the typo + // correction, but don't make it a fix-it since we're not going + // to recover well anyway. + AcceptableWithoutRecovery = + isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND); } else { // FIXME: We found a keyword. Suggest it, but don't provide a fix-it // because we aren't able to recover. + AcceptableWithoutRecovery = true; + } + + if (AcceptableWithRecovery || AcceptableWithoutRecovery) { + unsigned NoteID = (Corrected.getCorrectionDecl() && + isa<ImplicitParamDecl>(Corrected.getCorrectionDecl())) + ? diag::note_implicit_param_decl + : diag::note_previous_decl; if (SS.isEmpty()) - Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr; + diagnoseTypo(Corrected, PDiag(diagnostic_suggest) << Name, + PDiag(NoteID), AcceptableWithRecovery); else - Diag(R.getNameLoc(), diag::err_no_member_suggest) - << Name << computeDeclContext(SS, false) << CorrectedQuotedStr - << SS.getRange(); - return true; + diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest) + << Name << computeDeclContext(SS, false) + << DroppedSpecifier << SS.getRange(), + PDiag(NoteID), AcceptableWithRecovery); + + // Tell the callee whether to try to recover. + return !AcceptableWithRecovery; } } R.clear(); @@ -1824,10 +1919,10 @@ ExprResult Sema::ActOnIdExpression(Scope *S, UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand, - CorrectionCandidateCallback *CCC) { + CorrectionCandidateCallback *CCC, + bool IsInlineAsmIdentifier) { assert(!(IsAddressOfOperand && HasTrailingLParen) && "cannot be direct & operand and have a trailing lparen"); - if (SS.isInvalid()) return ExprError(); @@ -1918,6 +2013,7 @@ ExprResult Sema::ActOnIdExpression(Scope *S, bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen); if (R.empty() && !ADL) { + // Otherwise, this could be an implicitly declared function reference (legal // in C90, extension in C99, forbidden in C++). if (HasTrailingLParen && II && !getLangOpts().CPlusPlus) { @@ -1930,16 +2026,32 @@ ExprResult Sema::ActOnIdExpression(Scope *S, if (R.empty()) { // In Microsoft mode, if we are inside a template class member function // whose parent class has dependent base classes, and we can't resolve - // an identifier, then assume the identifier is type dependent. The - // goal is to postpone name lookup to instantiation time to be able to - // search into the type dependent base classes. + // an identifier, then assume the identifier is a member of a dependent + // base class. The goal is to postpone name lookup to instantiation time + // to be able to search into the type dependent base classes. + // FIXME: If we want 100% compatibility with MSVC, we will have delay all + // unqualified name lookup. Any name lookup during template parsing means + // clang might find something that MSVC doesn't. For now, we only handle + // the common case of members of a dependent base class. if (getLangOpts().MicrosoftMode) { CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext); - if (MD && MD->getParent()->hasAnyDependentBases()) - return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, - IsAddressOfOperand, TemplateArgs); + if (MD && MD->isInstance() && MD->getParent()->hasAnyDependentBases()) { + assert(SS.isEmpty() && "qualifiers should be already handled"); + QualType ThisType = MD->getThisType(Context); + // Since the 'this' expression is synthesized, we don't need to + // perform the double-lookup check. + NamedDecl *FirstQualifierInScope = 0; + return Owned(CXXDependentScopeMemberExpr::Create( + Context, /*This=*/0, ThisType, /*IsArrow=*/true, + /*Op=*/SourceLocation(), SS.getWithLocInContext(Context), + TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs)); + } } + // Don't diagnose an empty lookup for inline assmebly. + if (IsInlineAsmIdentifier) + return ExprError(); + CorrectionCandidateCallback DefaultValidator; if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator)) return ExprError(); @@ -2001,15 +2113,27 @@ ExprResult Sema::ActOnIdExpression(Scope *S, MightBeImplicitMember = true; else MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()) || - isa<IndirectFieldDecl>(R.getFoundDecl()); + isa<IndirectFieldDecl>(R.getFoundDecl()) || + isa<MSPropertyDecl>(R.getFoundDecl()); if (MightBeImplicitMember) return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs); } - if (TemplateArgs || TemplateKWLoc.isValid()) + if (TemplateArgs || TemplateKWLoc.isValid()) { + + // In C++1y, if this is a variable template id, then check it + // in BuildTemplateIdExpr(). + // The single lookup result must be a variable template declaration. + if (Id.getKind() == UnqualifiedId::IK_TemplateId && Id.TemplateId && + Id.TemplateId->Kind == TNK_Var_template) { + assert(R.getAsSingle<VarTemplateDecl>() && + "There should only be one declaration found."); + } + return BuildTemplateIdExpr(SS, TemplateKWLoc, R, ADL, TemplateArgs); + } return BuildDeclarationNameExpr(SS, R, ADL); } @@ -2139,6 +2263,14 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, return ExprError(); MarkAnyDeclReferenced(Loc, IV, true); + if (!IV->getBackingIvarReferencedInAccessor()) { + // Mark this ivar 'referenced' in this method, if it is a backing ivar + // of a property and current method is one of its property accessor. + const ObjCPropertyDecl *PDecl; + const ObjCIvarDecl *BIV = GetIvarBackingPropertyAccessor(CurMethod, PDecl); + if (BIV && BIV == IV) + IV->setBackingIvarReferencedInAccessor(true); + } ObjCMethodFamily MF = CurMethod->getMethodFamily(); if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize && @@ -2155,7 +2287,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, DiagnosticsEngine::Level Level = Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, Loc); if (Level != DiagnosticsEngine::Ignored) - getCurFunction()->recordUseOfWeak(Result); + recordUseOfEvaluatedWeak(Result); } if (CurContext->isClosure()) Diag(Loc, diag::warn_implicitly_retains_self) @@ -2289,9 +2421,8 @@ Sema::PerformObjectMemberConversion(Expr *From, // x = 17; // error: ambiguous base subobjects // Derived1::x = 17; // okay, pick the Base subobject of Derived1 // } - if (Qualifier) { + if (Qualifier && Qualifier->getAsType()) { QualType QType = QualType(Qualifier->getAsType(), 0); - assert(!QType.isNull() && "lookup done with dependent qualifier?"); assert(QType->isRecordType() && "lookup done with non-record type"); QualType QRecordType = QualType(QType->getAs<RecordType>(), 0); @@ -2400,7 +2531,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, // turn off ADL anyway). if (isa<UsingShadowDecl>(D)) D = cast<UsingShadowDecl>(D)->getTargetDecl(); - else if (D->getDeclContext()->isFunctionOrMethod()) + else if (D->getLexicalDeclContext()->isFunctionOrMethod()) return false; // C++0x [basic.lookup.argdep]p3: @@ -2477,10 +2608,9 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, } /// \brief Complete semantic analysis for a reference to the given declaration. -ExprResult -Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, - const DeclarationNameInfo &NameInfo, - NamedDecl *D, NamedDecl *FoundD) { +ExprResult Sema::BuildDeclarationNameExpr( + const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D, + NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs) { assert(D && "Cannot refer to a NULL declaration"); assert(!isa<FunctionTemplateDecl>(D) && "Cannot refer unambiguously to a function template"); @@ -2492,8 +2622,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) { // Specifically diagnose references to class templates that are missing // a template argument list. - Diag(Loc, diag::err_template_decl_ref) - << Template << SS.getRange(); + Diag(Loc, diag::err_template_decl_ref) << (isa<VarTemplateDecl>(D) ? 1 : 0) + << Template << SS.getRange(); Diag(Template->getLocation(), diag::note_template_decl_here); return ExprError(); } @@ -2583,6 +2713,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, } case Decl::Var: + case Decl::VarTemplateSpecialization: + case Decl::VarTemplatePartialSpecialization: // In C, "extern void blah;" is valid and is an r-value. if (!getLangOpts().CPlusPlus && !type.hasQualifiers() && @@ -2680,32 +2812,23 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, break; } - return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD); + return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD, + TemplateArgs); } } -ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { - PredefinedExpr::IdentType IT; - - switch (Kind) { - default: llvm_unreachable("Unknown simple primary expr!"); - case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2] - case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break; - case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break; - case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break; - } - - // Pre-defined identifiers are of type char[x], where x is the length of the - // string. - - Decl *currentDecl = getCurFunctionOrMethodDecl(); - // Blocks and lambdas can occur at global scope. Don't emit a warning. - if (!currentDecl) { - if (const BlockScopeInfo *BSI = getCurBlock()) - currentDecl = BSI->TheDecl; - else if (const LambdaScopeInfo *LSI = getCurLambda()) - currentDecl = LSI->CallOperator; - } +ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, + PredefinedExpr::IdentType IT) { + // Pick the current block, lambda, captured statement or function. + Decl *currentDecl = 0; + if (const BlockScopeInfo *BSI = getCurBlock()) + currentDecl = BSI->TheDecl; + else if (const LambdaScopeInfo *LSI = getCurLambda()) + currentDecl = LSI->CallOperator; + else if (const CapturedRegionScopeInfo *CSI = getCurCapturedRegion()) + currentDecl = CSI->TheCapturedDecl; + else + currentDecl = getCurFunctionOrMethodDecl(); if (!currentDecl) { Diag(Loc, diag::ext_predef_outside_function); @@ -2713,21 +2836,39 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { } QualType ResTy; - if (cast<DeclContext>(currentDecl)->isDependentContext()) { + if (cast<DeclContext>(currentDecl)->isDependentContext()) ResTy = Context.DependentTy; - } else { + else { + // Pre-defined identifiers are of type char[x], where x is the length of + // the string. unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length(); llvm::APInt LengthI(32, Length + 1); if (IT == PredefinedExpr::LFunction) - ResTy = Context.WCharTy.withConst(); + ResTy = Context.WideCharTy.withConst(); else ResTy = Context.CharTy.withConst(); ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0); } + return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT)); } +ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { + PredefinedExpr::IdentType IT; + + switch (Kind) { + default: llvm_unreachable("Unknown simple primary expr!"); + case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2] + case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break; + case tok::kw___FUNCDNAME__: IT = PredefinedExpr::FuncDName; break; // [MS] + case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break; + case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break; + } + + return BuildPredefinedExpr(Loc, IT); +} + ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) { SmallString<16> CharBuffer; bool Invalid = false; @@ -2742,7 +2883,7 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) { QualType Ty; if (Literal.isWide()) - Ty = Context.WCharTy; // L'x' -> wchar_t in C and C++. + Ty = Context.WideCharTy; // L'x' -> wchar_t in C and C++. else if (Literal.isUTF16()) Ty = Context.Char16Ty; // u'x' -> char16_t in C11 and C++11. else if (Literal.isUTF32()) @@ -2872,11 +3013,14 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc); OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc); + SourceLocation TokLoc = Tok.getLocation(); + // 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, CookedTy, - /*AllowRawAndTemplate*/true)) { + /*AllowRaw*/true, /*AllowTemplate*/true, + /*AllowStringTemplate*/false)) { case LOLR_Error: return ExprError(); @@ -2887,19 +3031,17 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { } else { llvm::APInt ResultVal(Context.getTargetInfo().getLongLongWidth(), 0); if (Literal.GetIntegerValue(ResultVal)) - Diag(Tok.getLocation(), diag::warn_integer_too_large); + Diag(Tok.getLocation(), diag::err_integer_too_large); Lit = IntegerLiteral::Create(Context, ResultVal, CookedTy, Tok.getLocation()); } - return BuildLiteralOperatorCall(R, OpNameInfo, Lit, - Tok.getLocation()); + return BuildLiteralOperatorCall(R, OpNameInfo, Lit, TokLoc); } 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.withConst(), llvm::APInt(32, Length + 1), @@ -2910,7 +3052,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { return BuildLiteralOperatorCall(R, OpNameInfo, Lit, TokLoc); } - case LOLR_Template: + 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'>() @@ -2925,11 +3067,12 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { TemplateArgumentLocInfo ArgInfo; ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo)); } - return BuildLiteralOperatorCall(R, OpNameInfo, None, Tok.getLocation(), + return BuildLiteralOperatorCall(R, OpNameInfo, None, TokLoc, &ExplicitArgs); } - - llvm_unreachable("unexpected literal operator lookup result"); + case LOLR_StringTemplate: + llvm_unreachable("unexpected literal operator lookup result"); + } } Expr *Res; @@ -2980,8 +3123,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { llvm::APInt ResultVal(MaxWidth, 0); if (Literal.GetIntegerValue(ResultVal)) { - // If this value didn't fit into uintmax_t, warn and force to ull. - Diag(Tok.getLocation(), diag::warn_integer_too_large); + // If this value didn't fit into uintmax_t, error and force to ull. + Diag(Tok.getLocation(), diag::err_integer_too_large); Ty = Context.UnsignedLongLongTy; assert(Context.getTypeSize(Ty) == ResultVal.getBitWidth() && "long long is not intmax_t?"); @@ -3103,6 +3246,10 @@ static bool CheckExtensionTraitOperandType(Sema &S, QualType T, SourceLocation Loc, SourceRange ArgRange, UnaryExprOrTypeTrait TraitKind) { + // Invalid types must be hard errors for SFINAE in C++. + if (S.LangOpts.CPlusPlus) + return true; + // C99 6.5.3.4p1: if (T->isFunctionType() && (TraitKind == UETT_SizeOf || TraitKind == UETT_AlignOf)) { @@ -3185,6 +3332,12 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E, ExprTy = E->getType(); assert(!ExprTy->isReferenceType()); + if (ExprTy->isFunctionType()) { + Diag(E->getExprLoc(), diag::err_sizeof_alignof_function_type) + << ExprKind << E->getSourceRange(); + return true; + } + if (CheckObjCTraitOperandConstraints(*this, ExprTy, E->getExprLoc(), E->getSourceRange(), ExprKind)) return true; @@ -3258,6 +3411,12 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType, ExprKind, ExprRange)) return true; + if (ExprType->isFunctionType()) { + Diag(OpLoc, diag::err_sizeof_alignof_function_type) + << ExprKind << ExprRange; + return true; + } + if (CheckObjCTraitOperandConstraints(*this, ExprType, OpLoc, ExprRange, ExprKind)) return true; @@ -3487,7 +3646,8 @@ static bool checkArithmeticOnObjCPointer(Sema &S, SourceLocation opLoc, Expr *op) { assert(op->getType()->isObjCObjectPointerType()); - if (S.LangOpts.ObjCRuntime.allowsPointerArithmetic()) + if (S.LangOpts.ObjCRuntime.allowsPointerArithmetic() && + !S.LangOpts.ObjCSubscriptingLegacyRuntime) return false; S.Diag(opLoc, diag::err_arithmetic_nonfragile_interface) @@ -3592,15 +3752,10 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, // Use custom logic if this should be the pseudo-object subscript // expression. - if (!LangOpts.ObjCRuntime.isSubscriptPointerArithmetic()) + if (!LangOpts.isSubscriptPointerArithmetic()) return BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, 0, 0); ResultType = PTy->getPointeeType(); - if (!LangOpts.ObjCRuntime.allowsPointerArithmetic()) { - Diag(LLoc, diag::err_subscript_nonfragile_interface) - << ResultType << BaseExpr->getSourceRange(); - return ExprError(); - } } else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) { // Handle the uncommon case of "123[Ptr]". BaseExpr = RHSExp; @@ -3612,7 +3767,7 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, BaseExpr = RHSExp; IndexExpr = LHSExp; ResultType = PTy->getPointeeType(); - if (!LangOpts.ObjCRuntime.allowsPointerArithmetic()) { + if (!LangOpts.isSubscriptPointerArithmetic()) { Diag(LLoc, diag::err_subscript_nonfragile_interface) << ResultType << BaseExpr->getSourceRange(); return ExprError(); @@ -3720,7 +3875,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, InstantiatingTemplate Inst(*this, CallLoc, Param, MutiLevelArgList.getInnermost()); - if (Inst) + if (Inst.isInvalid()) return ExprError(); ExprResult Result; @@ -3795,12 +3950,71 @@ Sema::getVariadicCallType(FunctionDecl *FDecl, const FunctionProtoType *Proto, if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(FDecl)) if (Method->isInstance()) return VariadicMethod; - } + } else if (Fn && Fn->getType() == Context.BoundMemberTy) + return VariadicMethod; return VariadicFunction; } return VariadicDoesNotApply; } +namespace { +class FunctionCallCCC : public FunctionCallFilterCCC { +public: + FunctionCallCCC(Sema &SemaRef, const IdentifierInfo *FuncName, + unsigned NumArgs, bool HasExplicitTemplateArgs) + : FunctionCallFilterCCC(SemaRef, NumArgs, HasExplicitTemplateArgs), + FunctionName(FuncName) {} + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + if (!candidate.getCorrectionSpecifier() || + candidate.getCorrectionAsIdentifierInfo() != FunctionName) { + return false; + } + + return FunctionCallFilterCCC::ValidateCandidate(candidate); + } + +private: + const IdentifierInfo *const FunctionName; +}; +} + +static TypoCorrection TryTypoCorrectionForCall(Sema &S, + DeclarationNameInfo FuncName, + ArrayRef<Expr *> Args) { + FunctionCallCCC CCC(S, FuncName.getName().getAsIdentifierInfo(), + Args.size(), false); + if (TypoCorrection Corrected = + S.CorrectTypo(FuncName, Sema::LookupOrdinaryName, + S.getScopeForContext(S.CurContext), NULL, CCC)) { + if (NamedDecl *ND = Corrected.getCorrectionDecl()) { + if (Corrected.isOverloaded()) { + OverloadCandidateSet OCS(FuncName.getLoc()); + OverloadCandidateSet::iterator Best; + for (TypoCorrection::decl_iterator CD = Corrected.begin(), + CDEnd = Corrected.end(); + CD != CDEnd; ++CD) { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*CD)) + S.AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none), Args, + OCS); + } + switch (OCS.BestViableFunction(S, FuncName.getLoc(), Best)) { + case OR_Success: + ND = Best->Function; + Corrected.setCorrectionDecl(ND); + break; + default: + break; + } + } + if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) { + return Corrected; + } + } + } + return TypoCorrection(); +} + /// ConvertArgumentsForCall - Converts the arguments specified in /// Args/NumArgs to the parameter types of the function FDecl with /// function prototype Proto. Call is the call expression itself, and @@ -3811,7 +4025,7 @@ bool Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, FunctionDecl *FDecl, const FunctionProtoType *Proto, - Expr **Args, unsigned NumArgs, + ArrayRef<Expr *> Args, SourceLocation RParenLoc, bool IsExecConfig) { // Bail out early if calling a builtin with custom typechecking. @@ -3833,9 +4047,23 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, // If too few arguments are available (and we don't have default // arguments for the remaining parameters), don't make the call. - if (NumArgs < NumArgsInProto) { - if (NumArgs < MinArgs) { - if (MinArgs == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName()) + if (Args.size() < NumArgsInProto) { + if (Args.size() < MinArgs) { + MemberExpr *ME = dyn_cast<MemberExpr>(Fn); + TypoCorrection TC; + if (FDecl && (TC = TryTypoCorrectionForCall( + *this, DeclarationNameInfo(FDecl->getDeclName(), + (ME ? ME->getMemberLoc() + : Fn->getLocStart())), + Args))) { + unsigned diag_id = + MinArgs == NumArgsInProto && !Proto->isVariadic() + ? diag::err_typecheck_call_too_few_args_suggest + : diag::err_typecheck_call_too_few_args_at_least_suggest; + diagnoseTypo(TC, PDiag(diag_id) << FnKind << MinArgs + << static_cast<unsigned>(Args.size()) + << Fn->getSourceRange()); + } else if (MinArgs == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName()) Diag(RParenLoc, MinArgs == NumArgsInProto && !Proto->isVariadic() ? diag::err_typecheck_call_too_few_args_one : diag::err_typecheck_call_too_few_args_at_least_one) @@ -3846,10 +4074,11 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, ? diag::err_typecheck_call_too_few_args : diag::err_typecheck_call_too_few_args_at_least) << FnKind - << MinArgs << NumArgs << Fn->getSourceRange(); + << MinArgs << static_cast<unsigned>(Args.size()) + << Fn->getSourceRange(); // Emit the location of the prototype. - if (FDecl && !FDecl->getBuiltinID() && !IsExecConfig) + if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig) Diag(FDecl->getLocStart(), diag::note_callee_decl) << FDecl; @@ -3860,29 +4089,44 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, // If too many are passed and not variadic, error on the extras and drop // them. - if (NumArgs > NumArgsInProto) { + if (Args.size() > NumArgsInProto) { if (!Proto->isVariadic()) { - if (NumArgsInProto == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName()) + TypoCorrection TC; + if (FDecl && (TC = TryTypoCorrectionForCall( + *this, DeclarationNameInfo(FDecl->getDeclName(), + Fn->getLocStart()), + Args))) { + unsigned diag_id = + MinArgs == NumArgsInProto && !Proto->isVariadic() + ? diag::err_typecheck_call_too_many_args_suggest + : diag::err_typecheck_call_too_many_args_at_most_suggest; + diagnoseTypo(TC, PDiag(diag_id) << FnKind << NumArgsInProto + << static_cast<unsigned>(Args.size()) + << Fn->getSourceRange()); + } else if (NumArgsInProto == 1 && FDecl && + FDecl->getParamDecl(0)->getDeclName()) Diag(Args[NumArgsInProto]->getLocStart(), MinArgs == NumArgsInProto ? diag::err_typecheck_call_too_many_args_one : diag::err_typecheck_call_too_many_args_at_most_one) << FnKind - << FDecl->getParamDecl(0) << NumArgs << Fn->getSourceRange() + << FDecl->getParamDecl(0) << static_cast<unsigned>(Args.size()) + << Fn->getSourceRange() << SourceRange(Args[NumArgsInProto]->getLocStart(), - Args[NumArgs-1]->getLocEnd()); + Args.back()->getLocEnd()); else Diag(Args[NumArgsInProto]->getLocStart(), MinArgs == NumArgsInProto ? diag::err_typecheck_call_too_many_args : diag::err_typecheck_call_too_many_args_at_most) << FnKind - << NumArgsInProto << NumArgs << Fn->getSourceRange() + << NumArgsInProto << static_cast<unsigned>(Args.size()) + << Fn->getSourceRange() << SourceRange(Args[NumArgsInProto]->getLocStart(), - Args[NumArgs-1]->getLocEnd()); + Args.back()->getLocEnd()); // Emit the location of the prototype. - if (FDecl && !FDecl->getBuiltinID() && !IsExecConfig) + if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig) Diag(FDecl->getLocStart(), diag::note_callee_decl) << FDecl; @@ -3895,7 +4139,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, VariadicCallType CallType = getVariadicCallType(FDecl, Proto, Fn); Invalid = GatherArgumentsForCall(Call->getLocStart(), FDecl, - Proto, 0, Args, NumArgs, AllArgs, CallType); + Proto, 0, Args, AllArgs, CallType); if (Invalid) return true; unsigned TotalNumArgs = AllArgs.size(); @@ -3909,15 +4153,15 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, const FunctionProtoType *Proto, unsigned FirstProtoArg, - Expr **Args, unsigned NumArgs, - SmallVector<Expr *, 8> &AllArgs, + ArrayRef<Expr *> Args, + SmallVectorImpl<Expr *> &AllArgs, VariadicCallType CallType, bool AllowExplicit, bool IsListInitialization) { unsigned NumArgsInProto = Proto->getNumArgs(); - unsigned NumArgsToCheck = NumArgs; + unsigned NumArgsToCheck = Args.size(); bool Invalid = false; - if (NumArgs != NumArgsInProto) + if (Args.size() != NumArgsInProto) // Use default arguments for missing arguments NumArgsToCheck = NumArgsInProto; unsigned ArgIx = 0; @@ -3927,7 +4171,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, Expr *Arg; ParmVarDecl *Param; - if (ArgIx < NumArgs) { + if (ArgIx < Args.size()) { Arg = Args[ArgIx++]; if (RequireCompleteType(Arg->getLocStart(), @@ -3941,15 +4185,25 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, Param = FDecl->getParamDecl(i); // Strip the unbridged-cast placeholder expression off, if applicable. + bool CFAudited = false; if (Arg->getType() == Context.ARCUnbridgedCastTy && FDecl && FDecl->hasAttr<CFAuditedTransferAttr>() && (!Param || !Param->hasAttr<CFConsumedAttr>())) Arg = stripARCUnbridgedCast(Arg); + else if (getLangOpts().ObjCAutoRefCount && + FDecl && FDecl->hasAttr<CFAuditedTransferAttr>() && + (!Param || !Param->hasAttr<CFConsumedAttr>())) + CFAudited = true; InitializedEntity Entity = Param ? InitializedEntity::InitializeParameter(Context, Param, ProtoArgType) : InitializedEntity::InitializeParameter(Context, ProtoArgType, Proto->isArgConsumed(i)); + + // Remember that parameter belongs to a CF audited API. + if (CFAudited) + Entity.setParameterCFAudited(); + ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), Owned(Arg), @@ -3988,7 +4242,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, // return __unknown_anytype aren't *really* variadic. if (Proto->getResultType() == Context.UnknownAnyTy && FDecl && FDecl->isExternC()) { - for (unsigned i = ArgIx; i != NumArgs; ++i) { + for (unsigned i = ArgIx, e = Args.size(); i != e; ++i) { QualType paramType; // ignored ExprResult arg = checkUnknownAnyArg(CallLoc, Args[i], paramType); Invalid |= arg.isInvalid(); @@ -3997,7 +4251,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, // Otherwise do argument promotion, (C99 6.5.2.2p7). } else { - for (unsigned i = ArgIx; i != NumArgs; ++i) { + for (unsigned i = ArgIx, e = Args.size(); i != e; ++i) { ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], CallType, FDecl); Invalid |= Arg.isInvalid(); @@ -4006,7 +4260,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, } // Check for array bounds violations. - for (unsigned i = ArgIx; i != NumArgs; ++i) + for (unsigned i = ArgIx, e = Args.size(); i != e; ++i) CheckArrayAccess(Args[i]); } return Invalid; @@ -4014,6 +4268,8 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, static void DiagnoseCalleeStaticArrayParam(Sema &S, ParmVarDecl *PVD) { TypeLoc TL = PVD->getTypeSourceInfo()->getTypeLoc(); + if (DecayedTypeLoc DTL = TL.getAs<DecayedTypeLoc>()) + TL = DTL.getOriginalLoc(); if (ArrayTypeLoc ATL = TL.getAs<ArrayTypeLoc>()) S.Diag(PVD->getLocation(), diag::note_callee_static_array) << ATL.getLocalSourceRange(); @@ -4188,8 +4444,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, // Determine whether this is a call to an object (C++ [over.call.object]). if (Fn->getType()->isRecordType()) return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, - ArgExprs.data(), - ArgExprs.size(), RParenLoc)); + ArgExprs, RParenLoc)); if (Fn->getType() == Context.UnknownAnyTy) { ExprResult result = rebuildUnknownAnyFunction(*this, Fn); @@ -4198,8 +4453,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, } if (Fn->getType() == Context.BoundMemberTy) { - return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs.data(), - ArgExprs.size(), RParenLoc); + return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs, RParenLoc); } } @@ -4212,11 +4466,11 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, OverloadExpr *ovl = find.Expression; if (isa<UnresolvedLookupExpr>(ovl)) { UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(ovl); - return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, ArgExprs.data(), - ArgExprs.size(), RParenLoc, ExecConfig); + return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, ArgExprs, + RParenLoc, ExecConfig); } else { - return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs.data(), - ArgExprs.size(), RParenLoc); + return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs, + RParenLoc); } } } @@ -4240,9 +4494,8 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, else if (isa<MemberExpr>(NakedFn)) NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl(); - return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs.data(), - ArgExprs.size(), RParenLoc, ExecConfig, - IsExecConfig); + return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs, RParenLoc, + ExecConfig, IsExecConfig); } ExprResult @@ -4283,6 +4536,19 @@ ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy, RParenLoc)); } +/// ActOnConvertVectorExpr - create a new convert-vector expression from the +/// provided arguments. +/// +/// __builtin_convertvector( value, dst type ) +/// +ExprResult Sema::ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy, + SourceLocation BuiltinLoc, + SourceLocation RParenLoc) { + TypeSourceInfo *TInfo; + GetTypeFromParser(ParsedDestTy, &TInfo); + return SemaConvertVectorExpr(E, TInfo, BuiltinLoc, RParenLoc); +} + /// BuildResolvedCallExpr - Build a call to a resolved expression, /// i.e. an expression not of \p OverloadTy. The expression should /// unary-convert to an expression of function-pointer or @@ -4292,7 +4558,7 @@ ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy, ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc, - Expr **Args, unsigned NumArgs, + ArrayRef<Expr *> Args, SourceLocation RParenLoc, Expr *Config, bool IsExecConfig) { FunctionDecl *FDecl = dyn_cast_or_null<FunctionDecl>(NDecl); @@ -4318,17 +4584,12 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, CallExpr *TheCall; if (Config) TheCall = new (Context) CUDAKernelCallExpr(Context, Fn, - cast<CallExpr>(Config), - llvm::makeArrayRef(Args,NumArgs), - Context.BoolTy, - VK_RValue, + cast<CallExpr>(Config), Args, + Context.BoolTy, VK_RValue, RParenLoc); else - TheCall = new (Context) CallExpr(Context, Fn, - llvm::makeArrayRef(Args, NumArgs), - Context.BoolTy, - VK_RValue, - RParenLoc); + TheCall = new (Context) CallExpr(Context, Fn, Args, Context.BoolTy, + VK_RValue, RParenLoc); // Bail out early if calling a builtin with custom typechecking. if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) @@ -4391,8 +4652,8 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT); if (Proto) { - if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, NumArgs, - RParenLoc, IsExecConfig)) + if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, RParenLoc, + IsExecConfig)) return ExprError(); } else { assert(isa<FunctionNoProtoType>(FuncT) && "Unknown FunctionType!"); @@ -4401,11 +4662,11 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, // Check if we have too few/too many template arguments, based // on our knowledge of the function definition. const FunctionDecl *Def = 0; - if (FDecl->hasBody(Def) && NumArgs != Def->param_size()) { + if (FDecl->hasBody(Def) && Args.size() != Def->param_size()) { Proto = Def->getType()->getAs<FunctionProtoType>(); - if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size())) + if (!Proto || !(Proto->isVariadic() && Args.size() >= Def->param_size())) Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments) - << (NumArgs > Def->param_size()) << FDecl << Fn->getSourceRange(); + << (Args.size() > Def->param_size()) << FDecl << Fn->getSourceRange(); } // If the function we're calling isn't a function prototype, but we have @@ -4415,7 +4676,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, } // Promote the arguments (C99 6.5.2.2p6). - for (unsigned i = 0; i != NumArgs; i++) { + for (unsigned i = 0, e = Args.size(); i != e; i++) { Expr *Arg = Args[i]; if (Proto && i < Proto->getNumArgs()) { @@ -4456,7 +4717,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, // Check for sentinels if (NDecl) - DiagnoseSentinelCalls(NDecl, LParenLoc, Args, NumArgs); + DiagnoseSentinelCalls(NDecl, LParenLoc, Args); // Do special checking on direct calls to functions. if (FDecl) { @@ -4466,7 +4727,10 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (BuiltinID) return CheckBuiltinFunctionCall(BuiltinID, TheCall); } else if (NDecl) { - if (CheckBlockCall(NDecl, TheCall, Proto)) + if (CheckPointerCall(NDecl, TheCall, Proto)) + return ExprError(); + } else { + if (CheckOtherCall(TheCall, Proto)) return ExprError(); } @@ -4476,7 +4740,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, ExprResult Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty, SourceLocation RParenLoc, Expr *InitExpr) { - assert((Ty != 0) && "ActOnCompoundLiteral(): missing type"); + assert(Ty && "ActOnCompoundLiteral(): missing type"); // FIXME: put back this assert when initializers are worked out. //assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression"); @@ -4522,7 +4786,10 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, LiteralExpr = Result.get(); bool isFileScope = getCurFunctionOrMethodDecl() == 0; - if (isFileScope) { // 6.5.2.5p3 + if (isFileScope && + !LiteralExpr->isTypeDependent() && + !LiteralExpr->isValueDependent() && + !literalType->isDependentType()) { // 6.5.2.5p3 if (CheckForConstantInitializer(LiteralExpr, literalType)) return ExprError(); } @@ -5108,9 +5375,11 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS, QualType lhptee, rhptee; // Get the pointee types. + bool IsBlockPointer = false; if (const BlockPointerType *LHSBTy = LHSTy->getAs<BlockPointerType>()) { lhptee = LHSBTy->getPointeeType(); rhptee = RHSTy->castAs<BlockPointerType>()->getPointeeType(); + IsBlockPointer = true; } else { lhptee = LHSTy->castAs<PointerType>()->getPointeeType(); rhptee = RHSTy->castAs<PointerType>()->getPointeeType(); @@ -5152,7 +5421,10 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS, // The pointer types are compatible. QualType ResultTy = CompositeTy.withCVRQualifiers(MergedCVRQual); - ResultTy = S.Context.getPointerType(ResultTy); + if (IsBlockPointer) + ResultTy = S.Context.getBlockPointerType(ResultTy); + else + ResultTy = S.Context.getPointerType(ResultTy); LHS = S.ImpCastExprToType(LHS.take(), ResultTy, CK_BitCast); RHS = S.ImpCastExprToType(RHS.take(), ResultTy, CK_BitCast); @@ -5266,28 +5538,26 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, VK = VK_RValue; OK = OK_Ordinary; + // First, check the condition. Cond = UsualUnaryConversions(Cond.take()); if (Cond.isInvalid()) return QualType(); - LHS = UsualUnaryConversions(LHS.take()); - if (LHS.isInvalid()) + if (checkCondition(*this, Cond.get())) return QualType(); - RHS = UsualUnaryConversions(RHS.take()); - if (RHS.isInvalid()) + + // Now check the two expressions. + if (LHS.get()->getType()->isVectorType() || + RHS.get()->getType()->isVectorType()) + return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false); + + UsualArithmeticConversions(LHS, RHS); + if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); QualType CondTy = Cond.get()->getType(); QualType LHSTy = LHS.get()->getType(); QualType RHSTy = RHS.get()->getType(); - // first, check the condition. - if (checkCondition(*this, Cond.get())) - return QualType(); - - // Now check the two expressions. - if (LHSTy->isVectorType() || RHSTy->isVectorType()) - return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false); - // 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. (OpenCL v1.1 s6.3.i) @@ -5297,12 +5567,8 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, // If both operands have arithmetic type, do the usual arithmetic conversions // to find a common type: C99 6.5.15p3,5. - if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) { - UsualArithmeticConversions(LHS, RHS); - if (LHS.isInvalid() || RHS.isInvalid()) - return QualType(); + if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) return LHS.get()->getType(); - } // If both operands are the same structure or union type, the result is that // type. @@ -5638,7 +5904,14 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, Expr *commonExpr = 0; if (LHSExpr == 0) { commonExpr = CondExpr; - + // Lower out placeholder types first. This is important so that we don't + // try to capture a placeholder. This happens in few cases in C++; such + // as Objective-C++'s dictionary subscripting syntax. + if (commonExpr->hasPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(commonExpr); + if (!result.isUsable()) return ExprError(); + commonExpr = result.take(); + } // We usually want to apply unary conversions *before* saving, except // in the special case of a C++ l-value conditional. if (!(getLangOpts().CPlusPlus @@ -6248,7 +6521,8 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Sema::AssignConvertType Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, - bool Diagnose) { + bool Diagnose, + bool DiagnoseCFAudited) { if (getLangOpts().CPlusPlus) { if (!LHSType->isRecordType() && !LHSType->isAtomicType()) { // C++ 5.17p3: If the left operand is not of class type, the @@ -6290,12 +6564,14 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, // C99 6.5.16.1p1: the left operand is a pointer and the right is // a null pointer constant. - if ((LHSType->isPointerType() || - LHSType->isObjCObjectPointerType() || - LHSType->isBlockPointerType()) - && RHS.get()->isNullPointerConstant(Context, - Expr::NPC_ValueDependentIsNull)) { - RHS = ImpCastExprToType(RHS.take(), LHSType, CK_NullToPointer); + if ((LHSType->isPointerType() || LHSType->isObjCObjectPointerType() || + LHSType->isBlockPointerType()) && + RHS.get()->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { + CastKind Kind; + CXXCastPath Path; + CheckPointerConversion(RHS.get(), LHSType, Kind, Path, false); + RHS = ImpCastExprToType(RHS.take(), LHSType, Kind, VK_RValue, &Path); return Compatible; } @@ -6321,9 +6597,14 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, // so that we can use references in built-in functions even in C. // The getNonReferenceType() call makes sure that the resulting expression // does not have reference type. - if (result != Incompatible && RHS.get()->getType() != LHSType) - RHS = ImpCastExprToType(RHS.take(), - LHSType.getNonLValueExprType(Context), Kind); + if (result != Incompatible && RHS.get()->getType() != LHSType) { + QualType Ty = LHSType.getNonLValueExprType(Context); + Expr *E = RHS.take(); + if (getLangOpts().ObjCAutoRefCount) + CheckObjCARCConversion(SourceRange(), Ty, E, CCK_ImplicitConversion, + DiagnoseCFAudited); + RHS = ImpCastExprToType(E, Ty, Kind); + } return result; } @@ -6402,12 +6683,19 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, return LHSType; } } - if (EltTy->isRealFloatingType() && RHSType->isScalarType() && - RHSType->isRealFloatingType()) { - int order = Context.getFloatingTypeOrder(EltTy, RHSType); - if (order > 0) - RHS = ImpCastExprToType(RHS.take(), EltTy, CK_FloatingCast); - if (order >= 0) { + if (EltTy->isRealFloatingType() && RHSType->isScalarType()) { + if (RHSType->isRealFloatingType()) { + int order = Context.getFloatingTypeOrder(EltTy, RHSType); + if (order > 0) + RHS = ImpCastExprToType(RHS.take(), EltTy, CK_FloatingCast); + if (order >= 0) { + RHS = ImpCastExprToType(RHS.take(), LHSType, CK_VectorSplat); + if (swapped) std::swap(RHS, LHS); + return LHSType; + } + } + if (RHSType->isIntegralType(Context)) { + RHS = ImpCastExprToType(RHS.take(), EltTy, CK_IntegralToFloating); RHS = ImpCastExprToType(RHS.take(), LHSType, CK_VectorSplat); if (swapped) std::swap(RHS, LHS); return LHSType; @@ -6480,11 +6768,12 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS, return InvalidOperands(Loc, LHS, RHS); // Check for division by zero. - if (IsDiv && - RHS.get()->isNullPointerConstant(Context, - Expr::NPC_ValueDependentIsNotNull)) - DiagRuntimeBehavior(Loc, RHS.get(), PDiag(diag::warn_division_by_zero) - << RHS.get()->getSourceRange()); + llvm::APSInt RHSValue; + if (IsDiv && !RHS.get()->isValueDependent() && + RHS.get()->EvaluateAsInt(RHSValue, Context) && RHSValue == 0) + DiagRuntimeBehavior(Loc, RHS.get(), + PDiag(diag::warn_division_by_zero) + << RHS.get()->getSourceRange()); return compType; } @@ -6509,10 +6798,12 @@ QualType Sema::CheckRemainderOperands( return InvalidOperands(Loc, LHS, RHS); // Check for remainder by zero. - if (RHS.get()->isNullPointerConstant(Context, - Expr::NPC_ValueDependentIsNotNull)) - DiagRuntimeBehavior(Loc, RHS.get(), PDiag(diag::warn_remainder_by_zero) - << RHS.get()->getSourceRange()); + llvm::APSInt RHSValue; + if (!RHS.get()->isValueDependent() && + RHS.get()->EvaluateAsInt(RHSValue, Context) && RHSValue == 0) + DiagRuntimeBehavior(Loc, RHS.get(), + PDiag(diag::warn_remainder_by_zero) + << RHS.get()->getSourceRange()); return compType; } @@ -6685,12 +6976,63 @@ static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc, // 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) + Self.Diag(OpLoc, diag::note_string_plus_scalar_silence) << FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&") << FixItHint::CreateReplacement(SourceRange(OpLoc), "[") << FixItHint::CreateInsertion(EndLoc, "]"); } else - Self.Diag(OpLoc, diag::note_string_plus_int_silence); + Self.Diag(OpLoc, diag::note_string_plus_scalar_silence); +} + +/// \brief Emit a warning when adding a char literal to a string. +static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc, + Expr *LHSExpr, Expr *RHSExpr) { + const DeclRefExpr *StringRefExpr = + dyn_cast<DeclRefExpr>(LHSExpr->IgnoreImpCasts()); + const CharacterLiteral *CharExpr = + dyn_cast<CharacterLiteral>(RHSExpr->IgnoreImpCasts()); + if (!StringRefExpr) { + StringRefExpr = dyn_cast<DeclRefExpr>(RHSExpr->IgnoreImpCasts()); + CharExpr = dyn_cast<CharacterLiteral>(LHSExpr->IgnoreImpCasts()); + } + + if (!CharExpr || !StringRefExpr) + return; + + const QualType StringType = StringRefExpr->getType(); + + // Return if not a PointerType. + if (!StringType->isAnyPointerType()) + return; + + // Return if not a CharacterType. + if (!StringType->getPointeeType()->isAnyCharacterType()) + return; + + ASTContext &Ctx = Self.getASTContext(); + SourceRange DiagRange(LHSExpr->getLocStart(), RHSExpr->getLocEnd()); + + const QualType CharType = CharExpr->getType(); + if (!CharType->isAnyCharacterType() && + CharType->isIntegerType() && + llvm::isUIntN(Ctx.getCharWidth(), CharExpr->getValue())) { + Self.Diag(OpLoc, diag::warn_string_plus_char) + << DiagRange << Ctx.CharTy; + } else { + Self.Diag(OpLoc, diag::warn_string_plus_char) + << DiagRange << CharExpr->getType(); + } + + // Only print a fixit for str + char, not for char + str. + if (isa<CharacterLiteral>(RHSExpr->IgnoreImpCasts())) { + SourceLocation EndLoc = Self.PP.getLocForEndOfToken(RHSExpr->getLocEnd()); + Self.Diag(OpLoc, diag::note_string_plus_scalar_silence) + << FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&") + << FixItHint::CreateReplacement(SourceRange(OpLoc), "[") + << FixItHint::CreateInsertion(EndLoc, "]"); + } else { + Self.Diag(OpLoc, diag::note_string_plus_scalar_silence); + } } /// \brief Emit error when two pointers are incompatible. @@ -6719,9 +7061,11 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6 if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); - // Diagnose "string literal" '+' int. - if (Opc == BO_Add) + // Diagnose "string literal" '+' int and string '+' "char literal". + if (Opc == BO_Add) { diagnoseStringPlusInt(*this, Loc, LHS.get(), RHS.get()); + diagnoseStringPlusChar(*this, Loc, LHS.get(), RHS.get()); + } // handle the common case first (both operands are arithmetic). if (!compType.isNull() && compType->isArithmeticType()) { @@ -6846,6 +7190,18 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, LHS.get(), RHS.get())) return QualType(); + // The pointee type may have zero size. As an extension, a structure or + // union may have zero size or an array may have zero length. In this + // case subtraction does not make sense. + if (!rpointee->isVoidType() && !rpointee->isFunctionType()) { + CharUnits ElementSize = Context.getTypeSizeInChars(rpointee); + if (ElementSize.isZero()) { + Diag(Loc,diag::warn_sub_ptr_zero_size_types) + << rpointee.getUnqualifiedType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + } + } + if (CompLHSTy) *CompLHSTy = LHS.get()->getType(); return Context.getPointerDiffType(); } @@ -7234,6 +7590,65 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc, } } +static void diagnoseLogicalNotOnLHSofComparison(Sema &S, ExprResult &LHS, + ExprResult &RHS, + SourceLocation Loc, + unsigned OpaqueOpc) { + // This checking requires bools. + if (!S.getLangOpts().Bool) return; + + // Check that left hand side is !something. + UnaryOperator *UO = dyn_cast<UnaryOperator>(LHS.get()->IgnoreImpCasts()); + if (!UO || UO->getOpcode() != UO_LNot) return; + + // Only check if the right hand side is non-bool arithmetic type. + if (RHS.get()->getType()->isBooleanType()) return; + + // Make sure that the something in !something is not bool. + Expr *SubExpr = UO->getSubExpr()->IgnoreImpCasts(); + if (SubExpr->getType()->isBooleanType()) return; + + // Emit warning. + S.Diag(UO->getOperatorLoc(), diag::warn_logical_not_on_lhs_of_comparison) + << Loc; + + // First note suggest !(x < y) + SourceLocation FirstOpen = SubExpr->getLocStart(); + SourceLocation FirstClose = RHS.get()->getLocEnd(); + FirstClose = S.getPreprocessor().getLocForEndOfToken(FirstClose); + if (FirstClose.isInvalid()) + FirstOpen = SourceLocation(); + S.Diag(UO->getOperatorLoc(), diag::note_logical_not_fix) + << FixItHint::CreateInsertion(FirstOpen, "(") + << FixItHint::CreateInsertion(FirstClose, ")"); + + // Second note suggests (!x) < y + SourceLocation SecondOpen = LHS.get()->getLocStart(); + SourceLocation SecondClose = LHS.get()->getLocEnd(); + SecondClose = S.getPreprocessor().getLocForEndOfToken(SecondClose); + if (SecondClose.isInvalid()) + SecondOpen = SourceLocation(); + S.Diag(UO->getOperatorLoc(), diag::note_logical_not_silence_with_parens) + << FixItHint::CreateInsertion(SecondOpen, "(") + << FixItHint::CreateInsertion(SecondClose, ")"); +} + +// Get the decl for a simple expression: a reference to a variable, +// an implicit C++ field reference, or an implicit ObjC ivar reference. +static ValueDecl *getCompareDecl(Expr *E) { + if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E)) + return DR->getDecl(); + if (ObjCIvarRefExpr* Ivar = dyn_cast<ObjCIvarRefExpr>(E)) { + if (Ivar->isFreeIvar()) + return Ivar->getDecl(); + } + if (MemberExpr* Mem = dyn_cast<MemberExpr>(E)) { + if (Mem->isImplicitAccess()) + return Mem->getMemberDecl(); + } + return 0; +} + // C99 6.5.8, C++ [expr.rel] QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned OpaqueOpc, @@ -7254,11 +7669,13 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, Expr *RHSStripped = RHS.get()->IgnoreParenImpCasts(); checkEnumComparison(*this, Loc, LHS.get(), RHS.get()); + diagnoseLogicalNotOnLHSofComparison(*this, LHS, RHS, Loc, OpaqueOpc); if (!LHSType->hasFloatingRepresentation() && !(LHSType->isBlockPointerType() && IsRelational) && !LHS.get()->getLocStart().isMacroID() && - !RHS.get()->getLocStart().isMacroID()) { + !RHS.get()->getLocStart().isMacroID() && + ActiveTemplateInstantiations.empty()) { // For non-floating point types, check for self-comparisons of the form // x == x, x != x, x < x, etc. These always evaluate to a constant, and // often indicate logic errors in the program. @@ -7269,37 +7686,34 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, // obvious cases in the definition of the template anyways. The idea is to // warn when the typed comparison operator will always evaluate to the same // result. - if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHSStripped)) { - if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) { - if (DRL->getDecl() == DRR->getDecl() && - !IsWithinTemplateSpecialization(DRL->getDecl())) { - DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) - << 0 // self- - << (Opc == BO_EQ - || Opc == BO_LE - || Opc == BO_GE)); - } else if (LHSType->isArrayType() && RHSType->isArrayType() && - !DRL->getDecl()->getType()->isReferenceType() && - !DRR->getDecl()->getType()->isReferenceType()) { - // what is it always going to eval to? - char always_evals_to; - switch(Opc) { - case BO_EQ: // e.g. array1 == array2 - always_evals_to = 0; // false - break; - case BO_NE: // e.g. array1 != array2 - always_evals_to = 1; // true - break; - default: - // best we can say is 'a constant' - always_evals_to = 2; // e.g. array1 <= array2 - break; - } - DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) - << 1 // array - << always_evals_to); + ValueDecl *DL = getCompareDecl(LHSStripped); + ValueDecl *DR = getCompareDecl(RHSStripped); + if (DL && DR && DL == DR && !IsWithinTemplateSpecialization(DL)) { + DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) + << 0 // self- + << (Opc == BO_EQ + || Opc == BO_LE + || Opc == BO_GE)); + } else if (DL && DR && LHSType->isArrayType() && RHSType->isArrayType() && + !DL->getType()->isReferenceType() && + !DR->getType()->isReferenceType()) { + // what is it always going to eval to? + char always_evals_to; + switch(Opc) { + case BO_EQ: // e.g. array1 == array2 + always_evals_to = 0; // false + break; + case BO_NE: // e.g. array1 != array2 + always_evals_to = 1; // true + break; + default: + // best we can say is 'a constant' + always_evals_to = 2; // e.g. array1 <= array2 + break; } - } + DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) + << 1 // array + << always_evals_to); } if (isa<CastExpr>(LHSStripped)) @@ -7333,21 +7747,9 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, } // C99 6.5.8p3 / C99 6.5.9p4 - if (LHS.get()->getType()->isArithmeticType() && - RHS.get()->getType()->isArithmeticType()) { - UsualArithmeticConversions(LHS, RHS); - if (LHS.isInvalid() || RHS.isInvalid()) - return QualType(); - } - else { - LHS = UsualUnaryConversions(LHS.take()); - if (LHS.isInvalid()) - return QualType(); - - RHS = UsualUnaryConversions(RHS.take()); - if (RHS.isInvalid()) - return QualType(); - } + UsualArithmeticConversions(LHS, RHS); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); LHSType = LHS.get()->getType(); RHSType = RHS.get()->getType(); @@ -7534,12 +7936,20 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS, /*isError*/false); } - if (LHSIsNull && !RHSIsNull) - LHS = ImpCastExprToType(LHS.take(), RHSType, + if (LHSIsNull && !RHSIsNull) { + Expr *E = LHS.take(); + if (getLangOpts().ObjCAutoRefCount) + CheckObjCARCConversion(SourceRange(), RHSType, E, CCK_ImplicitConversion); + LHS = ImpCastExprToType(E, RHSType, RPT ? CK_BitCast :CK_CPointerToObjCPointerCast); - else - RHS = ImpCastExprToType(RHS.take(), LHSType, + } + else { + Expr *E = RHS.take(); + if (getLangOpts().ObjCAutoRefCount) + CheckObjCARCConversion(SourceRange(), LHSType, E, CCK_ImplicitConversion); + RHS = ImpCastExprToType(E, LHSType, LPT ? CK_BitCast :CK_CPointerToObjCPointerCast); + } return ResultTy; } if (LHSType->isObjCObjectPointerType() && @@ -7651,7 +8061,8 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, // For non-floating point types, check for self-comparisons of the form // x == x, x != x, x < x, etc. These always evaluate to a constant, and // often indicate logic errors in the program. - if (!LHSType->hasFloatingRepresentation()) { + if (!LHSType->hasFloatingRepresentation() && + ActiveTemplateInstantiations.empty()) { if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHS.get()->IgnoreParenImpCasts())) if (DeclRefExpr* DRR @@ -7806,28 +8217,6 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] return Context.BoolTy; } -/// IsReadonlyProperty - Verify that otherwise a valid l-value expression -/// is a read-only property; return true if so. A readonly property expression -/// depends on various declarations and thus must be treated specially. -/// -static bool IsReadonlyProperty(Expr *E, Sema &S) { - const ObjCPropertyRefExpr *PropExpr = dyn_cast<ObjCPropertyRefExpr>(E); - if (!PropExpr) return false; - if (PropExpr->isImplicitProperty()) return false; - - 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 IsReadonlyMessage(Expr *E, Sema &S) { const MemberExpr *ME = dyn_cast<MemberExpr>(E); if (!ME) return false; @@ -7858,9 +8247,14 @@ static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) { assert(var->hasLocalStorage() && "capture added 'const' to non-local?"); // Decide whether the first capture was for a block or a lambda. - DeclContext *DC = S.CurContext; - while (DC->getParent() != var->getDeclContext()) + DeclContext *DC = S.CurContext, *Prev = 0; + while (DC != var->getDeclContext()) { + Prev = DC; DC = DC->getParent(); + } + // Unless we have an init-capture, we've gone one step too far. + if (!var->isInitCapture()) + DC = Prev; return (isa<BlockDecl>(DC) ? NCCK_Block : NCCK_Lambda); } @@ -7871,9 +8265,7 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { 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 (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S)) + if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S)) IsLV = Expr::MLV_InvalidMessageExpression; if (IsLV == Expr::MLV_Valid) return false; @@ -7956,7 +8348,6 @@ 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_ReadonlyProperty: case Expr::MLV_NoSetterProperty: llvm_unreachable("readonly properties should be processed differently"); case Expr::MLV_InvalidMessageExpression: @@ -8163,6 +8554,10 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, } // Increment of bool sets it to true, but is deprecated. S.Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange(); + } else if (S.getLangOpts().CPlusPlus && ResType->isEnumeralType()) { + // Error on enum increments and decrements in C++ mode + S.Diag(OpLoc, diag::err_increment_decrement_enum) << IsInc << ResType; + return QualType(); } else if (ResType->isRealType()) { // OK! } else if (ResType->isPointerType()) { @@ -8186,6 +8581,9 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, IsInc, IsPrefix); } else if (S.getLangOpts().AltiVec && ResType->isVectorType()) { // OK! ( C/C++ Language Extensions for CBEA(Version 2.6) 10.3 ) + } else if(S.getLangOpts().OpenCL && ResType->isVectorType() && + ResType->getAs<VectorType>()->getElementType()->isIntegerType()) { + // OpenCL V1.2 6.3 says dec/inc ops operate on integer vector types. } else { S.Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement) << ResType << int(IsInc) << Op->getSourceRange(); @@ -8289,43 +8687,50 @@ 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, ExprResult &OrigOp, - SourceLocation OpLoc) { +QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { if (const BuiltinType *PTy = OrigOp.get()->getType()->getAsPlaceholderType()){ if (PTy->getKind() == BuiltinType::Overload) { - if (!isa<OverloadExpr>(OrigOp.get()->IgnoreParens())) { - assert(cast<UnaryOperator>(OrigOp.get()->IgnoreParens())->getOpcode() - == UO_AddrOf); - S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof_addrof_function) + Expr *E = OrigOp.get()->IgnoreParens(); + if (!isa<OverloadExpr>(E)) { + assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf); + Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof_addrof_function) << OrigOp.get()->getSourceRange(); return QualType(); } - - return S.Context.OverloadTy; + + OverloadExpr *Ovl = cast<OverloadExpr>(E); + if (isa<UnresolvedMemberExpr>(Ovl)) + if (!ResolveSingleFunctionTemplateSpecialization(Ovl)) { + Diag(OpLoc, diag::err_invalid_form_pointer_member_function) + << OrigOp.get()->getSourceRange(); + return QualType(); + } + + return Context.OverloadTy; } if (PTy->getKind() == BuiltinType::UnknownAny) - return S.Context.UnknownAnyTy; + return Context.UnknownAnyTy; if (PTy->getKind() == BuiltinType::BoundMember) { - S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function) + Diag(OpLoc, diag::err_invalid_form_pointer_member_function) << OrigOp.get()->getSourceRange(); return QualType(); } - OrigOp = S.CheckPlaceholderExpr(OrigOp.take()); + OrigOp = CheckPlaceholderExpr(OrigOp.take()); if (OrigOp.isInvalid()) return QualType(); } if (OrigOp.get()->isTypeDependent()) - return S.Context.DependentTy; + return Context.DependentTy; assert(!OrigOp.get()->getType()->isPlaceholderType()); // Make sure to ignore parentheses in subsequent checks Expr *op = OrigOp.get()->IgnoreParens(); - if (S.getLangOpts().C99) { + if (getLangOpts().C99) { // Implement C99-only parts of addressof rules. if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) { if (uOp->getOpcode() == UO_Deref) @@ -8337,28 +8742,28 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp, // expressions here, but the result of one is always an lvalue anyway. } ValueDecl *dcl = getPrimaryDecl(op); - Expr::LValueClassification lval = op->ClassifyLValue(S.Context); + Expr::LValueClassification lval = op->ClassifyLValue(Context); unsigned AddressOfError = AO_No_Error; if (lval == Expr::LV_ClassTemporary || lval == Expr::LV_ArrayTemporary) { - bool sfinae = (bool)S.isSFINAEContext(); - S.Diag(OpLoc, S.isSFINAEContext() ? diag::err_typecheck_addrof_temporary - : diag::ext_typecheck_addrof_temporary) + bool sfinae = (bool)isSFINAEContext(); + Diag(OpLoc, isSFINAEContext() ? diag::err_typecheck_addrof_temporary + : diag::ext_typecheck_addrof_temporary) << op->getType() << op->getSourceRange(); if (sfinae) return QualType(); // Materialize the temporary as an lvalue so that we can take its address. - OrigOp = op = new (S.Context) - MaterializeTemporaryExpr(op->getType(), OrigOp.take(), true); + OrigOp = op = new (Context) + MaterializeTemporaryExpr(op->getType(), OrigOp.take(), true, 0); } else if (isa<ObjCSelectorExpr>(op)) { - return S.Context.getPointerType(op->getType()); + return Context.getPointerType(op->getType()); } else if (lval == Expr::LV_MemberFunction) { // If it's an instance method, make a member pointer. // The expression must have exactly the form &A::foo. // 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) + Diag(OpLoc, diag::err_invalid_form_pointer_member_function) << OrigOp.get()->getSourceRange(); return QualType(); } @@ -8367,25 +8772,29 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp, // The id-expression was parenthesized. if (OrigOp.get() != DRE) { - S.Diag(OpLoc, diag::err_parens_pointer_member_function) + Diag(OpLoc, diag::err_parens_pointer_member_function) << OrigOp.get()->getSourceRange(); // The method was named without a qualifier. } else if (!DRE->getQualifier()) { if (MD->getParent()->getName().empty()) - S.Diag(OpLoc, diag::err_unqualified_pointer_member_function) + Diag(OpLoc, diag::err_unqualified_pointer_member_function) << op->getSourceRange(); else { SmallString<32> Str; StringRef Qual = (MD->getParent()->getName() + "::").toStringRef(Str); - S.Diag(OpLoc, diag::err_unqualified_pointer_member_function) + Diag(OpLoc, diag::err_unqualified_pointer_member_function) << op->getSourceRange() << FixItHint::CreateInsertion(op->getSourceRange().getBegin(), Qual); } } - return S.Context.getMemberPointerType(op->getType(), - S.Context.getTypeDeclType(MD->getParent()).getTypePtr()); + // Taking the address of a dtor is illegal per C++ [class.dtor]p2. + if (isa<CXXDestructorDecl>(MD)) + Diag(OpLoc, diag::err_typecheck_addrof_dtor) << op->getSourceRange(); + + return Context.getMemberPointerType(op->getType(), + Context.getTypeDeclType(MD->getParent()).getTypePtr()); } else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) { // C99 6.5.3.2p1 // The operand must be either an l-value or a function designator @@ -8394,7 +8803,7 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp, if (isa<PseudoObjectExpr>(op)) { AddressOfError = AO_Property_Expansion; } else { - S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof) + Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof) << op->getType() << op->getSourceRange(); return QualType(); } @@ -8412,11 +8821,11 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &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.getLangOpts().CPlusPlus) { + !getLangOpts().CPlusPlus) { AddressOfError = AO_Register_Variable; } } else if (isa<FunctionTemplateDecl>(dcl)) { - return S.Context.OverloadTy; + return Context.OverloadTy; } else if (isa<FieldDecl>(dcl) || isa<IndirectFieldDecl>(dcl)) { // Okay: we can take the address of a field. // Could be a pointer to member, though, if there is an explicit @@ -8425,16 +8834,16 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp, DeclContext *Ctx = dcl->getDeclContext(); if (Ctx && Ctx->isRecord()) { if (dcl->getType()->isReferenceType()) { - S.Diag(OpLoc, - diag::err_cannot_form_pointer_to_member_of_reference_type) + Diag(OpLoc, + diag::err_cannot_form_pointer_to_member_of_reference_type) << dcl->getDeclName() << dcl->getType(); return QualType(); } while (cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion()) Ctx = Ctx->getParent(); - return S.Context.getMemberPointerType(op->getType(), - S.Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr()); + return Context.getMemberPointerType(op->getType(), + Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr()); } } } else if (!isa<FunctionDecl>(dcl) && !isa<NonTypeTemplateParmDecl>(dcl)) @@ -8442,7 +8851,7 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp, } if (AddressOfError != AO_No_Error) { - diagnoseAddressOfInvalidType(S, OpLoc, op, AddressOfError); + diagnoseAddressOfInvalidType(*this, OpLoc, op, AddressOfError); return QualType(); } @@ -8450,13 +8859,13 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp, // Taking the address of a void variable is technically illegal, but we // allow it in cases which are otherwise valid. // Example: "extern void x; void* y = &x;". - S.Diag(OpLoc, diag::ext_typecheck_addrof_void) << op->getSourceRange(); + Diag(OpLoc, diag::ext_typecheck_addrof_void) << op->getSourceRange(); } // If the operand has type "type", the result has type "pointer to type". if (op->getType()->isObjCObjectType()) - return S.Context.getObjCObjectPointerType(op->getType()); - return S.Context.getPointerType(op->getType()); + return Context.getObjCObjectPointerType(op->getType()); + return Context.getPointerType(op->getType()); } /// CheckIndirectionOperand - Type check unary indirection (prefix '*'). @@ -8630,7 +9039,20 @@ static void checkObjCPointerIntrospection(Sema &S, ExprResult &L, ExprResult &R, // looks for code trying to introspect into tagged pointers, which // code should generally never do. if (ObjCPointerExpr && isa<IntegerLiteral>(OtherExpr->IgnoreParenCasts())) { - S.Diag(OpLoc, diag::warn_objc_pointer_masking) + unsigned Diag = diag::warn_objc_pointer_masking; + // Determine if we are introspecting the result of performSelectorXXX. + const Expr *Ex = ObjCPointerExpr->IgnoreParenCasts(); + // Special case messages to -performSelector and friends, which + // can return non-pointer values boxed in a pointer value. + // Some clients may wish to silence warnings in this subcase. + if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(Ex)) { + Selector S = ME->getSelector(); + StringRef SelArg0 = S.getNameForSlot(0); + if (SelArg0.startswith("performSelector")) + Diag = diag::warn_objc_pointer_masking_performSelector; + } + + S.Diag(OpLoc, Diag) << ObjCPointerExpr->getSourceRange(); } } @@ -9149,7 +9571,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, Opc == UO_PreDec); break; case UO_AddrOf: - resultType = CheckAddressOfOperand(*this, Input, OpLoc); + resultType = CheckAddressOfOperand(Input, OpLoc); break; case UO_Deref: { Input = DefaultFunctionArrayLvalueConversion(Input.take()); @@ -9167,9 +9589,6 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, if (resultType->isArithmeticType() || // C99 6.5.3.3p1 resultType->isVectorType()) break; - else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6-7 - resultType->isEnumeralType()) - break; else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6 Opc == UO_Plus && resultType->isPointerType()) @@ -9392,7 +9811,7 @@ ExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc, /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo". ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, LabelDecl *TheDecl) { - TheDecl->setUsed(); + TheDecl->markUsed(Context); // Create the AST node. The address of a label always has type 'void*'. return Owned(new (Context) AddrLabelExpr(OpLoc, LabLoc, TheDecl, Context.getPointerType(Context.VoidTy))); @@ -9657,9 +10076,15 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, // If the member was found in a base class, introduce OffsetOfNodes for // the base class indirections. - CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, - /*DetectVirtual=*/false); + CXXBasePaths Paths; if (IsDerivedFrom(CurrentType, Context.getTypeDeclType(Parent), Paths)) { + if (Paths.getDetectedVirtual()) { + Diag(OC.LocEnd, diag::err_offsetof_field_of_virtual_base) + << MemberDecl->getDeclName() + << SourceRange(BuiltinLoc, RParenLoc); + return ExprError(); + } + CXXBasePath &Path = Paths.front(); for (CXXBasePath::iterator B = Path.begin(), BEnd = Path.end(); B != BEnd; ++B) @@ -9715,6 +10140,7 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, ExprObjectKind OK = OK_Ordinary; QualType resType; bool ValueDependent = false; + bool CondIsTrue = false; if (CondExpr->isTypeDependent() || CondExpr->isValueDependent()) { resType = Context.DependentTy; ValueDependent = true; @@ -9727,9 +10153,10 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, if (CondICE.isInvalid()) return ExprError(); CondExpr = CondICE.take(); + CondIsTrue = condEval.getZExtValue(); // If the condition is > zero, then the AST type is the same as the LSHExpr. - Expr *ActiveExpr = condEval.getZExtValue() ? LHSExpr : RHSExpr; + Expr *ActiveExpr = CondIsTrue ? LHSExpr : RHSExpr; resType = ActiveExpr->getType(); ValueDependent = ActiveExpr->isValueDependent(); @@ -9738,7 +10165,7 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, } return Owned(new (Context) ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr, - resType, VK, OK, RPLoc, + resType, VK, OK, RPLoc, CondIsTrue, resType->isDependentType(), ValueDependent)); } @@ -9750,6 +10177,17 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, /// ActOnBlockStart - This callback is invoked when a block literal is started. void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) { BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc); + + if (LangOpts.CPlusPlus) { + Decl *ManglingContextDecl; + if (MangleNumberingContext *MCtx = + getCurrentMangleNumberContext(Block->getDeclContext(), + ManglingContextDecl)) { + unsigned ManglingNumber = MCtx->getManglingNumber(Block); + Block->setBlockMangling(ManglingNumber, ManglingContextDecl); + } + } + PushBlockScope(CurScope, Block); CurContext->addDecl(Block); if (CurScope) @@ -9822,13 +10260,6 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, CurBlock->TheDecl->setIsVariadic(isVariadic); - // Don't allow returning a objc interface by value. - if (RetTy->isObjCObjectType()) { - Diag(ParamInfo.getLocStart(), - diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; - return; - } - // Context.DependentTy is used as a placeholder for a missing block // return type. TODO: what should we do with declarators like: // ^ * { ... } @@ -9876,11 +10307,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, // Finally we can process decl attributes. ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo); - // Put the parameter variables in scope. We can bail out immediately - // if we don't have any. - if (Params.empty()) - return; - + // Put the parameter variables in scope. for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(), E = CurBlock->TheDecl->param_end(); AI != E; ++AI) { (*AI)->setOwningFunction(CurBlock->TheDecl); @@ -9942,7 +10369,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (Cap.isThisCapture()) continue; BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture(), - Cap.isNested(), Cap.getCopyExpr()); + Cap.isNested(), Cap.getInitExpr()); Captures.push_back(NewCap); } BSI->TheDecl->setCaptures(Context, Captures.begin(), Captures.end(), @@ -9973,11 +10400,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.TypeQuals = 0; // FIXME: silently? EPI.ExtInfo = Ext; - BlockTy = - Context.getFunctionType(RetTy, - ArrayRef<QualType>(FPT->arg_type_begin(), - FPT->getNumArgs()), - EPI); + BlockTy = Context.getFunctionType(RetTy, FPT->getArgTypes(), EPI); } // If we don't have a function type, just build one from nothing. @@ -10007,7 +10430,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, computeNRVO(Body, getCurBlock()); BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy); - const AnalysisBasedWarnings::Policy &WP = AnalysisWarnings.getDefaultPolicy(); + AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result); // If the block isn't obviously global, i.e. it captures anything at @@ -10145,7 +10568,8 @@ ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) { } static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType, - Expr *SrcExpr, FixItHint &Hint) { + Expr *SrcExpr, FixItHint &Hint, + bool &IsNSString) { if (!SemaRef.getLangOpts().ObjC1) return; @@ -10159,6 +10583,7 @@ static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType, const ObjCInterfaceDecl *ID = PT->getInterfaceDecl(); if (!ID || !ID->getIdentifier()->isStr("NSString")) return; + IsNSString = true; } // Ignore any parens, implicit casts (should only be @@ -10192,6 +10617,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, ConversionFixItGenerator ConvHints; bool MayHaveConvFixit = false; bool MayHaveFunctionDiff = false; + bool IsNSString = false; switch (ConvTy) { case Compatible: @@ -10209,8 +10635,11 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, MayHaveConvFixit = true; break; case IncompatiblePointer: - MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint); - DiagKind = diag::ext_typecheck_convert_incompatible_pointer; + MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint, IsNSString); + DiagKind = + (Action == AA_Passing_CFAudited ? + diag::err_arc_typecheck_convert_incompatible_pointer : + diag::ext_typecheck_convert_incompatible_pointer); CheckInferredResultType = DstType->isObjCObjectPointerType() && SrcType->isObjCObjectPointerType(); if (Hint.isNull() && !CheckInferredResultType) { @@ -10220,6 +10649,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, SrcType = SrcType.getUnqualifiedType(); DstType = DstType.getUnqualifiedType(); } + else if (IsNSString && !Hint.isNull()) + DiagKind = diag::warn_missing_atsign_prefix; MayHaveConvFixit = true; break; case IncompatiblePointerSign: @@ -10302,6 +10733,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, case AA_Returning: case AA_Passing: + case AA_Passing_CFAudited: case AA_Converting: case AA_Sending: case AA_Casting: @@ -10312,7 +10744,10 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, } PartialDiagnostic FDiag = PDiag(DiagKind); - FDiag << FirstType << SecondType << Action << SrcExpr->getSourceRange(); + if (Action == AA_Passing_CFAudited) + FDiag << FirstType << SecondType << SrcExpr->getSourceRange(); + else + FDiag << FirstType << SecondType << Action << SrcExpr->getSourceRange(); // If we can fix the conversion, suggest the FixIts. assert(ConvHints.isNull() || Hint.isNull()); @@ -10394,112 +10829,52 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, // have a single non-explicit conversion function to an integral or // unscoped enumeration type ExprResult Converted; - if (!Diagnoser.Suppress) { - class CXX11ConvertDiagnoser : public ICEConvertDiagnoser { - public: - CXX11ConvertDiagnoser() : ICEConvertDiagnoser(false, true) { } - - virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, - QualType T) { - return S.Diag(Loc, diag::err_ice_not_integral) << T; - } - - virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, - SourceLocation Loc, - QualType T) { - return S.Diag(Loc, diag::err_ice_incomplete_type) << T; - } - - virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S, - SourceLocation Loc, - QualType T, - QualType ConvTy) { - return S.Diag(Loc, diag::err_ice_explicit_conversion) << T << ConvTy; - } - - virtual DiagnosticBuilder noteExplicitConv(Sema &S, - CXXConversionDecl *Conv, - QualType ConvTy) { - return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here) - << ConvTy->isEnumeralType() << ConvTy; - } - - virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, - QualType T) { - return S.Diag(Loc, diag::err_ice_ambiguous_conversion) << T; - } - - virtual DiagnosticBuilder noteAmbiguous(Sema &S, - CXXConversionDecl *Conv, - QualType ConvTy) { - return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here) - << ConvTy->isEnumeralType() << ConvTy; - } - - virtual DiagnosticBuilder diagnoseConversion(Sema &S, - SourceLocation Loc, - QualType T, - QualType ConvTy) { - return DiagnosticBuilder::getEmpty(); - } - } ConvertDiagnoser; + class CXX11ConvertDiagnoser : public ICEConvertDiagnoser { + public: + CXX11ConvertDiagnoser(bool Silent) + : ICEConvertDiagnoser(/*AllowScopedEnumerations*/false, + Silent, true) {} + + virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_ice_not_integral) << T; + } - Converted = ConvertToIntegralOrEnumerationType(DiagLoc, E, - ConvertDiagnoser, - /*AllowScopedEnumerations*/ false); - } else { - // The caller wants to silently enquire whether this is an ICE. Don't - // produce any diagnostics if it isn't. - class SilentICEConvertDiagnoser : public ICEConvertDiagnoser { - public: - SilentICEConvertDiagnoser() : ICEConvertDiagnoser(true, true) { } - - virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, - QualType T) { - return DiagnosticBuilder::getEmpty(); - } - - virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, - SourceLocation Loc, - QualType T) { - return DiagnosticBuilder::getEmpty(); - } - - virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S, - SourceLocation Loc, - QualType T, - QualType ConvTy) { - return DiagnosticBuilder::getEmpty(); - } - - virtual DiagnosticBuilder noteExplicitConv(Sema &S, - CXXConversionDecl *Conv, - QualType ConvTy) { - return DiagnosticBuilder::getEmpty(); - } - - virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, - QualType T) { - return DiagnosticBuilder::getEmpty(); - } - - virtual DiagnosticBuilder noteAmbiguous(Sema &S, - CXXConversionDecl *Conv, - QualType ConvTy) { - return DiagnosticBuilder::getEmpty(); - } - - virtual DiagnosticBuilder diagnoseConversion(Sema &S, - SourceLocation Loc, - QualType T, - QualType ConvTy) { - return DiagnosticBuilder::getEmpty(); - } - } ConvertDiagnoser; - - Converted = ConvertToIntegralOrEnumerationType(DiagLoc, E, - ConvertDiagnoser, false); - } + virtual SemaDiagnosticBuilder diagnoseIncomplete( + Sema &S, SourceLocation Loc, QualType T) { + return S.Diag(Loc, diag::err_ice_incomplete_type) << T; + } + + virtual SemaDiagnosticBuilder diagnoseExplicitConv( + Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) { + return S.Diag(Loc, diag::err_ice_explicit_conversion) << T << ConvTy; + } + + virtual SemaDiagnosticBuilder noteExplicitConv( + Sema &S, CXXConversionDecl *Conv, QualType ConvTy) { + return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here) + << ConvTy->isEnumeralType() << ConvTy; + } + + virtual SemaDiagnosticBuilder diagnoseAmbiguous( + Sema &S, SourceLocation Loc, QualType T) { + return S.Diag(Loc, diag::err_ice_ambiguous_conversion) << T; + } + + virtual SemaDiagnosticBuilder noteAmbiguous( + Sema &S, CXXConversionDecl *Conv, QualType ConvTy) { + return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here) + << ConvTy->isEnumeralType() << ConvTy; + } + + virtual SemaDiagnosticBuilder diagnoseConversion( + Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) { + llvm_unreachable("conversion functions are permitted"); + } + } ConvertDiagnoser(Diagnoser.Suppress); + + Converted = PerformContextualImplicitConversion(DiagLoc, E, + ConvertDiagnoser); if (Converted.isInvalid()) return Converted; E = Converted.take(); @@ -10647,21 +11022,30 @@ void Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t, bool IsDecltype) { - Decl *LambdaContextDecl = ExprEvalContexts.back().LambdaContextDecl; - PushExpressionEvaluationContext(NewContext, LambdaContextDecl, IsDecltype); + Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl; + PushExpressionEvaluationContext(NewContext, ClosureContextDecl, IsDecltype); } void Sema::PopExpressionEvaluationContext() { ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back(); if (!Rec.Lambdas.empty()) { - if (Rec.isUnevaluated()) { - // C++11 [expr.prim.lambda]p2: - // A lambda-expression shall not appear in an unevaluated operand - // (Clause 5). + if (Rec.isUnevaluated() || Rec.Context == ConstantEvaluated) { + unsigned D; + if (Rec.isUnevaluated()) { + // C++11 [expr.prim.lambda]p2: + // A lambda-expression shall not appear in an unevaluated operand + // (Clause 5). + D = diag::err_lambda_unevaluated_operand; + } else { + // C++1y [expr.const]p2: + // A conditional-expression e is a core constant expression unless the + // evaluation of e, following the rules of the abstract machine, would + // evaluate [...] a lambda-expression. + D = diag::err_lambda_in_constant_expression; + } for (unsigned I = 0, N = Rec.Lambdas.size(); I != N; ++I) - Diag(Rec.Lambdas[I]->getLocStart(), - diag::err_lambda_unevaluated_operand); + Diag(Rec.Lambdas[I]->getLocStart(), D); } else { // Mark the capture expressions odr-used. This was deferred // during lambda expression creation. @@ -10874,7 +11258,8 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { if (!AlreadyInstantiated || Func->isConstexpr()) { if (isa<CXXRecordDecl>(Func->getDeclContext()) && - cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass()) + cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass() && + ActiveTemplateInstantiations.size()) PendingLocalImplicitInstantiations.push_back( std::make_pair(Func, PointOfInstantiation)); else if (Func->isConstexpr()) @@ -10908,14 +11293,14 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc)); } - // Normally the must current decl is marked used while processing the use and + // Normally the most current decl is marked used while processing the use and // any subsequent decls are marked used by decl merging. This fails with // template instantiation since marking can happen at the end of the file // and, because of the two phase lookup, this function is called with at // decl in the middle of a decl chain. We loop to maintain the invariant // that once a decl is used, all decls after it are also used. for (FunctionDecl *F = Func->getMostRecentDecl();; F = F->getPreviousDecl()) { - F->setUsed(true); + F->markUsed(Context); if (F == Func) break; } @@ -10967,36 +11352,251 @@ diagnoseUncapturableValueReference(Sema &S, SourceLocation loc, // capture. } -/// \brief Capture the given variable in the captured region. -static ExprResult captureInCapturedRegion(Sema &S, CapturedRegionScopeInfo *RSI, - VarDecl *Var, QualType FieldType, - QualType DeclRefType, - SourceLocation Loc, - bool RefersToEnclosingLocal) { - // The current implemention assumes that all variables are captured - // by references. Since there is no capture by copy, no expression evaluation - // will be needed. - // - RecordDecl *RD = RSI->TheRecordDecl; + +static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDecl *Var, + bool &SubCapturesAreNested, + QualType &CaptureType, + QualType &DeclRefType) { + // Check whether we've already captured it. + if (CSI->CaptureMap.count(Var)) { + // If we found a capture, any subcaptures are nested. + SubCapturesAreNested = 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(); + return true; + } + return false; +} - FieldDecl *Field - = FieldDecl::Create(S.Context, RD, Loc, Loc, 0, FieldType, - S.Context.getTrivialTypeSourceInfo(FieldType, Loc), - 0, false, ICIS_NoInit); - Field->setImplicit(true); - Field->setAccess(AS_private); - RD->addDecl(Field); +// Only block literals, captured statements, and lambda expressions can +// capture; other scopes don't work. +static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC, VarDecl *Var, + SourceLocation Loc, + const bool Diagnose, Sema &S) { + if (isa<BlockDecl>(DC) || isa<CapturedDecl>(DC) || isLambdaCallOperator(DC)) + return getLambdaAwareParentOfDeclContext(DC); + else { + if (Diagnose) + diagnoseUncapturableValueReference(S, Loc, Var, DC); + } + return 0; +} - Expr *Ref = new (S.Context) DeclRefExpr(Var, RefersToEnclosingLocal, - DeclRefType, VK_LValue, Loc); - Var->setReferenced(true); - Var->setUsed(true); +// Certain capturing entities (lambdas, blocks etc.) are not allowed to capture +// certain types of variables (unnamed, variably modified types etc.) +// so check for eligibility. +static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var, + SourceLocation Loc, + const bool Diagnose, Sema &S) { + + bool IsBlock = isa<BlockScopeInfo>(CSI); + bool IsLambda = isa<LambdaScopeInfo>(CSI); + + // 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 (Diagnose) { + S.Diag(Loc, diag::err_lambda_capture_anonymous_var); + S.Diag(Var->getLocation(), diag::note_declared_at); + } + return false; + } + + // Prohibit variably-modified types; they're difficult to deal with. + if (Var->getType()->isVariablyModifiedType()) { + if (Diagnose) { + if (IsBlock) + S.Diag(Loc, diag::err_ref_vm_type); + else + S.Diag(Loc, diag::err_lambda_capture_vm_type) << Var->getDeclName(); + S.Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + } + return false; + } + // Prohibit structs with flexible array members too. + // We cannot capture what is in the tail end of the struct. + if (const RecordType *VTTy = Var->getType()->getAs<RecordType>()) { + if (VTTy->getDecl()->hasFlexibleArrayMember()) { + if (Diagnose) { + if (IsBlock) + S.Diag(Loc, diag::err_ref_flexarray_type); + else + S.Diag(Loc, diag::err_lambda_capture_flexarray_type) + << Var->getDeclName(); + S.Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + } + return false; + } + } + const bool HasBlocksAttr = Var->hasAttr<BlocksAttr>(); + // Lambdas and captured statements are not allowed to capture __block + // variables; they don't support the expected semantics. + if (HasBlocksAttr && (IsLambda || isa<CapturedRegionScopeInfo>(CSI))) { + if (Diagnose) { + S.Diag(Loc, diag::err_capture_block_variable) + << Var->getDeclName() << !IsLambda; + S.Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + } + return false; + } - return Ref; + return true; } -/// \brief Capture the given variable in the given lambda expression. -static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI, +// Returns true if the capture by block was successful. +static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, + SourceLocation Loc, + const bool BuildAndDiagnose, + QualType &CaptureType, + QualType &DeclRefType, + const bool Nested, + Sema &S) { + Expr *CopyExpr = 0; + bool ByRef = false; + + // Blocks are not allowed to capture arrays. + if (CaptureType->isArrayType()) { + if (BuildAndDiagnose) { + S.Diag(Loc, diag::err_ref_array_type); + S.Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + } + return false; + } + + // Forbid the block-capture of autoreleasing variables. + if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) { + if (BuildAndDiagnose) { + S.Diag(Loc, diag::err_arc_autoreleasing_capture) + << /*block*/ 0; + S.Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + } + return false; + } + const bool HasBlocksAttr = Var->hasAttr<BlocksAttr>(); + 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 (S.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)) + S.FinalizeVarWithDestructor(Var, Record); + + // Enter a new evaluation context to insulate the copy + // full-expression. + EnterExpressionEvaluationContext scope(S, S.PotentiallyEvaluated); + + // According to the blocks spec, the capture of a variable from + // the stack requires a const copy constructor. This is not true + // of the copy/move done to move a __block variable to the heap. + Expr *DeclRef = new (S.Context) DeclRefExpr(Var, Nested, + DeclRefType.withConst(), + VK_LValue, Loc); + + ExprResult Result + = S.PerformCopyInitialization( + InitializedEntity::InitializeBlock(Var->getLocation(), + CaptureType, 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(); + } + } + } + } + + // Actually capture the variable. + if (BuildAndDiagnose) + BSI->addCapture(Var, HasBlocksAttr, ByRef, Nested, Loc, + SourceLocation(), CaptureType, CopyExpr); + + return true; + +} + + +/// \brief Capture the given variable in the captured region. +static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI, + VarDecl *Var, + SourceLocation Loc, + const bool BuildAndDiagnose, + QualType &CaptureType, + QualType &DeclRefType, + const bool RefersToEnclosingLocal, + Sema &S) { + + // By default, capture variables by reference. + bool ByRef = true; + // Using an LValue reference type is consistent with Lambdas (see below). + CaptureType = S.Context.getLValueReferenceType(DeclRefType); + Expr *CopyExpr = 0; + if (BuildAndDiagnose) { + // The current implementation assumes that all variables are captured + // by references. Since there is no capture by copy, no expression evaluation + // will be needed. + // + RecordDecl *RD = RSI->TheRecordDecl; + + FieldDecl *Field + = FieldDecl::Create(S.Context, RD, Loc, Loc, 0, CaptureType, + S.Context.getTrivialTypeSourceInfo(CaptureType, Loc), + 0, false, ICIS_NoInit); + Field->setImplicit(true); + Field->setAccess(AS_private); + RD->addDecl(Field); + + CopyExpr = new (S.Context) DeclRefExpr(Var, RefersToEnclosingLocal, + DeclRefType, VK_LValue, Loc); + Var->setReferenced(true); + Var->markUsed(S.Context); + } + + // Actually capture the variable. + if (BuildAndDiagnose) + RSI->addCapture(Var, /*isBlock*/false, ByRef, RefersToEnclosingLocal, Loc, + SourceLocation(), CaptureType, CopyExpr); + + + return true; +} + +/// \brief Create a field within the lambda class for the variable +/// being captured. Handle Array captures. +static ExprResult addAsFieldToClosureType(Sema &S, + LambdaScopeInfo *LSI, VarDecl *Var, QualType FieldType, QualType DeclRefType, SourceLocation Loc, @@ -11032,7 +11632,7 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI, Expr *Ref = new (S.Context) DeclRefExpr(Var, RefersToEnclosingLocal, DeclRefType, VK_LValue, Loc); Var->setReferenced(true); - Var->setUsed(true); + Var->markUsed(S.Context); // When the field has array type, create index variables for each // dimension of the array. We use these index variables to subscript @@ -11088,7 +11688,8 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI, SmallVector<InitializedEntity, 4> Entities; Entities.reserve(1 + IndexVariables.size()); Entities.push_back( - InitializedEntity::InitializeLambdaCapture(Var, Field, Loc)); + InitializedEntity::InitializeLambdaCapture(Var->getIdentifier(), + Field->getType(), Loc)); for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I) Entities.push_back(InitializedEntity::InitializeElement(S.Context, 0, @@ -11113,127 +11714,207 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI, return Result; } -bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc, + + +/// \brief Capture the given variable in the lambda. +static bool captureInLambda(LambdaScopeInfo *LSI, + VarDecl *Var, + SourceLocation Loc, + const bool BuildAndDiagnose, + QualType &CaptureType, + QualType &DeclRefType, + const bool RefersToEnclosingLocal, + const Sema::TryCaptureKind Kind, + SourceLocation EllipsisLoc, + const bool IsTopScope, + Sema &S) { + + // Determine whether we are capturing by reference or by value. + bool ByRef = false; + if (IsTopScope && Kind != Sema::TryCapture_Implicit) { + ByRef = (Kind == Sema::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 = S.Context.getLValueReferenceType(DeclRefType); + } else { + // 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) { + S.Diag(Loc, diag::err_arc_autoreleasing_capture) << /*lambda*/ 1; + S.Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + } + return false; + } + + if (S.RequireNonAbstractType(Loc, CaptureType, + diag::err_capture_of_abstract_type)) + return false; + } + + // Capture this variable in the lambda. + Expr *CopyExpr = 0; + if (BuildAndDiagnose) { + ExprResult Result = addAsFieldToClosureType(S, LSI, Var, + CaptureType, DeclRefType, Loc, + RefersToEnclosingLocal); + 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) + LSI->addCapture(Var, /*IsBlock=*/false, ByRef, RefersToEnclosingLocal, + Loc, EllipsisLoc, CaptureType, CopyExpr); + + return true; +} + + +bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc, TryCaptureKind Kind, SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType, - QualType &DeclRefType) { + QualType &DeclRefType, + const unsigned *const FunctionScopeIndexToStopAt) { bool Nested = false; DeclContext *DC = CurContext; - if (Var->getDeclContext() == DC) return true; - if (!Var->hasLocalStorage()) return true; + const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt + ? *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1; + // We need to sync up the Declaration Context with the + // FunctionScopeIndexToStopAt + if (FunctionScopeIndexToStopAt) { + unsigned FSIndex = FunctionScopes.size() - 1; + while (FSIndex != MaxFunctionScopesIndex) { + DC = getLambdaAwareParentOfDeclContext(DC); + --FSIndex; + } + } - bool HasBlocksAttr = Var->hasAttr<BlocksAttr>(); + + // If the variable is declared in the current context (and is not an + // init-capture), there is no need to capture it. + if (!Var->isInitCapture() && Var->getDeclContext() == DC) return true; + if (!Var->hasLocalStorage()) return true; // 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. + // capture of that variable. We start from the innermost capturing-entity + // (the DC) and ensure that all intervening capturing-entities + // (blocks/lambdas etc.) between the innermost capturer and the variable`s + // declcontext can either capture the variable or have already captured + // the variable. CaptureType = Var->getType(); DeclRefType = CaptureType.getNonReferenceType(); bool Explicit = (Kind != TryCapture_Implicit); - unsigned FunctionScopesIndex = FunctionScopes.size() - 1; + unsigned FunctionScopesIndex = MaxFunctionScopesIndex; do { // Only block literals, captured statements, and lambda expressions can // capture; other scopes don't work. - DeclContext *ParentDC; - if (isa<BlockDecl>(DC) || isa<CapturedDecl>(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; - } + DeclContext *ParentDC = getParentOfCapturingContextOrNull(DC, Var, + ExprLoc, + BuildAndDiagnose, + *this); + if (!ParentDC) return true; + + FunctionScopeInfo *FSI = FunctionScopes[FunctionScopesIndex]; + CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FSI); - 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(); + if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType, + DeclRefType)) break; - } - - bool IsBlock = isa<BlockScopeInfo>(CSI); - bool IsLambda = isa<LambdaScopeInfo>(CSI); - - // 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 we are instantiating a generic lambda call operator body, + // we do not want to capture new variables. What was captured + // during either a lambdas transformation or initial parsing + // should be used. + if (isGenericLambdaCallOperatorSpecialization(DC)) { 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 - Diag(Loc, diag::err_lambda_capture_vm_type) << Var->getDeclName(); - Diag(Var->getLocation(), diag::note_previous_decl) - << Var->getDeclName(); - } - return true; - } - // Prohibit structs with flexible array members too. - // We cannot capture what is in the tail end of the struct. - if (const RecordType *VTTy = Var->getType()->getAs<RecordType>()) { - if (VTTy->getDecl()->hasFlexibleArrayMember()) { - if (BuildAndDiagnose) { - if (IsBlock) - Diag(Loc, diag::err_ref_flexarray_type); - else - Diag(Loc, diag::err_lambda_capture_flexarray_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(); + LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI); + if (LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None) { + Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName(); + Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + Diag(LSI->Lambda->getLocStart(), diag::note_lambda_decl); + } else + diagnoseUncapturableValueReference(*this, ExprLoc, Var, DC); } return true; } - + // Certain capturing entities (lambdas, blocks etc.) are not allowed to capture + // certain types of variables (unnamed, variably modified types etc.) + // so check for eligibility. + if (!isVariableCapturable(CSI, Var, ExprLoc, BuildAndDiagnose, *this)) + return true; + if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None && !Explicit) { - // No capture-default + // No capture-default, and this is not an explicit capture + // so cannot capture this variable. if (BuildAndDiagnose) { - Diag(Loc, diag::err_lambda_impcap) << Var->getDeclName(); + Diag(ExprLoc, 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); + // FIXME: If we error out because an outer lambda can not implicitly + // capture a variable that an inner lambda explicitly captures, we + // should have the inner lambda do the explicit capture - because + // it makes for cleaner diagnostics later. This would purely be done + // so that the diagnostic does not misleadingly claim that a variable + // can not be captured by a lambda implicitly even though it is captured + // explicitly. Suggestion: + // - create const bool VariableCaptureWasInitiallyExplicit = Explicit + // at the function head + // - cache the StartingDeclContext - this must be a lambda + // - captureInLambda in the innermost lambda the variable. } return true; } @@ -11243,203 +11924,37 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc, 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; + // Walk back down the scope stack, (e.g. from outer lambda to inner lambda) + // computing the type of the capture at each step, checking type-specific + // requirements, and adding captures if requested. + // If the variable had already been captured previously, we start capturing + // at the lambda nested within that one. + for (unsigned I = ++FunctionScopesIndex, N = MaxFunctionScopesIndex + 1; 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(); - } + if (BlockScopeInfo *BSI = dyn_cast<BlockScopeInfo>(CSI)) { + if (!captureInBlock(BSI, Var, ExprLoc, + BuildAndDiagnose, CaptureType, + DeclRefType, Nested, *this)) 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); - - // Enter a new evaluation context to insulate the copy - // full-expression. - EnterExpressionEvaluationContext scope(*this, PotentiallyEvaluated); - - // 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, Nested, - 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; - } - - if (CapturedRegionScopeInfo *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) { - // By default, capture variables by reference. - bool ByRef = true; - // Using an LValue reference type is consistent with Lambdas (see below). - CaptureType = Context.getLValueReferenceType(DeclRefType); - - Expr *CopyExpr = 0; - if (BuildAndDiagnose) { - ExprResult Result = captureInCapturedRegion(*this, RSI, Var, - CaptureType, DeclRefType, - Loc, Nested); - if (!Result.isInvalid()) - CopyExpr = Result.take(); - } - - // Actually capture the variable. - if (BuildAndDiagnose) - CSI->addCapture(Var, /*isBlock*/false, ByRef, Nested, Loc, - SourceLocation(), CaptureType, CopyExpr); + } else if (CapturedRegionScopeInfo *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) { + if (!captureInCapturedRegion(RSI, Var, ExprLoc, + BuildAndDiagnose, CaptureType, + DeclRefType, Nested, *this)) + return true; 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 { - // 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(); - } + LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI); + if (!captureInLambda(LSI, Var, ExprLoc, + BuildAndDiagnose, CaptureType, + DeclRefType, Nested, Kind, EllipsisLoc, + /*IsTopScope*/I == N - 1, *this)) return true; - } - } - - // Capture this variable in the lambda. - Expr *CopyExpr = 0; - if (BuildAndDiagnose) { - ExprResult Result = captureInLambda(*this, LSI, Var, CaptureType, - DeclRefType, Loc, - Nested); - 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(); + Nested = true; } - - // Add the capture. - if (BuildAndDiagnose) - CSI->addCapture(Var, /*IsBlock=*/false, ByRef, Nested, Loc, - EllipsisLoc, CaptureType, CopyExpr); - Nested = true; } - return false; } @@ -11449,7 +11964,7 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc, QualType DeclRefType; return tryCaptureVariable(Var, Loc, Kind, EllipsisLoc, /*BuildAndDiagnose=*/true, CaptureType, - DeclRefType); + DeclRefType, 0); } QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) { @@ -11458,28 +11973,36 @@ QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) { // Determine whether we can capture this variable. if (tryCaptureVariable(Var, Loc, TryCapture_Implicit, SourceLocation(), - /*BuildAndDiagnose=*/false, CaptureType, DeclRefType)) + /*BuildAndDiagnose=*/false, CaptureType, + DeclRefType, 0)) 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.UndefinedButUsed[Var->getCanonicalDecl()]; - if (old.isInvalid()) old = Loc; - } - SemaRef.tryCaptureVariable(Var, Loc); - Var->setUsed(true); +// If either the type of the variable or the initializer is dependent, +// return false. Otherwise, determine whether the variable is a constant +// expression. Use this if you need to know if a variable that might or +// might not be dependent is truly a constant expression. +static inline bool IsVariableNonDependentAndAConstantExpression(VarDecl *Var, + ASTContext &Context) { + + if (Var->getType()->isDependentType()) + return false; + const VarDecl *DefVD = 0; + Var->getAnyInitializer(DefVD); + if (!DefVD) + return false; + EvaluatedStmt *Eval = DefVD->ensureEvaluatedStmt(); + Expr *Init = cast<Expr>(Eval->Value); + if (Init->isValueDependent()) + return false; + return IsVariableAConstantExpression(Var, Context); } + 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 @@ -11487,6 +12010,22 @@ void Sema::UpdateMarkingForLValueToRValue(Expr *E) { // is immediately applied." This function handles the lvalue-to-rvalue // conversion part. MaybeODRUseExprs.erase(E->IgnoreParens()); + + // If we are in a lambda, check if this DeclRefExpr or MemberExpr refers + // to a variable that is a constant expression, and if so, identify it as + // a reference to a variable that does not involve an odr-use of that + // variable. + if (LambdaScopeInfo *LSI = getCurLambda()) { + Expr *SansParensExpr = E->IgnoreParens(); + VarDecl *Var = 0; + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SansParensExpr)) + Var = dyn_cast<VarDecl>(DRE->getFoundDecl()); + else if (MemberExpr *ME = dyn_cast<MemberExpr>(SansParensExpr)) + Var = dyn_cast<VarDecl>(ME->getMemberDecl()); + + if (Var && IsVariableNonDependentAndAConstantExpression(Var, Context)) + LSI->markVariableExprAsNonODRUsed(SansParensExpr); + } } ExprResult Sema::ActOnConstantExpression(ExprResult Res) { @@ -11517,46 +12056,105 @@ void Sema::CleanupVarDeclMarking() { llvm_unreachable("Unexpcted expression"); } - MarkVarDeclODRUsed(*this, Var, Loc); + MarkVarDeclODRUsed(Var, Loc, *this, /*MaxFunctionScopeIndex Pointer*/ 0); } 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) { + assert((!E || isa<DeclRefExpr>(E) || isa<MemberExpr>(E)) && + "Invalid Expr argument to DoMarkVarDeclReferenced"); 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) { + // If the context is not PotentiallyEvaluated and not Unevaluated + // (i.e PotentiallyEvaluatedIfUsed) do not bother to consider variables + // in this context for odr-use unless we are within a lambda. + // If we don't know whether the context is potentially evaluated or not + // (for e.g., if we're in a generic lambda), we want to add a potential + // capture and eventually analyze for odr-use. + // We should also be able to analyze certain constructs in a non-generic + // lambda setting for potential odr-use and capture violation: + // template<class T> void foo(T t) { + // auto L = [](int i) { return t; }; + // } + // + if (!IsPotentiallyEvaluatedContext(SemaRef)) { + + if (SemaRef.isUnevaluatedContext()) return; + + const bool refersToEnclosingScope = + (SemaRef.CurContext != Var->getDeclContext() && + Var->getDeclContext()->isFunctionOrMethod()); + if (!refersToEnclosingScope) return; + + if (LambdaScopeInfo *const LSI = SemaRef.getCurLambda()) { + // If a variable could potentially be odr-used, defer marking it so + // until we finish analyzing the full expression for any lvalue-to-rvalue + // or discarded value conversions that would obviate odr-use. + // Add it to the list of potential captures that will be analyzed + // later (ActOnFinishFullExpr) for eventual capture and odr-use marking + // unless the variable is a reference that was initialized by a constant + // expression (this will never need to be captured or odr-used). + const bool IsConstantExpr = IsVariableNonDependentAndAConstantExpression( + Var, SemaRef.Context); + assert(E && "Capture variable should be used in an expression."); + if (!IsConstantExpr || !Var->getType()->isReferenceType()) + LSI->addPotentialCapture(E->IgnoreParens()); + } + return; + } + + VarTemplateSpecializationDecl *VarSpec = + dyn_cast<VarTemplateSpecializationDecl>(Var); + assert(!isa<VarTemplatePartialSpecializationDecl>(Var) && + "Can't instantiate a partial template specialization."); + + // Implicit instantiation of static data members, static data member + // templates of class templates, and variable template specializations. + // Delay instantiations of variable templates, except for those + // that could be used in a constant expression. + TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind(); + if (isTemplateInstantiation(TSK)) { + bool TryInstantiating = TSK == TSK_ImplicitInstantiation; + + if (TryInstantiating && !isa<VarTemplateSpecializationDecl>(Var)) { + if (Var->getPointOfInstantiation().isInvalid()) { // This is a modification of an existing AST node. Notify listeners. if (ASTMutationListener *L = SemaRef.getASTMutationListener()) L->StaticDataMemberInstantiated(Var); - MSInfo->setPointOfInstantiation(Loc); + } else if (!Var->isUsableInConstantExpressions(SemaRef.Context)) + // Don't bother trying to instantiate it again, unless we might need + // its initializer before we get to the end of the TU. + TryInstantiating = false; + } + + if (Var->getPointOfInstantiation().isInvalid()) + Var->setTemplateSpecializationKind(TSK, Loc); + + if (TryInstantiating) { + SourceLocation PointOfInstantiation = Var->getPointOfInstantiation(); + bool InstantiationDependent = false; + bool IsNonDependent = + VarSpec ? !TemplateSpecializationType::anyDependentTemplateArguments( + VarSpec->getTemplateArgsInfo(), InstantiationDependent) + : true; + + // Do not instantiate specializations that are still type-dependent. + if (IsNonDependent) { + if (Var->isUsableInConstantExpressions(SemaRef.Context)) { + // Do not defer instantiations of variables which could be used in a + // constant expression. + SemaRef.InstantiateVariableDefinition(PointOfInstantiation, Var); + } else { + SemaRef.PendingInstantiations + .push_back(std::make_pair(Var, PointOfInstantiation)); + } } - 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 satisfies // the requirements for appearing in a constant expression (5.19) and, if // it is an object, the lvalue-to-rvalue conversion (4.1) @@ -11565,14 +12163,16 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, // Note that we use the C++11 definition everywhere because nothing in // C++03 depends on whether we get the C++03 version correct. The second // part does not apply to references, since they are not objects. - const VarDecl *DefVD; - if (E && !isa<ParmVarDecl>(Var) && - Var->isUsableInConstantExpressions(SemaRef.Context) && - Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE()) { + if (E && IsVariableAConstantExpression(Var, SemaRef.Context)) { + // A reference initialized by a constant expression can never be + // odr-used, so simply ignore it. + // But a non-reference might get odr-used if it doesn't undergo + // an lvalue-to-rvalue or is discarded, so track it. if (!Var->getType()->isReferenceType()) SemaRef.MaybeODRUseExprs.insert(E); - } else - MarkVarDeclODRUsed(SemaRef, Var, Loc); + } + else + MarkVarDeclODRUsed(Var, Loc, SemaRef, /*MaxFunctionScopeIndex ptr*/0); } /// \brief Mark a variable referenced, and check whether it is odr-used @@ -11889,7 +12489,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { Selector Sel = ME->getSelector(); // self = [<foo> init...] - if (isSelfExpr(Op->getLHS()) && Sel.getNameForSlot(0).startswith("init")) + if (isSelfExpr(Op->getLHS()) && ME->getMethodFamily() == OMF_init) diagnostic = diag::warn_condition_is_idiomatic_assignment; // <foo> = [<bar> nextObject] @@ -12204,15 +12804,49 @@ ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) { assert(E->getObjectKind() == OK_Ordinary); // Rebuild the function type, replacing the result type with DestType. - if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FnType)) - DestType = - S.Context.getFunctionType(DestType, - ArrayRef<QualType>(Proto->arg_type_begin(), - Proto->getNumArgs()), - Proto->getExtProtoInfo()); - else + const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FnType); + if (Proto) { + // __unknown_anytype(...) is a special case used by the debugger when + // it has no idea what a function's signature is. + // + // We want to build this call essentially under the K&R + // unprototyped rules, but making a FunctionNoProtoType in C++ + // would foul up all sorts of assumptions. However, we cannot + // simply pass all arguments as variadic arguments, nor can we + // portably just call the function under a non-variadic type; see + // the comment on IR-gen's TargetInfo::isNoProtoCallVariadic. + // However, it turns out that in practice it is generally safe to + // call a function declared as "A foo(B,C,D);" under the prototype + // "A foo(B,C,D,...);". The only known exception is with the + // Windows ABI, where any variadic function is implicitly cdecl + // regardless of its normal CC. Therefore we change the parameter + // types to match the types of the arguments. + // + // This is a hack, but it is far superior to moving the + // corresponding target-specific code from IR-gen to Sema/AST. + + ArrayRef<QualType> ParamTypes = Proto->getArgTypes(); + SmallVector<QualType, 8> ArgTypes; + if (ParamTypes.empty() && Proto->isVariadic()) { // the special case + ArgTypes.reserve(E->getNumArgs()); + for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) { + Expr *Arg = E->getArg(i); + QualType ArgType = Arg->getType(); + if (E->isLValue()) { + ArgType = S.Context.getLValueReferenceType(ArgType); + } else if (E->isXValue()) { + ArgType = S.Context.getRValueReferenceType(ArgType); + } + ArgTypes.push_back(ArgType); + } + ParamTypes = ArgTypes; + } + DestType = S.Context.getFunctionType(DestType, ParamTypes, + Proto->getExtProtoInfo()); + } else { DestType = S.Context.getFunctionNoProtoType(DestType, FnType->getExtInfo()); + } // Rebuild the appropriate pointer-to-function type. switch (Kind) { @@ -12345,6 +12979,8 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) { return ExprError(); } + // Modifying the declaration like this is friendly to IR-gen but + // also really dangerous. VD->setType(DestType); E->setType(Type); E->setValueKind(ValueKind); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp index 27032a911147..07e465766b74 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp @@ -21,6 +21,7 @@ #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" @@ -31,6 +32,7 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaLambda.h" #include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/STLExtras.h" @@ -305,7 +307,7 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, SemaDiagnosticBuilder DtorDiag = Diag(NameLoc, diag::err_destructor_class_name); if (S) { - const DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()); + const DeclContext *Ctx = S->getEntity(); if (const CXXRecordDecl *Class = dyn_cast_or_null<CXXRecordDecl>(Ctx)) DtorDiag << FixItHint::CreateReplacement(SourceRange(NameLoc), Class->getNameAsString()); @@ -462,11 +464,16 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, TypeSourceInfo *Operand, SourceLocation RParenLoc) { if (!Operand->getType()->isDependentType()) { - if (!CXXUuidofExpr::GetUuidAttrOfType(Operand->getType())) - return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + bool HasMultipleGUIDs = false; + if (!CXXUuidofExpr::GetUuidAttrOfType(Operand->getType(), + &HasMultipleGUIDs)) { + if (HasMultipleGUIDs) + return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids)); + else + return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + } } - // FIXME: add __uuidof semantic analysis for type operand. return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand, SourceRange(TypeidLoc, RParenLoc))); @@ -478,11 +485,16 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, Expr *E, SourceLocation RParenLoc) { if (!E->getType()->isDependentType()) { - if (!CXXUuidofExpr::GetUuidAttrOfType(E->getType()) && - !E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) - return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + bool HasMultipleGUIDs = false; + if (!CXXUuidofExpr::GetUuidAttrOfType(E->getType(), &HasMultipleGUIDs) && + !E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { + if (HasMultipleGUIDs) + return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids)); + else + return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + } } - // FIXME: add __uuidof semantic analysis for type operand. + return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(), E, SourceRange(TypeidLoc, RParenLoc))); @@ -741,21 +753,30 @@ static Expr *captureThis(ASTContext &Context, RecordDecl *RD, return new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit*/true); } -void Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit) { +bool Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit, + bool BuildAndDiagnose, const unsigned *const FunctionScopeIndexToStopAt) { // We don't need to capture this in an unevaluated context. if (isUnevaluatedContext() && !Explicit) - return; + return true; - // Otherwise, check that we can capture 'this'. + const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt ? + *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1; + // Otherwise, check that we can capture 'this'. unsigned NumClosures = 0; - for (unsigned idx = FunctionScopes.size() - 1; idx != 0; idx--) { + for (unsigned idx = MaxFunctionScopesIndex; 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; } - + LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI); + if (LSI && isGenericLambdaCallOperatorSpecialization(LSI->CallOperator)) { + // This context can't implicitly capture 'this'; fail out. + if (BuildAndDiagnose) + Diag(Loc, diag::err_this_capture) << Explicit; + return true; + } if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByref || CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByval || CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_Block || @@ -767,17 +788,18 @@ void Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit) { continue; } // This context can't implicitly capture 'this'; fail out. - Diag(Loc, diag::err_this_capture) << Explicit; - return; + if (BuildAndDiagnose) + Diag(Loc, diag::err_this_capture) << Explicit; + return true; } break; } - + if (!BuildAndDiagnose) return false; // 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) { + for (unsigned idx = MaxFunctionScopesIndex; NumClosures; + --idx, --NumClosures) { CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]); Expr *ThisExpr = 0; QualType ThisTy = getCurrentThisType(); @@ -791,6 +813,7 @@ void Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit) { bool isNested = NumClosures > 1; CSI->addThisCapture(isNested, Loc, ThisTy, ThisExpr); } + return false; } ExprResult Sema::ActOnCXXThis(SourceLocation Loc) { @@ -893,17 +916,21 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, InitializationSequence InitSeq(*this, Entity, Kind, Exprs); ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Exprs); - if (!Result.isInvalid() && ListInitialization && - isa<InitListExpr>(Result.get())) { + if (Result.isInvalid() || !ListInitialization) + return Result; + + Expr *Inner = Result.get(); + if (CXXBindTemporaryExpr *BTE = dyn_cast_or_null<CXXBindTemporaryExpr>(Inner)) + Inner = BTE->getSubExpr(); + if (isa<InitListExpr>(Inner)) { // 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)); + QualType ResultType = Result.get()->getType(); + Result = Owned(CXXFunctionalCastExpr::Create( + Context, ResultType, Expr::getValueKindForType(TInfo->getType()), TInfo, + CK_NoOp, Result.take(), /*Path=*/ 0, LParenLoc, RParenLoc)); } // FIXME: Improve AST representation? @@ -1017,10 +1044,23 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr; if (Expr *NumElts = (Expr *)Array.NumElts) { if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) { - Array.NumElts - = VerifyIntegerConstantExpression(NumElts, 0, - diag::err_new_array_nonconst) - .take(); + if (getLangOpts().CPlusPlus1y) { + // C++1y [expr.new]p6: Every constant-expression in a noptr-new-declarator + // shall be a converted constant expression (5.19) of type std::size_t + // and shall evaluate to a strictly positive value. + unsigned IntWidth = Context.getTargetInfo().getIntWidth(); + assert(IntWidth && "Builtin type of size 0?"); + llvm::APSInt Value(IntWidth); + Array.NumElts + = CheckConvertedConstantExpression(NumElts, Context.getSizeType(), Value, + CCEK_NewExpr) + .take(); + } else { + Array.NumElts + = VerifyIntegerConstantExpression(NumElts, 0, + diag::err_new_array_nonconst) + .take(); + } if (!Array.NumElts) return ExprError(); } @@ -1180,70 +1220,85 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // 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. + // C++1y [expr.new]p6: The expression [...] is implicitly converted to + // std::size_t. if (ArraySize && !ArraySize->isTypeDependent()) { - class SizeConvertDiagnoser : public ICEConvertDiagnoser { - Expr *ArraySize; - - public: - SizeConvertDiagnoser(Expr *ArraySize) - : ICEConvertDiagnoser(false, false), ArraySize(ArraySize) { } - - virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, - QualType T) { - return S.Diag(Loc, diag::err_array_size_not_integral) - << S.getLangOpts().CPlusPlus11 << T; - } - - virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc, - QualType T) { - return S.Diag(Loc, diag::err_array_size_incomplete_type) - << T << ArraySize->getSourceRange(); - } - - virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S, - SourceLocation Loc, - QualType T, - QualType ConvTy) { - return S.Diag(Loc, diag::err_array_size_explicit_conversion) << T << ConvTy; - } - - virtual DiagnosticBuilder noteExplicitConv(Sema &S, - CXXConversionDecl *Conv, - QualType ConvTy) { - return S.Diag(Conv->getLocation(), diag::note_array_size_conversion) - << ConvTy->isEnumeralType() << ConvTy; - } - - virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, - QualType T) { - return S.Diag(Loc, diag::err_array_size_ambiguous_conversion) << T; - } - - virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv, - QualType ConvTy) { - return S.Diag(Conv->getLocation(), diag::note_array_size_conversion) - << ConvTy->isEnumeralType() << ConvTy; - } - - virtual DiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc, - QualType T, - QualType ConvTy) { - return S.Diag(Loc, - S.getLangOpts().CPlusPlus11 - ? diag::warn_cxx98_compat_array_size_conversion - : diag::ext_array_size_conversion) - << T << ConvTy->isEnumeralType() << ConvTy; - } - } SizeDiagnoser(ArraySize); + ExprResult ConvertedSize; + if (getLangOpts().CPlusPlus1y) { + unsigned IntWidth = Context.getTargetInfo().getIntWidth(); + assert(IntWidth && "Builtin type of size 0?"); + llvm::APSInt Value(IntWidth); + ConvertedSize = PerformImplicitConversion(ArraySize, Context.getSizeType(), + AA_Converting); + + if (!ConvertedSize.isInvalid() && + ArraySize->getType()->getAs<RecordType>()) + // Diagnose the compatibility of this conversion. + Diag(StartLoc, diag::warn_cxx98_compat_array_size_conversion) + << ArraySize->getType() << 0 << "'size_t'"; + } else { + class SizeConvertDiagnoser : public ICEConvertDiagnoser { + protected: + Expr *ArraySize; + + public: + SizeConvertDiagnoser(Expr *ArraySize) + : ICEConvertDiagnoser(/*AllowScopedEnumerations*/false, false, false), + ArraySize(ArraySize) {} + + virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_array_size_not_integral) + << S.getLangOpts().CPlusPlus11 << T; + } + + virtual SemaDiagnosticBuilder diagnoseIncomplete( + Sema &S, SourceLocation Loc, QualType T) { + return S.Diag(Loc, diag::err_array_size_incomplete_type) + << T << ArraySize->getSourceRange(); + } + + virtual SemaDiagnosticBuilder diagnoseExplicitConv( + Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) { + return S.Diag(Loc, diag::err_array_size_explicit_conversion) << T << ConvTy; + } + + virtual SemaDiagnosticBuilder noteExplicitConv( + Sema &S, CXXConversionDecl *Conv, QualType ConvTy) { + return S.Diag(Conv->getLocation(), diag::note_array_size_conversion) + << ConvTy->isEnumeralType() << ConvTy; + } + + virtual SemaDiagnosticBuilder diagnoseAmbiguous( + Sema &S, SourceLocation Loc, QualType T) { + return S.Diag(Loc, diag::err_array_size_ambiguous_conversion) << T; + } + + virtual SemaDiagnosticBuilder noteAmbiguous( + Sema &S, CXXConversionDecl *Conv, QualType ConvTy) { + return S.Diag(Conv->getLocation(), diag::note_array_size_conversion) + << ConvTy->isEnumeralType() << ConvTy; + } + + virtual SemaDiagnosticBuilder diagnoseConversion( + Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) { + return S.Diag(Loc, + S.getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_array_size_conversion + : diag::ext_array_size_conversion) + << T << ConvTy->isEnumeralType() << ConvTy; + } + } SizeDiagnoser(ArraySize); - ExprResult ConvertedSize - = ConvertToIntegralOrEnumerationType(StartLoc, ArraySize, SizeDiagnoser, - /*AllowScopedEnumerations*/ false); + ConvertedSize = PerformContextualImplicitConversion(StartLoc, ArraySize, + SizeDiagnoser); + } if (ConvertedSize.isInvalid()) return ExprError(); ArraySize = ConvertedSize.take(); QualType SizeType = ArraySize->getType(); + if (!SizeType->isIntegralOrUnscopedEnumerationType()) return ExprError(); @@ -1306,16 +1361,13 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, FunctionDecl *OperatorNew = 0; FunctionDecl *OperatorDelete = 0; - Expr **PlaceArgs = PlacementArgs.data(); - unsigned NumPlaceArgs = PlacementArgs.size(); if (!AllocType->isDependentType() && - !Expr::hasAnyTypeDependentArguments( - llvm::makeArrayRef(PlaceArgs, NumPlaceArgs)) && + !Expr::hasAnyTypeDependentArguments(PlacementArgs) && FindAllocationFunctions(StartLoc, SourceRange(PlacementLParen, PlacementRParen), - UseGlobal, AllocType, ArraySize, PlaceArgs, - NumPlaceArgs, OperatorNew, OperatorDelete)) + UseGlobal, AllocType, ArraySize, PlacementArgs, + OperatorNew, OperatorDelete)) return ExprError(); // If this is an array allocation, compute whether the usual array @@ -1333,24 +1385,21 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, VariadicCallType CallType = Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply; - if (GatherArgumentsForCall(PlacementLParen, OperatorNew, - Proto, 1, PlaceArgs, NumPlaceArgs, - AllPlaceArgs, CallType)) + if (GatherArgumentsForCall(PlacementLParen, OperatorNew, Proto, 1, + PlacementArgs, AllPlaceArgs, CallType)) return ExprError(); - NumPlaceArgs = AllPlaceArgs.size(); - if (NumPlaceArgs > 0) - PlaceArgs = &AllPlaceArgs[0]; + if (!AllPlaceArgs.empty()) + PlacementArgs = AllPlaceArgs; - DiagnoseSentinelCalls(OperatorNew, PlacementLParen, - PlaceArgs, NumPlaceArgs); + DiagnoseSentinelCalls(OperatorNew, PlacementLParen, PlacementArgs); // FIXME: Missing call to CheckFunctionCall or equivalent } // Warn if the type is over-aligned and is being allocated by global operator // new. - if (NumPlaceArgs == 0 && OperatorNew && + if (PlacementArgs.empty() && OperatorNew && (OperatorNew->isImplicit() || getSourceManager().isInSystemHeader(OperatorNew->getLocStart()))) { if (unsigned Align = Context.getPreferredTypeAlign(AllocType.getTypePtr())){ @@ -1458,8 +1507,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew, OperatorDelete, UsualArrayDeleteWantsSize, - llvm::makeArrayRef(PlaceArgs, NumPlaceArgs), - TypeIdParens, + PlacementArgs, TypeIdParens, ArraySize, initStyle, Initializer, ResultType, AllocTypeInfo, Range, DirectInitRange)); @@ -1504,24 +1552,30 @@ bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc, /// \brief Determine whether the given function is a non-placement /// deallocation function. -static bool isNonPlacementDeallocationFunction(FunctionDecl *FD) { +static bool isNonPlacementDeallocationFunction(Sema &S, FunctionDecl *FD) { if (FD->isInvalidDecl()) return false; if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD)) return Method->isUsualDeallocationFunction(); - return ((FD->getOverloadedOperator() == OO_Delete || - FD->getOverloadedOperator() == OO_Array_Delete) && - FD->getNumParams() == 1); + if (FD->getOverloadedOperator() != OO_Delete && + FD->getOverloadedOperator() != OO_Array_Delete) + return false; + + if (FD->getNumParams() == 1) + return true; + + return S.getLangOpts().SizedDeallocation && FD->getNumParams() == 2 && + S.Context.hasSameUnqualifiedType(FD->getParamDecl(1)->getType(), + S.Context.getSizeType()); } /// FindAllocationFunctions - Finds the overloads of operator new and delete /// that are appropriate for the allocation. bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, bool UseGlobal, QualType AllocType, - bool IsArray, Expr **PlaceArgs, - unsigned NumPlaceArgs, + bool IsArray, MultiExprArg PlaceArgs, FunctionDecl *&OperatorNew, FunctionDecl *&OperatorDelete) { // --- Choosing an allocation function --- @@ -1533,7 +1587,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // 3) The first argument is always size_t. Append the arguments from the // placement form. - SmallVector<Expr*, 8> AllocArgs(1 + NumPlaceArgs); + SmallVector<Expr*, 8> AllocArgs(1 + PlaceArgs.size()); // We don't care about the actual value of this argument. // FIXME: Should the Sema create the expression and embed it in the syntax // tree? Or should the consumer just recalculate the value? @@ -1542,7 +1596,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, Context.getSizeType(), SourceLocation()); AllocArgs[0] = &Size; - std::copy(PlaceArgs, PlaceArgs + NumPlaceArgs, AllocArgs.begin() + 1); + std::copy(PlaceArgs.begin(), PlaceArgs.end(), AllocArgs.begin() + 1); // C++ [expr.new]p8: // If the allocated type is a non-array type, the allocation @@ -1560,19 +1614,32 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, if (AllocElemType->isRecordType() && !UseGlobal) { CXXRecordDecl *Record = cast<CXXRecordDecl>(AllocElemType->getAs<RecordType>()->getDecl()); - if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0], - AllocArgs.size(), Record, /*AllowMissing=*/true, - OperatorNew)) + if (FindAllocationOverload(StartLoc, Range, NewName, AllocArgs, Record, + /*AllowMissing=*/true, OperatorNew)) return true; } + if (!OperatorNew) { // Didn't find a member overload. Look for a global one. DeclareGlobalNewDelete(); DeclContext *TUDecl = Context.getTranslationUnitDecl(); - if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0], - AllocArgs.size(), TUDecl, /*AllowMissing=*/false, - OperatorNew)) + bool FallbackEnabled = IsArray && Context.getLangOpts().MicrosoftMode; + if (FindAllocationOverload(StartLoc, Range, NewName, AllocArgs, TUDecl, + /*AllowMissing=*/FallbackEnabled, OperatorNew, + /*Diagnose=*/!FallbackEnabled)) { + if (!FallbackEnabled) + return true; + + // MSVC will fall back on trying to find a matching global operator new + // if operator new[] cannot be found. Also, MSVC will leak by not + // generating a call to operator delete or operator delete[], but we + // will not replicate that bug. + NewName = Context.DeclarationNames.getCXXOperatorName(OO_New); + DeleteName = Context.DeclarationNames.getCXXOperatorName(OO_Delete); + if (FindAllocationOverload(StartLoc, Range, NewName, AllocArgs, TUDecl, + /*AllowMissing=*/false, OperatorNew)) return true; + } } // We don't need an operator delete if we're running under @@ -1584,8 +1651,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // FindAllocationOverload can change the passed in arguments, so we need to // copy them back. - if (NumPlaceArgs > 0) - std::copy(&AllocArgs[1], AllocArgs.end(), PlaceArgs); + if (!PlaceArgs.empty()) + std::copy(AllocArgs.begin() + 1, AllocArgs.end(), PlaceArgs.data()); // C++ [expr.new]p19: // @@ -1619,7 +1686,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // we had explicit placement arguments. This matters for things like // struct A { void *operator new(size_t, int = 0); ... }; // A *a = new A() - bool isPlacementNew = (NumPlaceArgs > 0 || OperatorNew->param_size() != 1); + bool isPlacementNew = (!PlaceArgs.empty() || OperatorNew->param_size() != 1); if (isPlacementNew) { // C++ [expr.new]p20: @@ -1676,9 +1743,28 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, DEnd = FoundDelete.end(); D != DEnd; ++D) { if (FunctionDecl *Fn = dyn_cast<FunctionDecl>((*D)->getUnderlyingDecl())) - if (isNonPlacementDeallocationFunction(Fn)) + if (isNonPlacementDeallocationFunction(*this, Fn)) Matches.push_back(std::make_pair(D.getPair(), Fn)); } + + // C++1y [expr.new]p22: + // For a non-placement allocation function, the normal deallocation + // function lookup is used + // C++1y [expr.delete]p?: + // If [...] deallocation function lookup finds both a usual deallocation + // function with only a pointer parameter and a usual deallocation + // function with both a pointer parameter and a size parameter, then the + // selected deallocation function shall be the one with two parameters. + // Otherwise, the selected deallocation function shall be the function + // with one parameter. + if (getLangOpts().SizedDeallocation && Matches.size() == 2) { + if (Matches[0].second->getNumParams() == 1) + Matches.erase(Matches.begin()); + else + Matches.erase(Matches.begin() + 1); + assert(Matches[0].second->getNumParams() == 2 && + "found an unexpected uusal deallocation function"); + } } // C++ [expr.new]p20: @@ -1694,13 +1780,14 @@ 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 && getLangOpts().CPlusPlus11 && - isNonPlacementDeallocationFunction(OperatorDelete)) { + if (!PlaceArgs.empty() && getLangOpts().CPlusPlus11 && + isNonPlacementDeallocationFunction(*this, OperatorDelete)) { Diag(StartLoc, diag::err_placement_new_non_placement_delete) - << SourceRange(PlaceArgs[0]->getLocStart(), - PlaceArgs[NumPlaceArgs - 1]->getLocEnd()); - Diag(OperatorDelete->getLocation(), diag::note_previous_decl) - << DeleteName; + << SourceRange(PlaceArgs.front()->getLocStart(), + PlaceArgs.back()->getLocEnd()); + if (!OperatorDelete->isImplicit()) + Diag(OperatorDelete->getLocation(), diag::note_previous_decl) + << DeleteName; } else { CheckAllocationAccess(StartLoc, Range, FoundDelete.getNamingClass(), Matches[0].first); @@ -1713,8 +1800,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, /// FindAllocationOverload - Find an fitting overload for the allocation /// function in the specified scope. bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, - DeclarationName Name, Expr** Args, - unsigned NumArgs, DeclContext *Ctx, + DeclarationName Name, MultiExprArg Args, + DeclContext *Ctx, bool AllowMissing, FunctionDecl *&Operator, bool Diagnose) { LookupResult R(*this, Name, StartLoc, LookupOrdinaryName); @@ -1741,15 +1828,13 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) { AddTemplateOverloadCandidate(FnTemplate, Alloc.getPair(), /*ExplicitTemplateArgs=*/0, - llvm::makeArrayRef(Args, NumArgs), - Candidates, + Args, Candidates, /*SuppressUserConversions=*/false); continue; } FunctionDecl *Fn = cast<FunctionDecl>(D); - AddOverloadCandidate(Fn, Alloc.getPair(), - llvm::makeArrayRef(Args, NumArgs), Candidates, + AddOverloadCandidate(Fn, Alloc.getPair(), Args, Candidates, /*SuppressUserConversions=*/false); } @@ -1765,7 +1850,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, // asserted on, though, since invalid decls are left in there.) // Watch out for variadic allocator function. unsigned NumArgsInFnDecl = FnDecl->getNumParams(); - for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) { + for (unsigned i = 0; (i < Args.size() && i < NumArgsInFnDecl); ++i) { InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, FnDecl->getParamDecl(i)); @@ -1793,8 +1878,7 @@ 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, - llvm::makeArrayRef(Args, NumArgs)); + Candidates.NoteCandidates(*this, OCD_AllCandidates, Args); } return true; @@ -1802,8 +1886,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, if (Diagnose) { Diag(StartLoc, diag::err_ovl_ambiguous_call) << Name << Range; - Candidates.NoteCandidates(*this, OCD_ViableCandidates, - llvm::makeArrayRef(Args, NumArgs)); + Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args); } return true; @@ -1814,8 +1897,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, << Name << getDeletedOrUnavailableSuffix(Best->Function) << Range; - Candidates.NoteCandidates(*this, OCD_AllCandidates, - llvm::makeArrayRef(Args, NumArgs)); + Candidates.NoteCandidates(*this, OCD_AllCandidates, Args); } return true; } @@ -1832,13 +1914,19 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, /// void* operator new[](std::size_t) throw(std::bad_alloc); /// void operator delete(void *) throw(); /// void operator delete[](void *) throw(); -/// // C++0x: +/// // C++11: +/// void* operator new(std::size_t); +/// void* operator new[](std::size_t); +/// void operator delete(void *) noexcept; +/// void operator delete[](void *) noexcept; +/// // C++1y: /// void* operator new(std::size_t); /// void* operator new[](std::size_t); -/// void operator delete(void *); -/// void operator delete[](void *); +/// void operator delete(void *) noexcept; +/// void operator delete[](void *) noexcept; +/// void operator delete(void *, std::size_t) noexcept; +/// void operator delete[](void *, std::size_t) noexcept; /// @endcode -/// C++0x operator delete is implicitly noexcept. /// Note that the placement and nothrow forms of new are *not* implicitly /// declared. Their use requires including \<new\>. void Sema::DeclareGlobalNewDelete() { @@ -1855,11 +1943,18 @@ void Sema::DeclareGlobalNewDelete() { // void* operator new[](std::size_t) throw(std::bad_alloc); // void operator delete(void*) throw(); // void operator delete[](void*) throw(); - // C++0x: + // C++11: + // void* operator new(std::size_t); + // void* operator new[](std::size_t); + // void operator delete(void*) noexcept; + // void operator delete[](void*) noexcept; + // C++1y: // void* operator new(std::size_t); // void* operator new[](std::size_t); - // void operator delete(void*); - // void operator delete[](void*); + // void operator delete(void*) noexcept; + // void operator delete[](void*) noexcept; + // void operator delete(void*, std::size_t) noexcept; + // void operator delete[](void*, std::size_t) noexcept; // // These implicit declarations introduce only the function names operator // new, operator new[], operator delete, operator delete[]. @@ -1868,8 +1963,6 @@ void Sema::DeclareGlobalNewDelete() { // "std" or "bad_alloc" as necessary to form the exception specification. // However, we do not make these implicit declarations visible to name // lookup. - // Note that the C++0x versions of operator delete are deallocation functions, - // and thus are implicitly noexcept. if (!StdBadAlloc && !getLangOpts().CPlusPlus11) { // The "std::bad_alloc" class has not yet been declared, so build it // implicitly. @@ -1889,40 +1982,61 @@ void Sema::DeclareGlobalNewDelete() { DeclareGlobalAllocationFunction( Context.DeclarationNames.getCXXOperatorName(OO_New), - VoidPtr, SizeT, AssumeSaneOperatorNew); + VoidPtr, SizeT, QualType(), AssumeSaneOperatorNew); DeclareGlobalAllocationFunction( Context.DeclarationNames.getCXXOperatorName(OO_Array_New), - VoidPtr, SizeT, AssumeSaneOperatorNew); + VoidPtr, SizeT, QualType(), AssumeSaneOperatorNew); DeclareGlobalAllocationFunction( Context.DeclarationNames.getCXXOperatorName(OO_Delete), Context.VoidTy, VoidPtr); DeclareGlobalAllocationFunction( Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete), Context.VoidTy, VoidPtr); + if (getLangOpts().SizedDeallocation) { + DeclareGlobalAllocationFunction( + Context.DeclarationNames.getCXXOperatorName(OO_Delete), + Context.VoidTy, VoidPtr, Context.getSizeType()); + DeclareGlobalAllocationFunction( + Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete), + Context.VoidTy, VoidPtr, Context.getSizeType()); + } } /// DeclareGlobalAllocationFunction - Declares a single implicit global /// allocation function if it doesn't already exist. void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, - QualType Return, QualType Argument, + QualType Return, + QualType Param1, QualType Param2, bool AddMallocAttr) { DeclContext *GlobalCtx = Context.getTranslationUnitDecl(); + unsigned NumParams = Param2.isNull() ? 1 : 2; // Check if this function is already declared. - { - DeclContext::lookup_result R = GlobalCtx->lookup(Name); - for (DeclContext::lookup_iterator Alloc = R.begin(), AllocEnd = R.end(); - Alloc != AllocEnd; ++Alloc) { - // Only look at non-template functions, as it is the predefined, - // non-templated allocation function we are trying to declare here. - if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*Alloc)) { - QualType InitialParamType = - Context.getCanonicalType( - Func->getParamDecl(0)->getType().getUnqualifiedType()); + DeclContext::lookup_result R = GlobalCtx->lookup(Name); + for (DeclContext::lookup_iterator Alloc = R.begin(), AllocEnd = R.end(); + Alloc != AllocEnd; ++Alloc) { + // Only look at non-template functions, as it is the predefined, + // non-templated allocation function we are trying to declare here. + if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*Alloc)) { + if (Func->getNumParams() == NumParams) { + QualType InitialParam1Type = + Context.getCanonicalType(Func->getParamDecl(0) + ->getType().getUnqualifiedType()); + QualType InitialParam2Type = + NumParams == 2 + ? Context.getCanonicalType(Func->getParamDecl(1) + ->getType().getUnqualifiedType()) + : QualType(); // FIXME: Do we need to check for default arguments here? - if (Func->getNumParams() == 1 && InitialParamType == Argument) { - if(AddMallocAttr && !Func->hasAttr<MallocAttr>()) - Func->addAttr(::new (Context) MallocAttr(SourceLocation(), Context)); + if (InitialParam1Type == Param1 && + (NumParams == 1 || InitialParam2Type == Param2)) { + if (AddMallocAttr && !Func->hasAttr<MallocAttr>()) + Func->addAttr(::new (Context) MallocAttr(SourceLocation(), + Context)); + // Make the function visible to name lookup, even if we found it in + // an unimported module. It either is an implicitly-declared global + // allocation function, or is suppressing that function. + Func->setHidden(false); return; } } @@ -1950,7 +2064,10 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, EST_BasicNoexcept : EST_DynamicNone; } - QualType FnType = Context.getFunctionType(Return, Argument, EPI); + QualType Params[] = { Param1, Param2 }; + + QualType FnType = Context.getFunctionType( + Return, ArrayRef<QualType>(Params, NumParams), EPI); FunctionDecl *Alloc = FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), SourceLocation(), Name, @@ -1960,11 +2077,13 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, if (AddMallocAttr) Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context)); - ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(), - SourceLocation(), 0, - Argument, /*TInfo=*/0, - SC_None, 0); - Alloc->setParams(Param); + ParmVarDecl *ParamDecls[2]; + for (unsigned I = 0; I != NumParams; ++I) + ParamDecls[I] = ParmVarDecl::Create(Context, Alloc, SourceLocation(), + SourceLocation(), 0, + Params[I], /*TInfo=*/0, + SC_None, 0); + Alloc->setParams(ArrayRef<ParmVarDecl*>(ParamDecls, NumParams)); // FIXME: Also add this declaration to the IdentifierResolver, but // make sure it is at the end of the chain to coincide with the @@ -1972,6 +2091,48 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, Context.getTranslationUnitDecl()->addDecl(Alloc); } +FunctionDecl *Sema::FindUsualDeallocationFunction(SourceLocation StartLoc, + bool CanProvideSize, + DeclarationName Name) { + DeclareGlobalNewDelete(); + + LookupResult FoundDelete(*this, Name, StartLoc, LookupOrdinaryName); + LookupQualifiedName(FoundDelete, Context.getTranslationUnitDecl()); + + // C++ [expr.new]p20: + // [...] Any non-placement deallocation function matches a + // non-placement allocation function. [...] + llvm::SmallVector<FunctionDecl*, 2> Matches; + for (LookupResult::iterator D = FoundDelete.begin(), + DEnd = FoundDelete.end(); + D != DEnd; ++D) { + if (FunctionDecl *Fn = dyn_cast<FunctionDecl>(*D)) + if (isNonPlacementDeallocationFunction(*this, Fn)) + Matches.push_back(Fn); + } + + // C++1y [expr.delete]p?: + // If the type is complete and deallocation function lookup finds both a + // usual deallocation function with only a pointer parameter and a usual + // deallocation function with both a pointer parameter and a size + // parameter, then the selected deallocation function shall be the one + // with two parameters. Otherwise, the selected deallocation function + // shall be the function with one parameter. + if (getLangOpts().SizedDeallocation && Matches.size() == 2) { + unsigned NumArgs = CanProvideSize ? 2 : 1; + if (Matches[0]->getNumParams() != NumArgs) + Matches.erase(Matches.begin()); + else + Matches.erase(Matches.begin() + 1); + assert(Matches[0]->getNumParams() == NumArgs && + "found an unexpected uusal deallocation function"); + } + + assert(Matches.size() == 1 && + "unexpectedly have multiple usual deallocation functions"); + return Matches.front(); +} + bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, DeclarationName Name, FunctionDecl* &Operator, bool Diagnose) { @@ -2045,19 +2206,7 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, return true; } - // Look for a global declaration. - DeclareGlobalNewDelete(); - DeclContext *TUDecl = Context.getTranslationUnitDecl(); - - CXXNullPtrLiteralExpr Null(Context.VoidPtrTy, SourceLocation()); - Expr* DeallocArgs[1]; - DeallocArgs[0] = &Null; - if (FindAllocationOverload(StartLoc, SourceRange(), Name, - DeallocArgs, 1, TUDecl, !Diagnose, - Operator, Diagnose)) - return true; - - assert(Operator && "Did not find a deallocation function!"); + Operator = 0; return false; } @@ -2070,7 +2219,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, bool ArrayForm, Expr *ExE) { // C++ [expr.delete]p1: // The operand shall have a pointer type, or a class type having a single - // conversion function to a pointer type. The result has type void. + // non-explicit conversion function to a pointer type. The result has type + // void. // // DR599 amends "pointer type" to "pointer to object type" in both cases. @@ -2087,59 +2237,65 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, QualType Type = Ex.get()->getType(); - if (const RecordType *Record = Type->getAs<RecordType>()) { - if (RequireCompleteType(StartLoc, Type, - diag::err_delete_incomplete_class_type)) - return ExprError(); + class DeleteConverter : public ContextualImplicitConverter { + public: + DeleteConverter() : ContextualImplicitConverter(false, true) {} - SmallVector<CXXConversionDecl*, 4> ObjectPtrConversions; + bool match(QualType ConvType) { + // FIXME: If we have an operator T* and an operator void*, we must pick + // the operator T*. + if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>()) + if (ConvPtrType->getPointeeType()->isIncompleteOrObjectType()) + return true; + return false; + } - CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); - std::pair<CXXRecordDecl::conversion_iterator, - CXXRecordDecl::conversion_iterator> - Conversions = RD->getVisibleConversionFunctions(); - for (CXXRecordDecl::conversion_iterator - I = Conversions.first, E = Conversions.second; I != E; ++I) { - NamedDecl *D = I.getDecl(); - if (isa<UsingShadowDecl>(D)) - D = cast<UsingShadowDecl>(D)->getTargetDecl(); + SemaDiagnosticBuilder diagnoseNoMatch(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_delete_operand) << T; + } - // Skip over templated conversion functions; they aren't considered. - if (isa<FunctionTemplateDecl>(D)) - continue; + SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_delete_incomplete_class_type) << T; + } - CXXConversionDecl *Conv = cast<CXXConversionDecl>(D); + SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc, + QualType T, QualType ConvTy) { + return S.Diag(Loc, diag::err_delete_explicit_conversion) << T << ConvTy; + } - QualType ConvType = Conv->getConversionType().getNonReferenceType(); - if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>()) - if (ConvPtrType->getPointeeType()->isIncompleteOrObjectType()) - ObjectPtrConversions.push_back(Conv); + SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv, + QualType ConvTy) { + return S.Diag(Conv->getLocation(), diag::note_delete_conversion) + << ConvTy; } - if (ObjectPtrConversions.size() == 1) { - // We have a single conversion to a pointer-to-object type. Perform - // that conversion. - // TODO: don't redo the conversion calculation. - ExprResult Res = - PerformImplicitConversion(Ex.get(), - ObjectPtrConversions.front()->getConversionType(), - AA_Converting); - if (Res.isUsable()) { - Ex = Res; - Type = Ex.get()->getType(); - } + + SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_ambiguous_delete_operand) << T; } - else if (ObjectPtrConversions.size() > 1) { - Diag(StartLoc, diag::err_ambiguous_delete_operand) - << Type << Ex.get()->getSourceRange(); - for (unsigned i= 0; i < ObjectPtrConversions.size(); i++) - NoteOverloadCandidate(ObjectPtrConversions[i]); - return ExprError(); + + SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv, + QualType ConvTy) { + return S.Diag(Conv->getLocation(), diag::note_delete_conversion) + << ConvTy; } - } - if (!Type->isPointerType()) - return ExprError(Diag(StartLoc, diag::err_delete_operand) - << Type << Ex.get()->getSourceRange()); + SemaDiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc, + QualType T, QualType ConvTy) { + llvm_unreachable("conversion functions are permitted"); + } + } Converter; + + Ex = PerformContextualImplicitConversion(StartLoc, Ex.take(), Converter); + if (Ex.isInvalid()) + return ExprError(); + Type = Ex.get()->getType(); + if (!Converter.match(Type)) + // FIXME: PerformContextualImplicitConversion should return ExprError + // itself in this case. + return ExprError(); QualType Pointee = Type->getAs<PointerType>()->getPointeeType(); QualType PointeeElem = Context.getBaseElementType(Pointee); @@ -2200,7 +2356,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // Otherwise, the usual operator delete[] should be the // function we just found. - else if (isa<CXXMethodDecl>(OperatorDelete)) + else if (OperatorDelete && isa<CXXMethodDecl>(OperatorDelete)) UsualArrayDeleteWantsSize = (OperatorDelete->getNumParams() == 2); } @@ -2238,19 +2394,13 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, } - if (!OperatorDelete) { + if (!OperatorDelete) // Look for a global declaration. - DeclareGlobalNewDelete(); - DeclContext *TUDecl = Context.getTranslationUnitDecl(); - Expr *Arg = Ex.get(); - if (!Context.hasSameType(Arg->getType(), Context.VoidPtrTy)) - Arg = ImplicitCastExpr::Create(Context, Context.VoidPtrTy, - CK_BitCast, Arg, 0, VK_RValue); - if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName, - &Arg, 1, TUDecl, /*AllowMissing=*/false, - OperatorDelete)) - return ExprError(); - } + OperatorDelete = FindUsualDeallocationFunction( + StartLoc, !RequireCompleteType(StartLoc, Pointee, 0) && + (!ArrayForm || UsualArrayDeleteWantsSize || + Pointee.isDestructedType()), + DeleteName); MarkFunctionReferenced(StartLoc, OperatorDelete); @@ -2261,7 +2411,6 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, PDiag(diag::err_access_dtor) << PointeeElem); } } - } return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm, @@ -2377,6 +2526,10 @@ static ExprResult BuildCXXCastArgument(Sema &S, CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Method); SmallVector<Expr*, 8> ConstructorArgs; + if (S.RequireNonAbstractType(CastLoc, Ty, + diag::err_allocation_of_abstract_type)) + return ExprError(); + if (S.CompleteConstructorCall(Constructor, From, CastLoc, ConstructorArgs)) return ExprError(); @@ -2462,7 +2615,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, BeforeToType = Ctor->getParamDecl(0)->getType().getNonReferenceType(); } } - // Watch out for elipsis conversion. + // Watch out for ellipsis conversion. if (!ICS.UserDefined.EllipsisConversion) { ExprResult Res = PerformImplicitConversion(From, BeforeToType, @@ -2566,6 +2719,14 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, FromType = From->getType(); } + // If we're converting to an atomic type, first convert to the corresponding + // non-atomic type. + QualType ToAtomicType; + if (const AtomicType *ToAtomic = ToType->getAs<AtomicType>()) { + ToAtomicType = ToType; + ToType = ToAtomic->getValueType(); + } + // Perform the first implicit conversion. switch (SCS.First) { case ICK_Identity: @@ -2715,7 +2876,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, (void) PrepareCastToObjCObjectPointer(E); From = E.take(); } - + if (getLangOpts().ObjCAutoRefCount) + CheckObjCARCConversion(SourceRange(), ToType, From, CCK); From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK) .take(); break; @@ -2875,7 +3037,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, << ToType.getNonReferenceType(); break; - } + } default: llvm_unreachable("Improper third standard conversion"); @@ -2883,11 +3045,13 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, // 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(); - + if (!ToAtomicType.isNull()) { + assert(Context.hasSameType( + ToAtomicType->castAs<AtomicType>()->getValueType(), From->getType())); + From = ImpCastExprToType(From, ToAtomicType, CK_NonAtomicToAtomic, + VK_RValue, 0, CCK).take(); + } + return Owned(From); } @@ -2979,6 +3143,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, // These traits require a complete type. case UTT_IsFinal: + case UTT_IsSealed: // These trait expressions are designed to help implement predicates in // [meta.unary.prop] despite not being named the same. They are specified @@ -3152,6 +3317,11 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) return RD->hasAttr<FinalAttr>(); return false; + case UTT_IsSealed: + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + if (FinalAttr *FA = RD->getAttr<FinalAttr>()) + return FA->isSpelledAsSealed(); + return false; case UTT_IsSigned: return T->isSignedIntegerType(); case UTT_IsUnsigned: @@ -3444,8 +3614,8 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, // 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. + // 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 @@ -3458,24 +3628,24 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, << 1 << 1 << 1 << (int)Args.size(); return false; } - - bool SawVoid = false; + + // Precondition: T and all types in the parameter pack Args shall be + // complete types, (possibly cv-qualified) void, or arrays of + // unknown bound. for (unsigned I = 0, N = Args.size(); I != N; ++I) { - if (Args[I]->getType()->isVoidType()) { - SawVoid = true; + QualType ArgTy = Args[I]->getType(); + if (ArgTy->isVoidType() || ArgTy->isIncompleteArrayType()) continue; - } - - if (!Args[I]->getType()->isIncompleteType() && - S.RequireCompleteType(KWLoc, Args[I]->getType(), + + if (S.RequireCompleteType(KWLoc, ArgTy, 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) + + // Make sure the first argument is a complete type. + if (Args[0]->getType()->isIncompleteType()) return false; - + SmallVector<OpaqueValueExpr, 2> OpaqueArgExprs; SmallVector<Expr *, 2> ArgExprs; ArgExprs.reserve(Args.size() - 1); @@ -4259,8 +4429,8 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, // ... and one of the following shall hold: // -- The second or the third operand (but not both) is a throw- // expression; the result is of the type of the other and is a prvalue. - bool LThrow = isa<CXXThrowExpr>(LHS.get()); - bool RThrow = isa<CXXThrowExpr>(RHS.get()); + bool LThrow = isa<CXXThrowExpr>(LHS.get()->IgnoreParenCasts()); + bool RThrow = isa<CXXThrowExpr>(RHS.get()->IgnoreParenCasts()); if (LThrow && !RThrow) return RTy; if (RThrow && !LThrow) @@ -4991,6 +5161,32 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { return Owned(E); } +/// Note a set of 'operator->' functions that were used for a member access. +static void noteOperatorArrows(Sema &S, + llvm::ArrayRef<FunctionDecl *> OperatorArrows) { + unsigned SkipStart = OperatorArrows.size(), SkipCount = 0; + // FIXME: Make this configurable? + unsigned Limit = 9; + if (OperatorArrows.size() > Limit) { + // Produce Limit-1 normal notes and one 'skipping' note. + SkipStart = (Limit - 1) / 2 + (Limit - 1) % 2; + SkipCount = OperatorArrows.size() - (Limit - 1); + } + + for (unsigned I = 0; I < OperatorArrows.size(); /**/) { + if (I == SkipStart) { + S.Diag(OperatorArrows[I]->getLocation(), + diag::note_operator_arrows_suppressed) + << SkipCount; + I += SkipCount; + } else { + S.Diag(OperatorArrows[I]->getLocation(), diag::note_operator_arrow_here) + << OperatorArrows[I]->getCallResultType(); + ++I; + } + } +} + ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, ParsedType &ObjectType, @@ -5023,29 +5219,68 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc, // [...] When operator->returns, the operator-> is applied to the value // returned, with the original second operand. if (OpKind == tok::arrow) { + QualType StartingType = BaseType; + bool NoArrowOperatorFound = false; + bool FirstIteration = true; + FunctionDecl *CurFD = dyn_cast<FunctionDecl>(CurContext); // The set of types we've considered so far. llvm::SmallPtrSet<CanQualType,8> CTypes; - SmallVector<SourceLocation, 8> Locations; + SmallVector<FunctionDecl*, 8> OperatorArrows; CTypes.insert(Context.getCanonicalType(BaseType)); while (BaseType->isRecordType()) { - Result = BuildOverloadedArrowExpr(S, Base, OpLoc); - if (Result.isInvalid()) + if (OperatorArrows.size() >= getLangOpts().ArrowDepth) { + Diag(OpLoc, diag::err_operator_arrow_depth_exceeded) + << StartingType << getLangOpts().ArrowDepth << Base->getSourceRange(); + noteOperatorArrows(*this, OperatorArrows); + Diag(OpLoc, diag::note_operator_arrow_depth) + << getLangOpts().ArrowDepth; + return ExprError(); + } + + Result = BuildOverloadedArrowExpr( + S, Base, OpLoc, + // When in a template specialization and on the first loop iteration, + // potentially give the default diagnostic (with the fixit in a + // separate note) instead of having the error reported back to here + // and giving a diagnostic with a fixit attached to the error itself. + (FirstIteration && CurFD && CurFD->isFunctionTemplateSpecialization()) + ? 0 + : &NoArrowOperatorFound); + if (Result.isInvalid()) { + if (NoArrowOperatorFound) { + if (FirstIteration) { + Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << BaseType << 1 << Base->getSourceRange() + << FixItHint::CreateReplacement(OpLoc, "."); + OpKind = tok::period; + break; + } + Diag(OpLoc, diag::err_typecheck_member_reference_arrow) + << BaseType << Base->getSourceRange(); + CallExpr *CE = dyn_cast<CallExpr>(Base); + if (Decl *CD = (CE ? CE->getCalleeDecl() : 0)) { + Diag(CD->getLocStart(), + diag::note_member_reference_arrow_from_operator_arrow); + } + } return ExprError(); + } Base = Result.get(); if (CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(Base)) - Locations.push_back(OpCall->getDirectCallee()->getLocation()); + OperatorArrows.push_back(OpCall->getDirectCallee()); BaseType = Base->getType(); CanQualType CBaseType = Context.getCanonicalType(BaseType); if (!CTypes.insert(CBaseType)) { - Diag(OpLoc, diag::err_operator_arrow_circular); - for (unsigned i = 0; i < Locations.size(); i++) - Diag(Locations[i], diag::note_declared_at); + Diag(OpLoc, diag::err_operator_arrow_circular) << StartingType; + noteOperatorArrows(*this, OperatorArrows); return ExprError(); } + FirstIteration = false; } - if (BaseType->isPointerType() || BaseType->isObjCObjectPointerType()) + if (OpKind == tok::arrow && + (BaseType->isPointerType() || BaseType->isObjCObjectPointerType())) BaseType = BaseType->getPointeeType(); } @@ -5555,7 +5790,7 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) { if (Res.isInvalid()) return Owned(E); E = Res.take(); - } + } return Owned(E); } @@ -5579,15 +5814,144 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) { return Owned(E); } +// If we can unambiguously determine whether Var can never be used +// in a constant expression, return true. +// - if the variable and its initializer are non-dependent, then +// we can unambiguously check if the variable is a constant expression. +// - if the initializer is not value dependent - we can determine whether +// it can be used to initialize a constant expression. If Init can not +// be used to initialize a constant expression we conclude that Var can +// never be a constant expression. +// - FXIME: if the initializer is dependent, we can still do some analysis and +// identify certain cases unambiguously as non-const by using a Visitor: +// - such as those that involve odr-use of a ParmVarDecl, involve a new +// delete, lambda-expr, dynamic-cast, reinterpret-cast etc... +static inline bool VariableCanNeverBeAConstantExpression(VarDecl *Var, + ASTContext &Context) { + if (isa<ParmVarDecl>(Var)) return true; + const VarDecl *DefVD = 0; + + // If there is no initializer - this can not be a constant expression. + if (!Var->getAnyInitializer(DefVD)) return true; + assert(DefVD); + if (DefVD->isWeak()) return false; + EvaluatedStmt *Eval = DefVD->ensureEvaluatedStmt(); + + Expr *Init = cast<Expr>(Eval->Value); + + if (Var->getType()->isDependentType() || Init->isValueDependent()) { + if (!Init->isValueDependent()) + return !DefVD->checkInitIsICE(); + // FIXME: We might still be able to do some analysis of Init here + // to conclude that even in a dependent setting, Init can never + // be a constexpr - but for now admit agnosticity. + return false; + } + return !IsVariableAConstantExpression(Var, Context); +} + +/// \brief Check if the current lambda scope has any potential captures, and +/// whether they can be captured by any of the enclosing lambdas that are +/// ready to capture. If there is a lambda that can capture a nested +/// potential-capture, go ahead and do so. Also, check to see if any +/// variables are uncaptureable or do not involve an odr-use so do not +/// need to be captured. + +static void CheckLambdaCaptures(Expr *const FE, + LambdaScopeInfo *const CurrentLSI, Sema &S) { + + assert(!S.isUnevaluatedContext()); + assert(S.CurContext->isDependentContext()); + const bool IsFullExprInstantiationDependent = + FE->isInstantiationDependent(); + // All the potentially captureable variables in the current nested + // lambda (within a generic outer lambda), must be captured by an + // outer lambda that is enclosed within a non-dependent context. + + for (size_t I = 0, N = CurrentLSI->getNumPotentialVariableCaptures(); + I != N; ++I) { + Expr *VarExpr = 0; + VarDecl *Var = 0; + CurrentLSI->getPotentialVariableCapture(I, Var, VarExpr); + // + if (CurrentLSI->isVariableExprMarkedAsNonODRUsed(VarExpr) && + !IsFullExprInstantiationDependent) + continue; + // Climb up until we find a lambda that can capture: + // - a generic-or-non-generic lambda call operator that is enclosed + // within a non-dependent context. + unsigned FunctionScopeIndexOfCapturableLambda = 0; + if (GetInnermostEnclosingCapturableLambda( + S.FunctionScopes, FunctionScopeIndexOfCapturableLambda, + S.CurContext, Var, S)) { + MarkVarDeclODRUsed(Var, VarExpr->getExprLoc(), + S, &FunctionScopeIndexOfCapturableLambda); + } + const bool IsVarNeverAConstantExpression = + VariableCanNeverBeAConstantExpression(Var, S.Context); + if (!IsFullExprInstantiationDependent || IsVarNeverAConstantExpression) { + // This full expression is not instantiation dependent or the variable + // can not be used in a constant expression - which means + // this variable must be odr-used here, so diagnose a + // capture violation early, if the variable is un-captureable. + // This is purely for diagnosing errors early. Otherwise, this + // error would get diagnosed when the lambda becomes capture ready. + QualType CaptureType, DeclRefType; + SourceLocation ExprLoc = VarExpr->getExprLoc(); + if (S.tryCaptureVariable(Var, ExprLoc, S.TryCapture_Implicit, + /*EllipsisLoc*/ SourceLocation(), + /*BuildAndDiagnose*/false, CaptureType, + DeclRefType, 0)) { + // We will never be able to capture this variable, and we need + // to be able to in any and all instantiations, so diagnose it. + S.tryCaptureVariable(Var, ExprLoc, S.TryCapture_Implicit, + /*EllipsisLoc*/ SourceLocation(), + /*BuildAndDiagnose*/true, CaptureType, + DeclRefType, 0); + } + } + } + + if (CurrentLSI->hasPotentialThisCapture()) { + unsigned FunctionScopeIndexOfCapturableLambda = 0; + if (GetInnermostEnclosingCapturableLambda( + S.FunctionScopes, FunctionScopeIndexOfCapturableLambda, + S.CurContext, /*0 is 'this'*/ 0, S)) { + S.CheckCXXThisCapture(CurrentLSI->PotentialThisCaptureLocation, + /*Explicit*/false, /*BuildAndDiagnose*/true, + &FunctionScopeIndexOfCapturableLambda); + } + } + CurrentLSI->clearPotentialCaptures(); +} + + ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC, bool DiscardedValue, - bool IsConstexpr) { + bool IsConstexpr, + bool IsLambdaInitCaptureInitializer) { ExprResult FullExpr = Owned(FE); if (!FullExpr.get()) return ExprError(); - - if (DiagnoseUnexpandedParameterPack(FullExpr.get())) + + // If we are an init-expression in a lambdas init-capture, we should not + // diagnose an unexpanded pack now (will be diagnosed once lambda-expr + // containing full-expression is done). + // template<class ... Ts> void test(Ts ... t) { + // test([&a(t)]() { <-- (t) is an init-expr that shouldn't be diagnosed now. + // return a; + // }() ...); + // } + // FIXME: This is a hack. It would be better if we pushed the lambda scope + // when we parse the lambda introducer, and teach capturing (but not + // unexpanded pack detection) to walk over LambdaScopeInfos which don't have a + // corresponding class yet (that is, have LambdaScopeInfo either represent a + // lambda where we've entered the introducer but not the body, or represent a + // lambda where we've entered the body, depending on where the + // parser/instantiation has got to). + if (!IsLambdaInitCaptureInitializer && + DiagnoseUnexpandedParameterPack(FullExpr.get())) return ExprError(); // Top-level expressions default to 'id' when we're in a debugger. @@ -5609,6 +5973,56 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC, } CheckCompletedExpr(FullExpr.get(), CC, IsConstexpr); + + // At the end of this full expression (which could be a deeply nested + // lambda), if there is a potential capture within the nested lambda, + // have the outer capture-able lambda try and capture it. + // Consider the following code: + // void f(int, int); + // void f(const int&, double); + // void foo() { + // const int x = 10, y = 20; + // auto L = [=](auto a) { + // auto M = [=](auto b) { + // f(x, b); <-- requires x to be captured by L and M + // f(y, a); <-- requires y to be captured by L, but not all Ms + // }; + // }; + // } + + // FIXME: Also consider what happens for something like this that involves + // the gnu-extension statement-expressions or even lambda-init-captures: + // void f() { + // const int n = 0; + // auto L = [&](auto a) { + // +n + ({ 0; a; }); + // }; + // } + // + // Here, we see +n, and then the full-expression 0; ends, so we don't + // capture n (and instead remove it from our list of potential captures), + // and then the full-expression +n + ({ 0; }); ends, but it's too late + // for us to see that we need to capture n after all. + + LambdaScopeInfo *const CurrentLSI = getCurLambda(); + // FIXME: PR 17877 showed that getCurLambda() can return a valid pointer + // even if CurContext is not a lambda call operator. Refer to that Bug Report + // for an example of the code that might cause this asynchrony. + // By ensuring we are in the context of a lambda's call operator + // we can fix the bug (we only need to check whether we need to capture + // if we are within a lambda's body); but per the comments in that + // PR, a proper fix would entail : + // "Alternative suggestion: + // - Add to Sema an integer holding the smallest (outermost) scope + // index that we are *lexically* within, and save/restore/set to + // FunctionScopes.size() in InstantiatingTemplate's + // constructor/destructor. + // - Teach the handful of places that iterate over FunctionScopes to + // stop at the outermost enclosing lexical scope." + const bool IsInLambdaDeclContext = isLambdaCallOperator(CurContext); + if (IsInLambdaDeclContext && CurrentLSI && + CurrentLSI->hasPotentialCaptures() && !FullExpr.isInvalid()) + CheckLambdaCaptures(FE, CurrentLSI, *this); return MaybeCreateExprWithCleanups(FullExpr); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp index 545ac2746d6d..f6accb15bf98 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" @@ -538,13 +539,42 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, namespace { // Callback to only accept typo corrections that are either a ValueDecl or a -// FunctionTemplateDecl. +// FunctionTemplateDecl and are declared in the current record or, for a C++ +// classes, one of its base classes. class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback { public: + explicit RecordMemberExprValidatorCCC(const RecordType *RTy) + : Record(RTy->getDecl()) {} + virtual bool ValidateCandidate(const TypoCorrection &candidate) { NamedDecl *ND = candidate.getCorrectionDecl(); - return ND && (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)); + // Don't accept candidates that cannot be member functions, constants, + // variables, or templates. + if (!ND || !(isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND))) + return false; + + // Accept candidates that occur in the current record. + if (Record->containsDecl(ND)) + return true; + + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record)) { + // Accept candidates that occur in any of the current class' base classes. + for (CXXRecordDecl::base_class_const_iterator BS = RD->bases_begin(), + BSEnd = RD->bases_end(); + BS != BSEnd; ++BS) { + if (const RecordType *BSTy = dyn_cast_or_null<RecordType>( + BS->getType().getTypePtrOrNull())) { + if (BSTy->getDecl()->containsDecl(ND)) + return true; + } + } + } + + return false; } + + private: + const RecordDecl *const Record; }; } @@ -600,24 +630,31 @@ 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; + RecordMemberExprValidatorCCC Validator(RTy); TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), NULL, &SS, Validator, DC); R.clear(); - if (NamedDecl *ND = Corrected.getCorrectionDecl()) { - std::string CorrectedStr( - Corrected.getAsString(SemaRef.getLangOpts())); - std::string CorrectedQuotedStr( - Corrected.getQuoted(SemaRef.getLangOpts())); + if (Corrected.isResolved() && !Corrected.isKeyword()) { R.setLookupName(Corrected.getCorrection()); - R.addDecl(ND); - SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest) - << Name << DC << CorrectedQuotedStr << SS.getRange() - << FixItHint::CreateReplacement(Corrected.getCorrectionRange(), - CorrectedStr); - SemaRef.Diag(ND->getLocation(), diag::note_previous_decl) - << ND->getDeclName(); + for (TypoCorrection::decl_iterator DI = Corrected.begin(), + DIEnd = Corrected.end(); + DI != DIEnd; ++DI) { + R.addDecl(*DI); + } + R.resolveKind(); + + // If we're typo-correcting to an overloaded name, we don't yet have enough + // information to do overload resolution, so we don't know which previous + // declaration to point to. + if (Corrected.isOverloaded()) + Corrected.setCorrectionDecl(0); + bool DroppedSpecifier = + Corrected.WillReplaceSpecifier() && + Name.getAsString() == Corrected.getAsString(SemaRef.getLangOpts()); + SemaRef.diagnoseTypo(Corrected, + SemaRef.PDiag(diag::err_no_member_suggest) + << Name << DC << DroppedSpecifier << SS.getRange()); } return false; @@ -687,6 +724,7 @@ ExprResult Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, SourceLocation loc, IndirectFieldDecl *indirectField, + DeclAccessPair foundDecl, Expr *baseObjectExpr, SourceLocation opLoc) { // First, build the expression that refers to the base object. @@ -764,15 +802,15 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, if (!baseVariable) { FieldDecl *field = cast<FieldDecl>(*FI); - // FIXME: use the real found-decl info! - DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess()); - // Make a nameInfo that properly uses the anonymous name. DeclarationNameInfo memberNameInfo(field->getDeclName(), loc); result = BuildFieldReferenceExpr(*this, result, baseObjectIsPointer, EmptySS, field, foundDecl, memberNameInfo).take(); + if (!result) + return ExprError(); + baseObjectIsPointer = false; // FIXME: check qualified member access @@ -783,14 +821,15 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, while (FI != FEnd) { FieldDecl *field = cast<FieldDecl>(*FI++); - + // FIXME: these are somewhat meaningless DeclarationNameInfo memberNameInfo(field->getDeclName(), loc); - DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess()); - + DeclAccessPair fakeFoundDecl = + DeclAccessPair::make(field, field->getAccess()); + result = BuildFieldReferenceExpr(*this, result, /*isarrow*/ false, - (FI == FEnd? SS : EmptySS), field, - foundDecl, memberNameInfo).take(); + (FI == FEnd? SS : EmptySS), field, + fakeFoundDecl, memberNameInfo).take(); } return Owned(result); @@ -845,7 +884,54 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, BaseType = BaseType->castAs<PointerType>()->getPointeeType(); } R.setBaseObjectType(BaseType); - + + LambdaScopeInfo *const CurLSI = getCurLambda(); + // If this is an implicit member reference and the overloaded + // name refers to both static and non-static member functions + // (i.e. BaseExpr is null) and if we are currently processing a lambda, + // check if we should/can capture 'this'... + // Keep this example in mind: + // struct X { + // void f(int) { } + // static void f(double) { } + // + // int g() { + // auto L = [=](auto a) { + // return [](int i) { + // return [=](auto b) { + // f(b); + // //f(decltype(a){}); + // }; + // }; + // }; + // auto M = L(0.0); + // auto N = M(3); + // N(5.32); // OK, must not error. + // return 0; + // } + // }; + // + if (!BaseExpr && CurLSI) { + SourceLocation Loc = R.getNameLoc(); + if (SS.getRange().isValid()) + Loc = SS.getRange().getBegin(); + DeclContext *EnclosingFunctionCtx = CurContext->getParent()->getParent(); + // If the enclosing function is not dependent, then this lambda is + // capture ready, so if we can capture this, do so. + if (!EnclosingFunctionCtx->isDependentContext()) { + // If the current lambda and all enclosing lambdas can capture 'this' - + // then go ahead and capture 'this' (since our unresolved overload set + // contains both static and non-static member functions). + if (!CheckCXXThisCapture(Loc, /*Explcit*/false, /*Diagnose*/false)) + CheckCXXThisCapture(Loc); + } else if (CurContext->isDependentContext()) { + // ... since this is an implicit member reference, that might potentially + // involve a 'this' capture, mark 'this' for potential capture in + // enclosing lambdas. + if (CurLSI->ImpCaptureStyle != CurLSI->ImpCap_None) + CurLSI->addPotentialThisCapture(Loc); + } + } const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo(); DeclarationName MemberName = MemberNameInfo.getName(); SourceLocation MemberLoc = MemberNameInfo.getLoc(); @@ -974,7 +1060,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, // We may have found a field within an anonymous union or struct // (C++ [class.union]). return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD, - BaseExpr, OpLoc); + FoundDecl, BaseExpr, + OpLoc); if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, @@ -1117,10 +1204,13 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, // foo->bar // This is actually well-formed in C++ if MyRecord has an // overloaded operator->, but that should have been dealt with - // by now. - Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) - << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() - << FixItHint::CreateReplacement(OpLoc, "."); + // by now--or a diagnostic message already issued if a problem + // was encountered while looking for the overloaded operator->. + if (!getLangOpts().CPlusPlus) { + Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() + << FixItHint::CreateReplacement(OpLoc, "."); + } IsArrow = false; } else if (BaseType->isFunctionType()) { goto fail; @@ -1190,14 +1280,10 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, LookupMemberName, NULL, NULL, Validator, IDecl)) { IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>(); - Diag(R.getNameLoc(), - diag::err_typecheck_member_reference_ivar_suggest) - << IDecl->getDeclName() << MemberName << IV->getDeclName() - << FixItHint::CreateReplacement(R.getNameLoc(), - IV->getNameAsString()); - Diag(IV->getLocation(), diag::note_previous_decl) - << IV->getDeclName(); - + diagnoseTypo(Corrected, + PDiag(diag::err_typecheck_member_reference_ivar_suggest) + << IDecl->getDeclName() << MemberName); + // Figure out the class that declares the ivar. assert(!ClassDeclared); Decl *D = cast<Decl>(IV->getDeclContext()); @@ -1297,7 +1383,7 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, MemberLoc); if (Level != DiagnosticsEngine::Ignored) - getCurFunction()->recordUseOfWeak(Result); + recordUseOfEvaluatedWeak(Result); } } @@ -1348,8 +1434,9 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, if (DiagnoseUseOfDecl(OMD, MemberLoc)) return ExprError(); Selector SetterSel = - SelectorTable::constructSetterName(PP.getIdentifierTable(), - PP.getSelectorTable(), Member); + SelectorTable::constructSetterSelector(PP.getIdentifierTable(), + PP.getSelectorTable(), + Member); ObjCMethodDecl *SMD = 0; if (Decl *SDecl = FindGetterSetterNameDecl(OPT, /*Property id*/0, SetterSel, Context)) @@ -1396,8 +1483,9 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, // If we found a getter then this may be a valid dot-reference, we // will look for the matching setter, in case it is needed. Selector SetterSel = - SelectorTable::constructSetterName(PP.getIdentifierTable(), - PP.getSelectorTable(), Member); + SelectorTable::constructSetterSelector(PP.getIdentifierTable(), + PP.getSelectorTable(), + Member); ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); if (!Setter) { // If this reference is in an @implementation, also check for 'private' @@ -1670,7 +1758,8 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, // (C++ [class.union]). // FIXME: template-ids inside anonymous structs? if (IndirectFieldDecl *FD = R.getAsSingle<IndirectFieldDecl>()) - return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD); + return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD, + R.begin().getPair()); // If this is known to be an instance access, go ahead and build an // implicit 'this' expression now. diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp index cf77896cb8c3..cc8eacee6103 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp @@ -266,7 +266,7 @@ ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) { break; case CharacterLiteral::Wide: - NumberType = Context.getWCharType(); + NumberType = Context.getWideCharType(); break; case CharacterLiteral::UTF16: @@ -324,7 +324,8 @@ ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc, /// \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) { + QualType T, + bool ArrayLiteral = false) { // If the expression is type-dependent, there's nothing for us to do. if (Element->isTypeDependent()) return Element; @@ -401,14 +402,34 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, Recovered = true; } } - + if (!Recovered) { S.Diag(Element->getLocStart(), diag::err_invalid_collection_element) << Element->getType(); return ExprError(); } } - + if (ArrayLiteral) + if (ObjCStringLiteral *getString = + dyn_cast<ObjCStringLiteral>(OrigElement)) { + if (StringLiteral *SL = getString->getString()) { + unsigned numConcat = SL->getNumConcatenated(); + if (numConcat > 1) { + // Only warn if the concatenated string doesn't come from a macro. + bool hasMacro = false; + for (unsigned i = 0; i < numConcat ; ++i) + if (SL->getStrTokenLoc(i).isMacroID()) { + hasMacro = true; + break; + } + if (!hasMacro) + S.Diag(Element->getLocStart(), + diag::warn_concatenated_nsarray_literal) + << Element->getType(); + } + } + } + // Make sure that the element has the type that the container factory // function expects. return S.PerformCopyInitialization( @@ -521,7 +542,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { break; case CharacterLiteral::Wide: - ValueType = Context.getWCharType(); + ValueType = Context.getWideCharType(); break; case CharacterLiteral::UTF16: @@ -581,7 +602,7 @@ ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, Expr *IndexExpr, ObjCMethodDecl *getterMethod, ObjCMethodDecl *setterMethod) { - assert(!LangOpts.ObjCRuntime.isSubscriptPointerArithmetic()); + assert(!LangOpts.isSubscriptPointerArithmetic()); // We can't get dependent types here; our callers should have // filtered them out. @@ -710,7 +731,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { for (unsigned I = 0, N = Elements.size(); I != N; ++I) { ExprResult Converted = CheckObjCCollectionLiteralElement(*this, ElementsBuffer[I], - RequiredType); + RequiredType, true); if (Converted.isInvalid()) return ExprError(); @@ -902,14 +923,10 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, QualType Ty = Context.getObjCObjectPointerType( - Context.getObjCInterfaceType(NSDictionaryDecl)); - return MaybeBindToTemporary( - ObjCDictionaryLiteral::Create(Context, - llvm::makeArrayRef(Elements, - NumElements), - HasPackExpansions, - Ty, - DictionaryWithObjectsMethod, SR)); + Context.getObjCInterfaceType(NSDictionaryDecl)); + return MaybeBindToTemporary(ObjCDictionaryLiteral::Create( + Context, makeArrayRef(Elements, NumElements), HasPackExpansions, Ty, + DictionaryWithObjectsMethod, SR)); } ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc, @@ -968,8 +985,18 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, if (!Method) Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(LParenLoc, RParenLoc)); - if (!Method) - Diag(SelLoc, diag::warn_undeclared_selector) << Sel; + if (!Method) { + if (const ObjCMethodDecl *OM = SelectorsForTypoCorrection(Sel)) { + Selector MatchedSel = OM->getSelector(); + SourceRange SelectorRange(LParenLoc.getLocWithOffset(1), + RParenLoc.getLocWithOffset(-1)); + Diag(SelLoc, diag::warn_undeclared_selector_with_typo) + << Sel << MatchedSel + << FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString()); + + } else + Diag(SelLoc, diag::warn_undeclared_selector) << Sel; + } if (!Method || Method->getImplementationControl() != ObjCMethodDecl::Optional) { @@ -1184,8 +1211,8 @@ void Sema::EmitRelatedResultTypeNote(const Expr *E) { } bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, - Expr **Args, unsigned NumArgs, - Selector Sel, + MultiExprArg Args, + Selector Sel, ArrayRef<SourceLocation> SelectorLocs, ObjCMethodDecl *Method, bool isClassMessage, bool isSuperMessage, @@ -1199,7 +1226,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, if (!Method) { // Apply default argument promotion as for (C99 6.5.2.2p6). - for (unsigned i = 0; i != NumArgs; i++) { + for (unsigned i = 0, e = Args.size(); i != e; i++) { if (Args[i]->isTypeDependent()) continue; @@ -1221,10 +1248,31 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, else DiagID = isClassMessage ? diag::warn_class_method_not_found : diag::warn_inst_method_not_found; - if (!getLangOpts().DebuggerSupport) - Diag(SelLoc, DiagID) - << Sel << isClassMessage << SourceRange(SelectorLocs.front(), + if (!getLangOpts().DebuggerSupport) { + const ObjCMethodDecl *OMD = SelectorsForTypoCorrection(Sel, ReceiverType); + if (OMD && !OMD->isInvalidDecl()) { + if (getLangOpts().ObjCAutoRefCount) + DiagID = diag::error_method_not_found_with_typo; + else + DiagID = isClassMessage ? diag::warn_class_method_not_found_with_typo + : diag::warn_instance_method_not_found_with_typo; + Selector MatchedSel = OMD->getSelector(); + SourceRange SelectorRange(SelectorLocs.front(), SelectorLocs.back()); + Diag(SelLoc, DiagID) + << Sel<< isClassMessage << MatchedSel + << FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString()); + } + else + Diag(SelLoc, DiagID) + << Sel << isClassMessage << SourceRange(SelectorLocs.front(), SelectorLocs.back()); + // Find the class to which we are sending this message. + if (ReceiverType->isObjCObjectPointerType()) { + if (ObjCInterfaceDecl *Class = + ReceiverType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()) + Diag(Class->getLocation(), diag::note_receiver_class_declared); + } + } // In debuggers, we want to use __unknown_anytype for these // results so that clients can cast them. @@ -1247,9 +1295,9 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, if (Method->param_size() > Sel.getNumArgs()) NumNamedArgs = Method->param_size(); // FIXME. This need be cleaned up. - if (NumArgs < NumNamedArgs) { + if (Args.size() < NumNamedArgs) { Diag(SelLoc, diag::err_typecheck_call_too_few_args) - << 2 << NumNamedArgs << NumArgs; + << 2 << NumNamedArgs << static_cast<unsigned>(Args.size()); return false; } @@ -1302,7 +1350,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, // Promote additional arguments to variadic methods. if (Method->isVariadic()) { - for (unsigned i = NumNamedArgs; i < NumArgs; ++i) { + for (unsigned i = NumNamedArgs, e = Args.size(); i < e; ++i) { if (Args[i]->isTypeDependent()) continue; @@ -1313,21 +1361,21 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, } } else { // Check for extra arguments to non-variadic methods. - if (NumArgs != NumNamedArgs) { + if (Args.size() != NumNamedArgs) { Diag(Args[NumNamedArgs]->getLocStart(), diag::err_typecheck_call_too_many_args) - << 2 /*method*/ << NumNamedArgs << NumArgs + << 2 /*method*/ << NumNamedArgs << static_cast<unsigned>(Args.size()) << Method->getSourceRange() << SourceRange(Args[NumNamedArgs]->getLocStart(), - Args[NumArgs-1]->getLocEnd()); + Args.back()->getLocEnd()); } } - DiagnoseSentinelCalls(Method, SelLoc, Args, NumArgs); + DiagnoseSentinelCalls(Method, SelLoc, Args); // Do additional checkings on method. - IsError |= CheckObjCMethodCall(Method, SelLoc, - llvm::makeArrayRef<const Expr *>(Args, NumArgs)); + IsError |= CheckObjCMethodCall( + Method, SelLoc, makeArrayRef<const Expr *>(Args.data(), Args.size())); return IsError; } @@ -1534,8 +1582,8 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, // If we found a getter then this may be a valid dot-reference, we // will look for the matching setter, in case it is needed. Selector SetterSel = - SelectorTable::constructSetterName(PP.getIdentifierTable(), - PP.getSelectorTable(), Member); + SelectorTable::constructSetterSelector(PP.getIdentifierTable(), + PP.getSelectorTable(), Member); ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel); // May be founf in property's qualified list. @@ -1569,16 +1617,11 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, // Attempt to correct for typos in property names. DeclFilterCCC<ObjCPropertyDecl> Validator; if (TypoCorrection Corrected = CorrectTypo( - DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL, - NULL, Validator, IFace, false, OPT)) { - ObjCPropertyDecl *Property = - Corrected.getCorrectionDeclAs<ObjCPropertyDecl>(); + DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL, + NULL, Validator, IFace, false, OPT)) { + diagnoseTypo(Corrected, PDiag(diag::err_property_not_found_suggest) + << MemberName << QualType(OPT, 0)); DeclarationName TypoResult = Corrected.getCorrection(); - Diag(MemberLoc, diag::err_property_not_found_suggest) - << MemberName << QualType(OPT, 0) << TypoResult - << FixItHint::CreateReplacement(MemberLoc, TypoResult.getAsString()); - Diag(Property->getLocation(), diag::note_previous_decl) - << Property->getDeclName(); return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc, TypoResult, MemberLoc, SuperLoc, SuperType, Super); @@ -1681,8 +1724,9 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, // Look for the matching setter, in case it is needed. Selector SetterSel = - SelectorTable::constructSetterName(PP.getIdentifierTable(), - PP.getSelectorTable(), &propertyName); + SelectorTable::constructSetterSelector(PP.getIdentifierTable(), + PP.getSelectorTable(), + &propertyName); ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); if (!Setter) { @@ -1809,34 +1853,28 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, } ObjCInterfaceOrSuperCCC Validator(getCurMethodDecl()); - if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(), - Result.getLookupKind(), S, NULL, - Validator)) { + if (TypoCorrection Corrected = + CorrectTypo(Result.getLookupNameInfo(), Result.getLookupKind(), S, + NULL, Validator, NULL, false, NULL, false)) { if (Corrected.isKeyword()) { // If we've found the keyword "super" (the only keyword that would be // returned by CorrectTypo), this is a send to super. - Diag(NameLoc, diag::err_unknown_receiver_suggest) - << Name << Corrected.getCorrection() - << FixItHint::CreateReplacement(SourceRange(NameLoc), "super"); + diagnoseTypo(Corrected, + PDiag(diag::err_unknown_receiver_suggest) << Name); return ObjCSuperMessage; } else if (ObjCInterfaceDecl *Class = - Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) { + 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(); - + diagnoseTypo(Corrected, + PDiag(diag::err_unknown_receiver_suggest) << Name); QualType T = Context.getObjCInterfaceType(Class); TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc); ReceiverType = CreateParsedType(T, TSInfo); return ObjCClassMessage; } } - + // Fall back: let the parser try to parse it as an instance message. return ObjCInstanceMessage; } @@ -2065,7 +2103,8 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, unsigned NumArgs = ArgsIn.size(); Expr **Args = ArgsIn.data(); - if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, SelectorLocs, + if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs), + Sel, SelectorLocs, Method, true, SuperLoc.isValid(), LBracLoc, RBracLoc, ReturnType, VK)) @@ -2246,6 +2285,11 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } ReceiverType = Receiver->getType(); } else if (getLangOpts().CPlusPlus) { + // The receiver must be a complete type. + if (RequireCompleteType(Loc, Receiver->getType(), + diag::err_incomplete_receiver_type)) + return ExprError(); + ExprResult result = PerformContextuallyConvertToObjCPointer(Receiver); if (result.isUsable()) { Receiver = result.take(); @@ -2410,8 +2454,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, ExprValueKind VK = VK_RValue; bool ClassMessage = (ReceiverType->isObjCClassType() || ReceiverType->isObjCQualifiedClassType()); - if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, - SelectorLocs, Method, + if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs), + Sel, SelectorLocs, Method, ClassMessage, SuperLoc.isValid(), LBracLoc, RBracLoc, ReturnType, VK)) return ExprError(); @@ -3121,9 +3165,112 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, << castRange << castExpr->getSourceRange(); } +static inline ObjCBridgeAttr *getObjCBridgeAttr(const TypedefType *TD) { + TypedefNameDecl *TDNDecl = TD->getDecl(); + QualType QT = TDNDecl->getUnderlyingType(); + if (QT->isPointerType()) { + QT = QT->getPointeeType(); + if (const RecordType *RT = QT->getAs<RecordType>()) + if (RecordDecl *RD = RT->getDecl()) + if (RD->hasAttr<ObjCBridgeAttr>()) + return RD->getAttr<ObjCBridgeAttr>(); + } + return 0; +} + +static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr) { + QualType T = castExpr->getType(); + while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) { + TypedefNameDecl *TDNDecl = TD->getDecl(); + if (ObjCBridgeAttr *ObjCBAttr = getObjCBridgeAttr(TD)) { + if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) { + NamedDecl *Target = 0; + // Check for an existing type with this name. + LookupResult R(S, DeclarationName(Parm), SourceLocation(), + Sema::LookupOrdinaryName); + if (S.LookupName(R, S.TUScope)) { + Target = R.getFoundDecl(); + if (Target && isa<ObjCInterfaceDecl>(Target)) { + ObjCInterfaceDecl *ExprClass = cast<ObjCInterfaceDecl>(Target); + if (const ObjCObjectPointerType *InterfacePointerType = + castType->getAsObjCInterfacePointerType()) { + ObjCInterfaceDecl *CastClass + = InterfacePointerType->getObjectType()->getInterface(); + if ((CastClass == ExprClass) || (CastClass && ExprClass->isSuperClassOf(CastClass))) + return true; + S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge) + << T << Target->getName() << castType->getPointeeType(); + return true; + } else { + S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge) + << T << Target->getName() << castType; + return true; + } + } + } + S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface) + << castExpr->getType() << Parm->getName(); + S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); + if (Target) + S.Diag(Target->getLocStart(), diag::note_declared_at); + } + return true; + } + T = TDNDecl->getUnderlyingType(); + } + return false; +} + +// (CFErrorRef)ns +static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr) { + QualType T = castType; + while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) { + TypedefNameDecl *TDNDecl = TD->getDecl(); + if (ObjCBridgeAttr *ObjCBAttr = getObjCBridgeAttr(TD)) { + if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) { + NamedDecl *Target = 0; + // Check for an existing type with this name. + LookupResult R(S, DeclarationName(Parm), SourceLocation(), + Sema::LookupOrdinaryName); + if (S.LookupName(R, S.TUScope)) { + Target = R.getFoundDecl(); + if (Target && isa<ObjCInterfaceDecl>(Target)) { + ObjCInterfaceDecl *CastClass = cast<ObjCInterfaceDecl>(Target); + if (const ObjCObjectPointerType *InterfacePointerType = + castExpr->getType()->getAsObjCInterfacePointerType()) { + ObjCInterfaceDecl *ExprClass + = InterfacePointerType->getObjectType()->getInterface(); + if ((CastClass == ExprClass) || (ExprClass && CastClass->isSuperClassOf(ExprClass))) + return true; + S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf) + << castExpr->getType()->getPointeeType() << T; + S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); + return true; + } else { + S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf) + << castExpr->getType() << castType; + S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); + return true; + } + } + } + S.Diag(castExpr->getLocStart(), diag::err_objc_ns_bridged_invalid_cfobject) + << castExpr->getType() << castType; + S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); + if (Target) + S.Diag(Target->getLocStart(), diag::note_declared_at); + } + return true; + } + T = TDNDecl->getUnderlyingType(); + } + return false; +} + Sema::ARCConversionResult Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, - Expr *&castExpr, CheckedConversionKind CCK) { + Expr *&castExpr, CheckedConversionKind CCK, + bool DiagnoseCFAudited) { QualType castExprType = castExpr->getType(); // For the purposes of the classification, we assume reference types @@ -3177,6 +3324,17 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr && CCK != CCK_ImplicitConversion) return ACR_okay; + + if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation && + (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast)) + if (CheckObjCBridgeNSCast(*this, castType, castExpr)) + return ACR_okay; + + if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable && + (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast)) + if (CheckObjCBridgeCFCast(*this, castType, castExpr)) + return ACR_okay; + switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) { // For invalid casts, fall through. @@ -3204,8 +3362,14 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, CCK != CCK_ImplicitConversion) return ACR_unbridged; - diagnoseObjCARCConversion(*this, castRange, castType, castACTC, - castExpr, castExpr, exprACTC, CCK); + // Do not issue "bridge cast" diagnostic when implicit casting + // a retainable object to a CF type parameter belonging to an audited + // CF API function. Let caller issue a normal type mismatched diagnostic + // instead. + if (!DiagnoseCFAudited || exprACTC != ACTC_retainable || + castACTC != ACTC_coreFoundation) + diagnoseObjCARCConversion(*this, castRange, castType, castACTC, + castExpr, castExpr, exprACTC, CCK); return ACR_okay; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp index 2a845ba9898b..32b56bcddc63 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp @@ -160,27 +160,33 @@ 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)); +static bool isMacroDefined(const Sema &S, SourceLocation Loc, StringRef Name) { + const IdentifierInfo *II = &S.getASTContext().Idents.get(Name); + if (!II->hadMacroDefinition()) return false; + + MacroDirective *Macro = S.PP.getMacroDirectiveHistory(II); + return Macro && Macro->findDirectiveAtLoc(Loc, S.getSourceManager()); } -static std::string getScalarZeroExpressionForType(const Type& T, const Sema& S) { +static std::string getScalarZeroExpressionForType( + const Type &T, SourceLocation Loc, const Sema &S) { assert(T.isScalarType() && "use scalar types only"); // Suggest "0" for non-enumeration scalar types, unless we can find a // better initializer. if (T.isEnumeralType()) return std::string(); if ((T.isObjCObjectPointerType() || T.isBlockPointerType()) && - isMacroDefined(S, "nil")) + isMacroDefined(S, Loc, "nil")) return "nil"; if (T.isRealFloatingType()) return "0.0"; - if (T.isBooleanType() && S.LangOpts.CPlusPlus) + if (T.isBooleanType() && + (S.LangOpts.CPlusPlus || isMacroDefined(S, Loc, "false"))) return "false"; if (T.isPointerType() || T.isMemberPointerType()) { if (S.LangOpts.CPlusPlus11) return "nullptr"; - if (isMacroDefined(S, "NULL")) + if (isMacroDefined(S, Loc, "NULL")) return "NULL"; } if (T.isCharType()) @@ -194,9 +200,10 @@ static std::string getScalarZeroExpressionForType(const Type& T, const Sema& S) return "0"; } -std::string Sema::getFixItZeroInitializerForType(QualType T) const { +std::string +Sema::getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const { if (T->isScalarType()) { - std::string s = getScalarZeroExpressionForType(*T, *this); + std::string s = getScalarZeroExpressionForType(*T, Loc, *this); if (!s.empty()) s = " = " + s; return s; @@ -212,6 +219,7 @@ std::string Sema::getFixItZeroInitializerForType(QualType T) const { return std::string(); } -std::string Sema::getFixItZeroLiteralForType(QualType T) const { - return getScalarZeroExpressionForType(*T, *this); +std::string +Sema::getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const { + return getScalarZeroExpressionForType(*T, Loc, *this); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp index a632f022f5dd..034c1b6c7184 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp @@ -32,53 +32,99 @@ using namespace clang; // Sema Initialization Checking //===----------------------------------------------------------------------===// -static Expr *IsStringInit(Expr *Init, const ArrayType *AT, - ASTContext &Context) { +/// \brief Check whether T is compatible with a wide character type (wchar_t, +/// char16_t or char32_t). +static bool IsWideCharCompatible(QualType T, ASTContext &Context) { + if (Context.typesAreCompatible(Context.getWideCharType(), T)) + return true; + if (Context.getLangOpts().CPlusPlus || Context.getLangOpts().C11) { + return Context.typesAreCompatible(Context.Char16Ty, T) || + Context.typesAreCompatible(Context.Char32Ty, T); + } + return false; +} + +enum StringInitFailureKind { + SIF_None, + SIF_NarrowStringIntoWideChar, + SIF_WideStringIntoChar, + SIF_IncompatWideStringIntoWideChar, + SIF_Other +}; + +/// \brief Check whether the array of type AT can be initialized by the Init +/// expression by means of string initialization. Returns SIF_None if so, +/// otherwise returns a StringInitFailureKind that describes why the +/// initialization would not work. +static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, + ASTContext &Context) { if (!isa<ConstantArrayType>(AT) && !isa<IncompleteArrayType>(AT)) - return 0; + return SIF_Other; // See if this is a string literal or @encode. Init = Init->IgnoreParens(); // Handle @encode, which is a narrow string. if (isa<ObjCEncodeExpr>(Init) && AT->getElementType()->isCharType()) - return Init; + return SIF_None; // Otherwise we can only handle string literals. StringLiteral *SL = dyn_cast<StringLiteral>(Init); - if (SL == 0) return 0; + if (SL == 0) + return SIF_Other; - QualType ElemTy = Context.getCanonicalType(AT->getElementType()); + const QualType ElemTy = + Context.getCanonicalType(AT->getElementType()).getUnqualifiedType(); switch (SL->getKind()) { case StringLiteral::Ascii: case StringLiteral::UTF8: // char array can be initialized with a narrow string. // Only allow char x[] = "foo"; not char x[] = L"foo"; - return ElemTy->isCharType() ? Init : 0; + if (ElemTy->isCharType()) + return SIF_None; + if (IsWideCharCompatible(ElemTy, Context)) + return SIF_NarrowStringIntoWideChar; + return SIF_Other; + // C99 6.7.8p15 (with correction from DR343), or C11 6.7.9p15: + // "An array with element type compatible with a qualified or unqualified + // version of wchar_t, char16_t, or char32_t may be initialized by a wide + // string literal with the corresponding encoding prefix (L, u, or U, + // respectively), optionally enclosed in braces. case StringLiteral::UTF16: - return ElemTy->isChar16Type() ? Init : 0; + if (Context.typesAreCompatible(Context.Char16Ty, ElemTy)) + return SIF_None; + if (ElemTy->isCharType()) + return SIF_WideStringIntoChar; + if (IsWideCharCompatible(ElemTy, Context)) + return SIF_IncompatWideStringIntoWideChar; + return SIF_Other; case StringLiteral::UTF32: - return ElemTy->isChar32Type() ? Init : 0; + if (Context.typesAreCompatible(Context.Char32Ty, ElemTy)) + return SIF_None; + if (ElemTy->isCharType()) + return SIF_WideStringIntoChar; + if (IsWideCharCompatible(ElemTy, Context)) + return SIF_IncompatWideStringIntoWideChar; + return SIF_Other; case StringLiteral::Wide: - // wchar_t array can be initialized with a wide string: C99 6.7.8p15 (with - // correction from DR343): "An array with element type compatible with a - // qualified or unqualified version of wchar_t may be initialized by a wide - // string literal, optionally enclosed in braces." - if (Context.typesAreCompatible(Context.getWCharType(), - ElemTy.getUnqualifiedType())) - return Init; - - return 0; + if (Context.typesAreCompatible(Context.getWideCharType(), ElemTy)) + return SIF_None; + if (ElemTy->isCharType()) + return SIF_WideStringIntoChar; + if (IsWideCharCompatible(ElemTy, Context)) + return SIF_IncompatWideStringIntoWideChar; + return SIF_Other; } llvm_unreachable("missed a StringLiteral kind?"); } -static Expr *IsStringInit(Expr *init, QualType declType, ASTContext &Context) { +static StringInitFailureKind IsStringInit(Expr *init, QualType declType, + ASTContext &Context) { const ArrayType *arrayType = Context.getAsArrayType(declType); - if (!arrayType) return 0; - + if (!arrayType) + return SIF_Other; return IsStringInit(init, arrayType, Context); } @@ -190,7 +236,6 @@ class InitListChecker { Sema &SemaRef; bool hadError; bool VerifyOnly; // no diagnostics, no structure building - bool AllowBraceElision; llvm::DenseMap<InitListExpr *, InitListExpr *> SyntacticToSemantic; InitListExpr *FullyStructuredList; @@ -200,8 +245,7 @@ class InitListChecker { unsigned &StructuredIndex); void CheckExplicitInitList(const InitializedEntity &Entity, InitListExpr *IList, QualType &T, - unsigned &Index, InitListExpr *StructuredList, - unsigned &StructuredIndex, + InitListExpr *StructuredList, bool TopLevelObject = false); void CheckListElementTypes(const InitializedEntity &Entity, InitListExpr *IList, QualType &DeclType, @@ -281,8 +325,7 @@ class InitListChecker { public: InitListChecker(Sema &S, const InitializedEntity &Entity, - InitListExpr *IL, QualType &T, bool VerifyOnly, - bool AllowBraceElision); + InitListExpr *IL, QualType &T, bool VerifyOnly); bool HadError() { return hadError; } // @brief Retrieves the fully-structured initializer list used for @@ -513,16 +556,13 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity, InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, InitListExpr *IL, QualType &T, - bool VerifyOnly, bool AllowBraceElision) - : SemaRef(S), VerifyOnly(VerifyOnly), AllowBraceElision(AllowBraceElision) { + bool VerifyOnly) + : SemaRef(S), VerifyOnly(VerifyOnly) { hadError = false; - unsigned newIndex = 0; - unsigned newStructuredIndex = 0; - FullyStructuredList - = getStructuredSubobjectInit(IL, newIndex, T, 0, 0, IL->getSourceRange()); - CheckExplicitInitList(Entity, IL, T, newIndex, - FullyStructuredList, newStructuredIndex, + FullyStructuredList = + getStructuredSubobjectInit(IL, 0, T, 0, 0, IL->getSourceRange()); + CheckExplicitInitList(Entity, IL, T, FullyStructuredList, /*TopLevelObject=*/true); if (!hadError && !VerifyOnly) { @@ -559,6 +599,12 @@ int InitListChecker::numStructUnionElements(QualType DeclType) { return InitializableMembers - structDecl->hasFlexibleArrayMember(); } +/// Check whether the range of the initializer \p ParentIList from element +/// \p Index onwards can be used to initialize an object of type \p T. Update +/// \p Index to indicate how many elements of the list were consumed. +/// +/// This also fills in \p StructuredList, from element \p StructuredIndex +/// onwards, with the fully-braced, desugared form of the initialization. void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, InitListExpr *ParentIList, QualType T, unsigned &Index, @@ -599,10 +645,7 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, StructuredSubobjectInitList, StructuredSubobjectInitIndex); - if (VerifyOnly) { - if (!AllowBraceElision && (T->isArrayType() || T->isRecordType())) - hadError = true; - } else { + if (!VerifyOnly) { StructuredSubobjectInitList->setType(T); unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1); @@ -617,8 +660,7 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, // Complain about missing braces. if (T->isArrayType() || T->isRecordType()) { SemaRef.Diag(StructuredSubobjectInitList->getLocStart(), - AllowBraceElision ? diag::warn_missing_braces : - diag::err_missing_braces) + diag::warn_missing_braces) << StructuredSubobjectInitList->getSourceRange() << FixItHint::CreateInsertion( StructuredSubobjectInitList->getLocStart(), "{") @@ -626,23 +668,26 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, SemaRef.PP.getLocForEndOfToken( StructuredSubobjectInitList->getLocEnd()), "}"); - if (!AllowBraceElision) - hadError = true; } } } +/// Check whether the initializer \p IList (that was written with explicit +/// braces) can be used to initialize an object of type \p T. +/// +/// This also fills in \p StructuredList with the fully-braced, desugared +/// form of the initialization. void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, InitListExpr *IList, QualType &T, - unsigned &Index, InitListExpr *StructuredList, - unsigned &StructuredIndex, bool TopLevelObject) { assert(IList->isExplicit() && "Illegal Implicit InitListExpr"); if (!VerifyOnly) { SyntacticToSemantic[IList] = StructuredList; StructuredList->setSyntacticForm(IList); } + + unsigned Index = 0, StructuredIndex = 0; CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true, Index, StructuredList, StructuredIndex, TopLevelObject); if (!VerifyOnly) { @@ -667,7 +712,8 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, } if (StructuredIndex == 1 && - IsStringInit(StructuredList->getInit(0), T, SemaRef.Context)) { + IsStringInit(StructuredList->getInit(0), T, SemaRef.Context) == + SIF_None) { unsigned DK = diag::warn_excess_initializers_in_char_array_initializer; if (SemaRef.getLangOpts().CPlusPlus) { DK = diag::err_excess_initializers_in_char_array_initializer; @@ -781,14 +827,12 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) { if (!ElemType->isRecordType() || ElemType->isAggregateType()) { - unsigned newIndex = 0; - unsigned newStructuredIndex = 0; - InitListExpr *newStructuredList + InitListExpr *InnerStructuredList = getStructuredSubobjectInit(IList, Index, ElemType, StructuredList, StructuredIndex, SubInitList->getSourceRange()); - CheckExplicitInitList(Entity, SubInitList, ElemType, newIndex, - newStructuredList, newStructuredIndex); + CheckExplicitInitList(Entity, SubInitList, ElemType, + InnerStructuredList); ++StructuredIndex; ++Index; return; @@ -811,10 +855,10 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, // array member. There's nothing we can do with the completed // type here, though. - if (Expr *Str = IsStringInit(expr, arrayType, SemaRef.Context)) { + if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) { if (!VerifyOnly) { - CheckStringInit(Str, ElemType, arrayType, SemaRef); - UpdateStructuredListElement(StructuredList, StructuredIndex, Str); + CheckStringInit(expr, ElemType, arrayType, SemaRef); + UpdateStructuredListElement(StructuredList, StructuredIndex, expr); } ++Index; return; @@ -862,7 +906,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, if ((ElemType->isRecordType() || ElemType->isVectorType()) && SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes, !VerifyOnly) - == Sema::Compatible) { + != Sema::Incompatible) { if (ExprRes.isInvalid()) hadError = true; else { @@ -1194,16 +1238,17 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity, // Check for the special-case of initializing an array with a string. if (Index < IList->getNumInits()) { - if (Expr *Str = IsStringInit(IList->getInit(Index), arrayType, - SemaRef.Context)) { + if (IsStringInit(IList->getInit(Index), arrayType, SemaRef.Context) == + SIF_None) { // We place the string literal directly into the resulting // initializer list. This is the only place where the structure // of the structured initializer list doesn't match exactly, // because doing so would involve allocating one character // constant for each string. if (!VerifyOnly) { - CheckStringInit(Str, DeclType, arrayType, SemaRef); - UpdateStructuredListElement(StructuredList, StructuredIndex, Str); + CheckStringInit(IList->getInit(Index), DeclType, arrayType, SemaRef); + UpdateStructuredListElement(StructuredList, StructuredIndex, + IList->getInit(Index)); StructuredList->resizeInits(SemaRef.Context, StructuredIndex); } ++Index; @@ -1773,22 +1818,15 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // Name lookup didn't find anything. Determine whether this // was a typo for another field name. FieldInitializerValidatorCCC Validator(RT->getDecl()); - TypoCorrection Corrected = SemaRef.CorrectTypo( - DeclarationNameInfo(FieldName, D->getFieldLoc()), - Sema::LookupMemberName, /*Scope=*/0, /*SS=*/0, Validator, - RT->getDecl()); - if (Corrected) { - std::string CorrectedStr( - Corrected.getAsString(SemaRef.getLangOpts())); - std::string CorrectedQuotedStr( - Corrected.getQuoted(SemaRef.getLangOpts())); + if (TypoCorrection Corrected = SemaRef.CorrectTypo( + DeclarationNameInfo(FieldName, D->getFieldLoc()), + Sema::LookupMemberName, /*Scope=*/ 0, /*SS=*/ 0, Validator, + RT->getDecl())) { + SemaRef.diagnoseTypo( + Corrected, + SemaRef.PDiag(diag::err_field_designator_unknown_suggest) + << FieldName << CurrentObjectType); ReplacementField = Corrected.getCorrectionDeclAs<FieldDecl>(); - SemaRef.Diag(D->getFieldLoc(), - diag::err_field_designator_unknown_suggest) - << FieldName << CurrentObjectType << CorrectedQuotedStr - << FixItHint::CreateReplacement(D->getFieldLoc(), CorrectedStr); - SemaRef.Diag(ReplacementField->getLocation(), - diag::note_previous_decl) << CorrectedQuotedStr; hadError = true; } else { SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown) @@ -1830,8 +1868,29 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // the initializer list. if (RT->getDecl()->isUnion()) { FieldIndex = 0; - if (!VerifyOnly) + if (!VerifyOnly) { + FieldDecl *CurrentField = StructuredList->getInitializedFieldInUnion(); + if (CurrentField && CurrentField != *Field) { + assert(StructuredList->getNumInits() == 1 + && "A union should never have more than one initializer!"); + + // we're about to throw away an initializer, emit warning + SemaRef.Diag(D->getFieldLoc(), + diag::warn_initializer_overrides) + << D->getSourceRange(); + Expr *ExistingInit = StructuredList->getInit(0); + SemaRef.Diag(ExistingInit->getLocStart(), + diag::note_previous_initializer) + << /*FIXME:has side effects=*/0 + << ExistingInit->getSourceRange(); + + // remove existing initializer + StructuredList->resizeInits(SemaRef.Context, 0); + StructuredList->setInitializedFieldInUnion(0); + } + StructuredList->setInitializedFieldInUnion(*Field); + } } // Make sure we can use this declaration. @@ -2039,6 +2098,64 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, DesignatedEndIndex.setIsUnsigned(true); } + if (!VerifyOnly && StructuredList->isStringLiteralInit()) { + // We're modifying a string literal init; we have to decompose the string + // so we can modify the individual characters. + ASTContext &Context = SemaRef.Context; + Expr *SubExpr = StructuredList->getInit(0)->IgnoreParens(); + + // Compute the character type + QualType CharTy = AT->getElementType(); + + // Compute the type of the integer literals. + QualType PromotedCharTy = CharTy; + if (CharTy->isPromotableIntegerType()) + PromotedCharTy = Context.getPromotedIntegerType(CharTy); + unsigned PromotedCharTyWidth = Context.getTypeSize(PromotedCharTy); + + if (StringLiteral *SL = dyn_cast<StringLiteral>(SubExpr)) { + // Get the length of the string. + uint64_t StrLen = SL->getLength(); + if (cast<ConstantArrayType>(AT)->getSize().ult(StrLen)) + StrLen = cast<ConstantArrayType>(AT)->getSize().getZExtValue(); + StructuredList->resizeInits(Context, StrLen); + + // Build a literal for each character in the string, and put them into + // the init list. + for (unsigned i = 0, e = StrLen; i != e; ++i) { + llvm::APInt CodeUnit(PromotedCharTyWidth, SL->getCodeUnit(i)); + Expr *Init = new (Context) IntegerLiteral( + Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc()); + if (CharTy != PromotedCharTy) + Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast, + Init, 0, VK_RValue); + StructuredList->updateInit(Context, i, Init); + } + } else { + ObjCEncodeExpr *E = cast<ObjCEncodeExpr>(SubExpr); + std::string Str; + Context.getObjCEncodingForType(E->getEncodedType(), Str); + + // Get the length of the string. + uint64_t StrLen = Str.size(); + if (cast<ConstantArrayType>(AT)->getSize().ult(StrLen)) + StrLen = cast<ConstantArrayType>(AT)->getSize().getZExtValue(); + StructuredList->resizeInits(Context, StrLen); + + // Build a literal for each character in the string, and put them into + // the init list. + for (unsigned i = 0, e = StrLen; i != e; ++i) { + llvm::APInt CodeUnit(PromotedCharTyWidth, Str[i]); + Expr *Init = new (Context) IntegerLiteral( + Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc()); + if (CharTy != PromotedCharTy) + Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast, + Init, 0, VK_RValue); + StructuredList->updateInit(Context, i, Init); + } + } + } + // Make sure that our non-designated initializer list has space // for a subobject corresponding to this array element. if (!VerifyOnly && @@ -2361,12 +2478,13 @@ InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index, } } -InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context, - CXXBaseSpecifier *Base, - bool IsInheritedVirtualBase) -{ +InitializedEntity +InitializedEntity::InitializeBase(ASTContext &Context, + const CXXBaseSpecifier *Base, + bool IsInheritedVirtualBase) { InitializedEntity Result; Result.Kind = EK_Base; + Result.Parent = 0; Result.Base = reinterpret_cast<uintptr_t>(Base); if (IsInheritedVirtualBase) Result.Base |= 0x01; @@ -2377,7 +2495,8 @@ InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context, DeclarationName InitializedEntity::getName() const { switch (getKind()) { - case EK_Parameter: { + case EK_Parameter: + case EK_Parameter_CF_Audited: { ParmVarDecl *D = reinterpret_cast<ParmVarDecl*>(Parameter & ~0x1); return (D ? D->getDeclName() : DeclarationName()); } @@ -2387,7 +2506,7 @@ DeclarationName InitializedEntity::getName() const { return VariableOrMember->getDeclName(); case EK_LambdaCapture: - return Capture.Var->getDeclName(); + return DeclarationName(Capture.VarID); case EK_Result: case EK_Exception: @@ -2400,6 +2519,7 @@ DeclarationName InitializedEntity::getName() const { case EK_ComplexElement: case EK_BlockElement: case EK_CompoundLiteralInit: + case EK_RelatedResult: return DeclarationName(); } @@ -2413,6 +2533,7 @@ DeclaratorDecl *InitializedEntity::getDecl() const { return VariableOrMember; case EK_Parameter: + case EK_Parameter_CF_Audited: return reinterpret_cast<ParmVarDecl*>(Parameter & ~0x1); case EK_Result: @@ -2427,6 +2548,7 @@ DeclaratorDecl *InitializedEntity::getDecl() const { case EK_BlockElement: case EK_LambdaCapture: case EK_CompoundLiteralInit: + case EK_RelatedResult: return 0; } @@ -2441,6 +2563,7 @@ bool InitializedEntity::allowsNRVO() const { case EK_Variable: case EK_Parameter: + case EK_Parameter_CF_Audited: case EK_Member: case EK_New: case EK_Temporary: @@ -2452,12 +2575,57 @@ bool InitializedEntity::allowsNRVO() const { case EK_ComplexElement: case EK_BlockElement: case EK_LambdaCapture: + case EK_RelatedResult: break; } return false; } +unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const { + assert(getParent() != this); + unsigned Depth = getParent() ? getParent()->dumpImpl(OS) : 0; + for (unsigned I = 0; I != Depth; ++I) + OS << "`-"; + + switch (getKind()) { + case EK_Variable: OS << "Variable"; break; + case EK_Parameter: OS << "Parameter"; break; + case EK_Parameter_CF_Audited: OS << "CF audited function Parameter"; + break; + case EK_Result: OS << "Result"; break; + case EK_Exception: OS << "Exception"; break; + case EK_Member: OS << "Member"; break; + case EK_New: OS << "New"; break; + case EK_Temporary: OS << "Temporary"; break; + case EK_CompoundLiteralInit: OS << "CompoundLiteral";break; + case EK_RelatedResult: OS << "RelatedResult"; break; + case EK_Base: OS << "Base"; break; + case EK_Delegating: OS << "Delegating"; break; + case EK_ArrayElement: OS << "ArrayElement " << Index; break; + case EK_VectorElement: OS << "VectorElement " << Index; break; + case EK_ComplexElement: OS << "ComplexElement " << Index; break; + case EK_BlockElement: OS << "Block"; break; + case EK_LambdaCapture: + OS << "LambdaCapture "; + OS << DeclarationName(Capture.VarID); + break; + } + + if (Decl *D = getDecl()) { + OS << " "; + cast<NamedDecl>(D)->printQualifiedName(OS); + } + + OS << " '" << getType().getAsString() << "'\n"; + + return Depth + 1; +} + +void InitializedEntity::dump() const { + dumpImpl(llvm::errs()); +} + //===----------------------------------------------------------------------===// // Initialization sequence //===----------------------------------------------------------------------===// @@ -2496,6 +2664,7 @@ void InitializationSequence::Step::Destroy() { break; case SK_ConversionSequence: + case SK_ConversionSequenceNoNarrowing: delete ICS; } } @@ -2512,6 +2681,10 @@ bool InitializationSequence::isAmbiguous() const { case FK_TooManyInitsForReference: case FK_ArrayNeedsInitList: case FK_ArrayNeedsInitListOrStringLiteral: + case FK_ArrayNeedsInitListOrWideStringLiteral: + case FK_NarrowStringIntoWideCharArray: + case FK_WideStringIntoCharArray: + case FK_IncompatWideStringIntoWideChar: case FK_AddressOfOverloadFailed: // FIXME: Could do better case FK_NonConstLValueReferenceBindingToTemporary: case FK_NonConstLValueReferenceBindingToUnrelated: @@ -2530,7 +2703,6 @@ bool InitializationSequence::isAmbiguous() const { case FK_ListInitializationFailed: case FK_VariableLengthArrayHasInitializer: case FK_PlaceholderType: - case FK_InitListElementCopyFailure: case FK_ExplicitConstructor: return false; @@ -2632,10 +2804,11 @@ void InitializationSequence::AddLValueToRValueStep(QualType Ty) { } void InitializationSequence::AddConversionSequenceStep( - const ImplicitConversionSequence &ICS, - QualType T) { + const ImplicitConversionSequence &ICS, QualType T, + bool TopLevelOfInitList) { Step S; - S.Kind = SK_ConversionSequence; + S.Kind = TopLevelOfInitList ? SK_ConversionSequenceNoNarrowing + : SK_ConversionSequence; S.Type = T; S.ICS = new ImplicitConversionSequence(ICS); Steps.push_back(S); @@ -2777,7 +2950,7 @@ static void MaybeProduceObjCObject(Sema &S, /// When initializing a parameter, produce the value if it's marked /// __attribute__((ns_consumed)). - if (Entity.getKind() == InitializedEntity::EK_Parameter) { + if (Entity.isParameterKind()) { if (!Entity.isParameterConsumed()) return; @@ -2797,6 +2970,12 @@ static void MaybeProduceObjCObject(Sema &S, } } +static void TryListInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + InitListExpr *InitList, + InitializationSequence &Sequence); + /// \brief When initializing from init list via constructor, handle /// initialization of an object of type std::initializer_list<T>. /// @@ -2810,25 +2989,23 @@ static bool TryInitializerListConstruction(Sema &S, if (!S.isStdInitializerList(DestType, &E)) return false; - // 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; - } + if (S.RequireCompleteType(List->getExprLoc(), E, 0)) { + Sequence.setIncompleteTypeFailure(E); + return true; } - Sequence.AddStdInitializerListConstructionStep(DestType); + + // Try initializing a temporary array from the init list. + QualType ArrayType = S.Context.getConstantArrayType( + E.withConst(), llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()), + List->getNumInits()), + clang::ArrayType::Normal, 0); + InitializedEntity HiddenArray = + InitializedEntity::InitializeTemporary(ArrayType); + InitializationKind Kind = + InitializationKind::CreateDirectList(List->getExprLoc()); + TryListInitialization(S, HiddenArray, Kind, List, Sequence); + if (Sequence) + Sequence.AddStdInitializerListConstructionStep(DestType); return true; } @@ -2857,9 +3034,19 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, 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. + // C++11 [over.best.ics]p4: + // However, when considering the argument of a constructor or + // user-defined conversion function that is a candidate: + // -- by 13.3.1.3 when invoked for the copying/moving of a temporary + // in the second step of a class copy-initialization, + // -- by 13.3.1.7 when passing the initializer list as a single + // argument or when the initializer list has exactly one elementand + // a conversion to some class X or reference to (possibly + // cv-qualified) X is considered for the first parameter of a + // constructor of X, 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 considered. if ((CopyInitializing || (InitListSyntax && Args.size() == 1)) && Constructor->isCopyOrMoveConstructor()) SuppressUserConversions = true; @@ -3058,19 +3245,12 @@ static void TryValueInitialization(Sema &S, InitializationSequence &Sequence, InitListExpr *InitList = 0); -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) -{ + InitializationSequence &Sequence) { // First, catch C++03 where this isn't possible. if (!S.getLangOpts().CPlusPlus11) { Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList); @@ -3187,11 +3367,36 @@ static void TryListInitialization(Sema &S, return; } } + if (S.getLangOpts().CPlusPlus && !DestType->isAggregateType() && + InitList->getNumInits() == 1 && + InitList->getInit(0)->getType()->isRecordType()) { + // - Otherwise, if the initializer list has a single element of type E + // [...references are handled above...], the object or reference is + // initialized from that element; if a narrowing conversion is required + // to convert the element to T, the program is ill-formed. + // + // Per core-24034, this is direct-initialization if we were performing + // direct-list-initialization and copy-initialization otherwise. + // We can't use InitListChecker for this, because it always performs + // copy-initialization. This only matters if we might use an 'explicit' + // conversion operator, so we only need to handle the cases where the source + // is of record type. + InitializationKind SubKind = + Kind.getKind() == InitializationKind::IK_DirectList + ? InitializationKind::CreateDirect(Kind.getLocation(), + InitList->getLBraceLoc(), + InitList->getRBraceLoc()) + : Kind; + Expr *SubInit[1] = { InitList->getInit(0) }; + Sequence.InitializeFrom(S, Entity, SubKind, SubInit, + /*TopLevelOfInitList*/true); + if (Sequence) + Sequence.RewrapReferenceInitList(Entity.getType(), InitList); + return; + } InitListChecker CheckInitList(S, Entity, InitList, - DestType, /*VerifyOnly=*/true, - Kind.getKind() != InitializationKind::IK_DirectList || - !S.getLangOpts().CPlusPlus11); + DestType, /*VerifyOnly=*/true); if (CheckInitList.HadError()) { Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed); return; @@ -3235,8 +3440,8 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // Determine whether we are allowed to call explicit constructors or // explicit conversion operators. bool AllowExplicit = Kind.AllowExplicit(); - bool AllowExplicitConvs = Kind.allowExplicitConversionFunctions(); - + bool AllowExplicitConvs = Kind.allowExplicitConversionFunctionsInRefBinding(); + const RecordType *T1RecordType = 0; if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) && !S.RequireCompleteType(Kind.getLocation(), T1, 0)) { @@ -3249,7 +3454,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // be changed while iterating (e.g. because of deserialization). // To be safe we copy the lookup results to a new container. SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end()); - for (SmallVector<NamedDecl*, 16>::iterator + for (SmallVectorImpl<NamedDecl *>::iterator CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) { NamedDecl *D = *CI; DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); @@ -3503,7 +3708,7 @@ static void TryReferenceInitializationCore(Sema &S, // // - If the reference is an lvalue reference and the initializer // expression - // Note the analogous bullet points for rvlaue refs to functions. Because + // Note the analogous bullet points for rvalue refs to functions. Because // there are no function rvalues in C++, rvalue refs to functions are treated // like lvalue refs. OverloadingResult ConvOvlResult = OR_Success; @@ -3544,20 +3749,17 @@ static void TryReferenceInitializationCore(Sema &S, // applicable conversion functions (13.3.1.6) and choosing the best // one through overload resolution (13.3)), // If we have an rvalue ref to function type here, the rhs must be - // an rvalue. + // an rvalue. DR1287 removed the "implicitly" here. if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType() && (isLValueRef || InitCategory.isRValue())) { - ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, Kind, - Initializer, - /*AllowRValues=*/isRValueRef, - Sequence); + ConvOvlResult = TryRefInitWithConversionFunction( + S, Entity, Kind, Initializer, /*AllowRValues*/isRValueRef, Sequence); if (ConvOvlResult == OR_Success) return; - if (ConvOvlResult != OR_No_Viable_Function) { + if (ConvOvlResult != OR_No_Viable_Function) Sequence.SetOverloadFailure( - InitializationSequence::FK_ReferenceInitOverloadFailed, - ConvOvlResult); - } + InitializationSequence::FK_ReferenceInitOverloadFailed, + ConvOvlResult); } } @@ -3629,16 +3831,16 @@ static void TryReferenceInitializationCore(Sema &S, // reference-related to T2, and can be implicitly converted to an // xvalue, class prvalue, or function lvalue of type "cv3 T3", // where "cv1 T1" is reference-compatible with "cv3 T3", + // + // DR1287 removes the "implicitly" here. if (T2->isRecordType()) { if (RefRelationship == Sema::Ref_Incompatible) { - ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, - Kind, Initializer, - /*AllowRValues=*/true, - Sequence); + ConvOvlResult = TryRefInitWithConversionFunction( + S, Entity, Kind, Initializer, /*AllowRValues*/true, Sequence); if (ConvOvlResult) Sequence.SetOverloadFailure( - InitializationSequence::FK_ReferenceInitOverloadFailed, - ConvOvlResult); + InitializationSequence::FK_ReferenceInitOverloadFailed, + ConvOvlResult); return; } @@ -3657,19 +3859,17 @@ static void TryReferenceInitializationCore(Sema &S, // - Otherwise, a temporary of type "cv1 T1" is created and initialized // from the initializer expression using the rules for a non-reference - // copy initialization (8.5). The reference is then bound to the + // copy-initialization (8.5). The reference is then bound to the // temporary. [...] - // Determine whether we are allowed to call explicit constructors or - // explicit conversion operators. - bool AllowExplicit = Kind.AllowExplicit(); - InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1); + // FIXME: Why do we use an implicit conversion here rather than trying + // copy-initialization? ImplicitConversionSequence ICS = S.TryImplicitConversion(Initializer, TempEntity.getType(), - /*SuppressUserConversions*/ false, - AllowExplicit, + /*SuppressUserConversions=*/false, + /*AllowExplicit=*/false, /*FIXME:InOverloadResolution=*/false, /*CStyle=*/Kind.isCStyleOrFunctionalCast(), /*AllowObjCWritebackConversion=*/false); @@ -3848,7 +4048,8 @@ static void TryUserDefinedConversion(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, Expr *Initializer, - InitializationSequence &Sequence) { + InitializationSequence &Sequence, + bool TopLevelOfInitList) { QualType DestType = Entity.getType(); assert(!DestType->isReferenceType() && "References are handled elsewhere"); QualType SourceType = Initializer->getType(); @@ -3877,7 +4078,7 @@ static void TryUserDefinedConversion(Sema &S, // be changed while iterating. To be safe we copy the lookup results // to a new container. SmallVector<NamedDecl*, 8> CopyOfCon(R.begin(), R.end()); - for (SmallVector<NamedDecl*, 8>::iterator + for (SmallVectorImpl<NamedDecl *>::iterator Con = CopyOfCon.begin(), ConEnd = CopyOfCon.end(); Con != ConEnd; ++Con) { NamedDecl *D = *Con; @@ -3999,10 +4200,28 @@ static void TryUserDefinedConversion(Sema &S, ImplicitConversionSequence ICS; ICS.setStandard(); ICS.Standard = Best->FinalConversion; - Sequence.AddConversionSequenceStep(ICS, DestType); + Sequence.AddConversionSequenceStep(ICS, DestType, TopLevelOfInitList); } } +/// An egregious hack for compatibility with libstdc++-4.2: in <tr1/hashtable>, +/// a function with a pointer return type contains a 'return false;' statement. +/// In C++11, 'false' is not a null pointer, so this breaks the build of any +/// code using that header. +/// +/// Work around this by treating 'return false;' as zero-initializing the result +/// if it's used in a pointer-returning function in a system header. +static bool isLibstdcxxPointerReturnFalseHack(Sema &S, + const InitializedEntity &Entity, + const Expr *Init) { + return S.getLangOpts().CPlusPlus11 && + Entity.getKind() == InitializedEntity::EK_Result && + Entity.getType()->isPointerType() && + isa<CXXBoolLiteralExpr>(Init) && + !cast<CXXBoolLiteralExpr>(Init)->getValue() && + S.getSourceManager().isInSystemHeader(Init->getExprLoc()); +} + /// The non-zero enum values here are indexes into diagnostic alternatives. enum InvalidICRKind { IIK_okay, IIK_nonlocal, IIK_nonscalar }; @@ -4192,8 +4411,17 @@ static bool TryOCLZeroEventInitialization(Sema &S, InitializationSequence::InitializationSequence(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, - MultiExprArg Args) + MultiExprArg Args, + bool TopLevelOfInitList) : FailedCandidateSet(Kind.getLocation()) { + InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList); +} + +void InitializationSequence::InitializeFrom(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + MultiExprArg Args, + bool TopLevelOfInitList) { ASTContext &Context = S.Context; // Eliminate non-overload placeholder types in the arguments. We @@ -4283,9 +4511,23 @@ InitializationSequence::InitializationSequence(Sema &S, return; } - if (Initializer && IsStringInit(Initializer, DestAT, Context)) { - TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this); - return; + if (Initializer) { + switch (IsStringInit(Initializer, DestAT, Context)) { + case SIF_None: + TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this); + return; + case SIF_NarrowStringIntoWideChar: + SetFailed(FK_NarrowStringIntoWideCharArray); + return; + case SIF_WideStringIntoChar: + SetFailed(FK_WideStringIntoCharArray); + return; + case SIF_IncompatWideStringIntoWideChar: + SetFailed(FK_IncompatWideStringIntoWideChar); + return; + case SIF_Other: + break; + } } // Note: as an GNU C extension, we allow initialization of an @@ -4312,8 +4554,10 @@ InitializationSequence::InitializationSequence(Sema &S, TryListInitialization(S, Entity, Kind, cast<InitListExpr>(Initializer), *this); AddParenthesizedArrayInitStep(DestType); - } else if (DestAT->getElementType()->isAnyCharacterType()) + } else if (DestAT->getElementType()->isCharType()) SetFailed(FK_ArrayNeedsInitListOrStringLiteral); + else if (IsWideCharCompatible(DestAT->getElementType(), Context)) + SetFailed(FK_ArrayNeedsInitListOrWideStringLiteral); else SetFailed(FK_ArrayNeedsInitList); @@ -4323,7 +4567,7 @@ InitializationSequence::InitializationSequence(Sema &S, // Determine whether we should consider writeback conversions for // Objective-C ARC. bool allowObjCWritebackConversion = S.getLangOpts().ObjCAutoRefCount && - Entity.getKind() == InitializedEntity::EK_Parameter; + Entity.isParameterKind(); // 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. @@ -4367,7 +4611,8 @@ InitializationSequence::InitializationSequence(Sema &S, // 13.3.1.4, and the best one is chosen through overload resolution // (13.3). else - TryUserDefinedConversion(S, Entity, Kind, Initializer, *this); + TryUserDefinedConversion(S, Entity, Kind, Initializer, *this, + TopLevelOfInitList); return; } @@ -4380,7 +4625,8 @@ InitializationSequence::InitializationSequence(Sema &S, // - Otherwise, if the source type is a (possibly cv-qualified) class // type, conversion functions are considered. if (!SourceType.isNull() && SourceType->isRecordType()) { - TryUserDefinedConversion(S, Entity, Kind, Initializer, *this); + TryUserDefinedConversion(S, Entity, Kind, Initializer, *this, + TopLevelOfInitList); MaybeProduceObjCObject(S, *this, Entity); return; } @@ -4423,14 +4669,16 @@ InitializationSequence::InitializationSequence(Sema &S, AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy); } else if (ICS.isBad()) { DeclAccessPair dap; - if (Initializer->getType() == Context.OverloadTy && - !S.ResolveAddressOfOverloadedFunction(Initializer - , DestType, false, dap)) + if (isLibstdcxxPointerReturnFalseHack(S, Entity, Initializer)) { + AddZeroInitializationStep(Entity.getType()); + } else if (Initializer->getType() == Context.OverloadTy && + !S.ResolveAddressOfOverloadedFunction(Initializer, DestType, + false, dap)) SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); else SetFailed(InitializationSequence::FK_ConversionFailed); } else { - AddConversionSequenceStep(ICS, Entity.getType()); + AddConversionSequenceStep(ICS, Entity.getType(), TopLevelOfInitList); MaybeProduceObjCObject(S, *this, Entity); } @@ -4447,7 +4695,7 @@ InitializationSequence::~InitializationSequence() { // Perform initialization //===----------------------------------------------------------------------===// static Sema::AssignmentAction -getAssignmentAction(const InitializedEntity &Entity) { +getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) { switch(Entity.getKind()) { case InitializedEntity::EK_Variable: case InitializedEntity::EK_New: @@ -4463,10 +4711,18 @@ getAssignmentAction(const InitializedEntity &Entity) { return Sema::AA_Passing; + case InitializedEntity::EK_Parameter_CF_Audited: + if (Entity.getDecl() && + isa<ObjCMethodDecl>(Entity.getDecl()->getDeclContext())) + return Sema::AA_Sending; + + return !Diagnose ? Sema::AA_Passing : Sema::AA_Passing_CFAudited; + case InitializedEntity::EK_Result: return Sema::AA_Returning; case InitializedEntity::EK_Temporary: + case InitializedEntity::EK_RelatedResult: // FIXME: Can we tell apart casting vs. converting? return Sema::AA_Casting; @@ -4503,7 +4759,9 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) { return false; case InitializedEntity::EK_Parameter: + case InitializedEntity::EK_Parameter_CF_Audited: case InitializedEntity::EK_Temporary: + case InitializedEntity::EK_RelatedResult: return true; } @@ -4527,10 +4785,12 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_Member: case InitializedEntity::EK_Variable: case InitializedEntity::EK_Parameter: + case InitializedEntity::EK_Parameter_CF_Audited: case InitializedEntity::EK_Temporary: case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Exception: case InitializedEntity::EK_CompoundLiteralInit: + case InitializedEntity::EK_RelatedResult: return true; } @@ -4548,7 +4808,7 @@ static void LookupCopyAndMoveConstructors(Sema &S, // be changed while iterating (e.g. because of deserialization). // To be safe we copy the lookup results to a new container. SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end()); - for (SmallVector<NamedDecl*, 16>::iterator + for (SmallVectorImpl<NamedDecl *>::iterator CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) { NamedDecl *D = *CI; CXXConstructorDecl *Constructor = 0; @@ -4605,6 +4865,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity, case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Member: case InitializedEntity::EK_Parameter: + case InitializedEntity::EK_Parameter_CF_Audited: case InitializedEntity::EK_Temporary: case InitializedEntity::EK_New: case InitializedEntity::EK_Base: @@ -4613,6 +4874,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity, case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_CompoundLiteralInit: + case InitializedEntity::EK_RelatedResult: return Initializer->getLocStart(); } llvm_unreachable("missed an InitializedEntity kind?"); @@ -4823,7 +5085,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S, void InitializationSequence::PrintInitLocationNote(Sema &S, const InitializedEntity &Entity) { - if (Entity.getKind() == InitializedEntity::EK_Parameter && Entity.getDecl()) { + if (Entity.isParameterKind() && Entity.getDecl()) { if (Entity.getDecl()->getLocation().isInvalid()) return; @@ -4833,6 +5095,11 @@ void InitializationSequence::PrintInitLocationNote(Sema &S, else S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_here); } + else if (Entity.getKind() == InitializedEntity::EK_RelatedResult && + Entity.getMethodDecl()) + S.Diag(Entity.getMethodDecl()->getLocation(), + diag::note_method_return_type_change) + << Entity.getMethodDecl()->getDeclName(); } static bool isReferenceBinding(const InitializationSequence::Step &s) { @@ -4848,6 +5115,7 @@ static bool isExplicitTemporary(const InitializedEntity &Entity, switch (Entity.getKind()) { case InitializedEntity::EK_Temporary: case InitializedEntity::EK_CompoundLiteralInit: + case InitializedEntity::EK_RelatedResult: break; default: return false; @@ -4872,7 +5140,9 @@ PerformConstructorInitialization(Sema &S, MultiExprArg Args, const InitializationSequence::Step& Step, bool &ConstructorInitRequiresZeroInit, - bool IsListInitialization) { + bool IsListInitialization, + SourceLocation LBraceLoc, + SourceLocation RBraceLoc) { unsigned NumArgs = Args.size(); CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Step.Function.Function); @@ -4924,15 +5194,17 @@ PerformConstructorInitialization(Sema &S, TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); if (!TSInfo) TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc); - SourceRange ParenRange; - if (Kind.getKind() != InitializationKind::IK_DirectList) - ParenRange = Kind.getParenRange(); + SourceRange ParenOrBraceRange = + (Kind.getKind() == InitializationKind::IK_DirectList) + ? SourceRange(LBraceLoc, RBraceLoc) + : Kind.getParenRange(); CurInit = S.Owned( new (S.Context) CXXTemporaryObjectExpr(S.Context, Constructor, TSInfo, ConstructorArgs, - ParenRange, IsListInitialization, + ParenOrBraceRange, HadMultipleCandidates, + IsListInitialization, ConstructorInitRequiresZeroInit)); } else { CXXConstructExpr::ConstructionKind ConstructKind = @@ -4982,7 +5254,7 @@ PerformConstructorInitialization(Sema &S, return ExprError(); if (shouldBindAsTemporary(Entity)) - CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); + CurInit = S.MaybeBindToTemporary(CurInit.take()); return CurInit; } @@ -5015,9 +5287,11 @@ InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) { return false; case InitializedEntity::EK_Parameter: + case InitializedEntity::EK_Parameter_CF_Audited: case InitializedEntity::EK_Temporary: case InitializedEntity::EK_LambdaCapture: case InitializedEntity::EK_CompoundLiteralInit: + case InitializedEntity::EK_RelatedResult: // The entity being initialized might not outlive the full-expression. return false; } @@ -5025,6 +5299,220 @@ InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) { llvm_unreachable("unknown entity kind"); } +/// Determine the declaration which an initialized entity ultimately refers to, +/// for the purpose of lifetime-extending a temporary bound to a reference in +/// the initialization of \p Entity. +static const ValueDecl * +getDeclForTemporaryLifetimeExtension(const InitializedEntity &Entity, + const ValueDecl *FallbackDecl = 0) { + // C++11 [class.temporary]p5: + switch (Entity.getKind()) { + case InitializedEntity::EK_Variable: + // The temporary [...] persists for the lifetime of the reference + return Entity.getDecl(); + + case InitializedEntity::EK_Member: + // For subobjects, we look at the complete object. + if (Entity.getParent()) + return getDeclForTemporaryLifetimeExtension(*Entity.getParent(), + Entity.getDecl()); + + // except: + // -- A temporary bound to a reference member in a constructor's + // ctor-initializer persists until the constructor exits. + return Entity.getDecl(); + + case InitializedEntity::EK_Parameter: + case InitializedEntity::EK_Parameter_CF_Audited: + // -- A temporary bound to a reference parameter in a function call + // persists until the completion of the full-expression containing + // the call. + case InitializedEntity::EK_Result: + // -- The lifetime of a temporary bound to the returned value in a + // function return statement is not extended; the temporary is + // destroyed at the end of the full-expression in the return statement. + case InitializedEntity::EK_New: + // -- A temporary bound to a reference in a new-initializer persists + // until the completion of the full-expression containing the + // new-initializer. + return 0; + + case InitializedEntity::EK_Temporary: + case InitializedEntity::EK_CompoundLiteralInit: + case InitializedEntity::EK_RelatedResult: + // We don't yet know the storage duration of the surrounding temporary. + // Assume it's got full-expression duration for now, it will patch up our + // storage duration if that's not correct. + return 0; + + case InitializedEntity::EK_ArrayElement: + // For subobjects, we look at the complete object. + return getDeclForTemporaryLifetimeExtension(*Entity.getParent(), + FallbackDecl); + + case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: + // We can reach this case for aggregate initialization in a constructor: + // struct A { int &&r; }; + // struct B : A { B() : A{0} {} }; + // In this case, use the innermost field decl as the context. + return FallbackDecl; + + case InitializedEntity::EK_BlockElement: + case InitializedEntity::EK_LambdaCapture: + case InitializedEntity::EK_Exception: + case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_ComplexElement: + return 0; + } + llvm_unreachable("unknown entity kind"); +} + +static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD); + +/// Update a glvalue expression that is used as the initializer of a reference +/// to note that its lifetime is extended. +/// \return \c true if any temporary had its lifetime extended. +static bool performReferenceExtension(Expr *Init, const ValueDecl *ExtendingD) { + if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) { + if (ILE->getNumInits() == 1 && ILE->isGLValue()) { + // This is just redundant braces around an initializer. Step over it. + Init = ILE->getInit(0); + } + } + + // Walk past any constructs which we can lifetime-extend across. + Expr *Old; + do { + Old = Init; + + // Step over any subobject adjustments; we may have a materialized + // temporary inside them. + SmallVector<const Expr *, 2> CommaLHSs; + SmallVector<SubobjectAdjustment, 2> Adjustments; + Init = const_cast<Expr *>( + Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments)); + + // Per current approach for DR1376, look through casts to reference type + // when performing lifetime extension. + if (CastExpr *CE = dyn_cast<CastExpr>(Init)) + if (CE->getSubExpr()->isGLValue()) + Init = CE->getSubExpr(); + + // FIXME: Per DR1213, subscripting on an array temporary produces an xvalue. + // It's unclear if binding a reference to that xvalue extends the array + // temporary. + } while (Init != Old); + + if (MaterializeTemporaryExpr *ME = dyn_cast<MaterializeTemporaryExpr>(Init)) { + // Update the storage duration of the materialized temporary. + // FIXME: Rebuild the expression instead of mutating it. + ME->setExtendingDecl(ExtendingD); + performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingD); + return true; + } + + return false; +} + +/// Update a prvalue expression that is going to be materialized as a +/// lifetime-extended temporary. +static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) { + // Dig out the expression which constructs the extended temporary. + SmallVector<const Expr *, 2> CommaLHSs; + SmallVector<SubobjectAdjustment, 2> Adjustments; + Init = const_cast<Expr *>( + Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments)); + + if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init)) + Init = BTE->getSubExpr(); + + if (CXXStdInitializerListExpr *ILE = + dyn_cast<CXXStdInitializerListExpr>(Init)) { + performReferenceExtension(ILE->getSubExpr(), ExtendingD); + return; + } + + if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) { + if (ILE->getType()->isArrayType()) { + for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I) + performLifetimeExtension(ILE->getInit(I), ExtendingD); + return; + } + + if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) { + assert(RD->isAggregate() && "aggregate init on non-aggregate"); + + // If we lifetime-extend a braced initializer which is initializing an + // aggregate, and that aggregate contains reference members which are + // bound to temporaries, those temporaries are also lifetime-extended. + if (RD->isUnion() && ILE->getInitializedFieldInUnion() && + ILE->getInitializedFieldInUnion()->getType()->isReferenceType()) + performReferenceExtension(ILE->getInit(0), ExtendingD); + else { + unsigned Index = 0; + for (RecordDecl::field_iterator I = RD->field_begin(), + E = RD->field_end(); + I != E; ++I) { + if (Index >= ILE->getNumInits()) + break; + if (I->isUnnamedBitfield()) + continue; + Expr *SubInit = ILE->getInit(Index); + if (I->getType()->isReferenceType()) + performReferenceExtension(SubInit, ExtendingD); + else if (isa<InitListExpr>(SubInit) || + isa<CXXStdInitializerListExpr>(SubInit)) + // This may be either aggregate-initialization of a member or + // initialization of a std::initializer_list object. Either way, + // we should recursively lifetime-extend that initializer. + performLifetimeExtension(SubInit, ExtendingD); + ++Index; + } + } + } + } +} + +static void warnOnLifetimeExtension(Sema &S, const InitializedEntity &Entity, + const Expr *Init, bool IsInitializerList, + const ValueDecl *ExtendingDecl) { + // Warn if a field lifetime-extends a temporary. + if (isa<FieldDecl>(ExtendingDecl)) { + if (IsInitializerList) { + S.Diag(Init->getExprLoc(), diag::warn_dangling_std_initializer_list) + << /*at end of constructor*/true; + return; + } + + bool IsSubobjectMember = false; + for (const InitializedEntity *Ent = Entity.getParent(); Ent; + Ent = Ent->getParent()) { + if (Ent->getKind() != InitializedEntity::EK_Base) { + IsSubobjectMember = true; + break; + } + } + S.Diag(Init->getExprLoc(), + diag::warn_bind_ref_member_to_temporary) + << ExtendingDecl << Init->getSourceRange() + << IsSubobjectMember << IsInitializerList; + if (IsSubobjectMember) + S.Diag(ExtendingDecl->getLocation(), + diag::note_ref_subobject_of_member_declared_here); + else + S.Diag(ExtendingDecl->getLocation(), + diag::note_ref_or_ptr_member_declared_here) + << /*is pointer*/false; + } +} + +static void DiagnoseNarrowingInInitList(Sema &S, + const ImplicitConversionSequence &ICS, + QualType PreNarrowingType, + QualType EntityType, + const Expr *PostInit); + ExprResult InitializationSequence::Perform(Sema &S, const InitializedEntity &Entity, @@ -5094,7 +5582,7 @@ InitializationSequence::Perform(Sema &S, if (S.getLangOpts().CPlusPlus11 && Entity.getType()->isReferenceType() && Args.size() == 1 && isa<InitListExpr>(Args[0]) && - Entity.getKind() != InitializedEntity::EK_Parameter) { + !Entity.isParameterKind()) { // Produce a C++98 compatibility warning if we are initializing a reference // from an initializer list. For parameters, we produce a better warning // elsewhere. @@ -5142,6 +5630,7 @@ InitializationSequence::Perform(Sema &S, case SK_QualificationConversionRValue: case SK_LValueToRValue: case SK_ConversionSequence: + case SK_ConversionSequenceNoNarrowing: case SK_ListInitialization: case SK_UnwrapInitList: case SK_RewrapInitList: @@ -5260,9 +5749,19 @@ InitializationSequence::Perform(Sema &S, if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType)) return ExprError(); + // Even though we didn't materialize a temporary, the binding may still + // extend the lifetime of a temporary. This happens if we bind a reference + // to the result of a cast to reference type. + if (const ValueDecl *ExtendingDecl = + getDeclForTemporaryLifetimeExtension(Entity)) { + if (performReferenceExtension(CurInit.get(), ExtendingDecl)) + warnOnLifetimeExtension(S, Entity, CurInit.get(), false, + ExtendingDecl); + } + break; - case SK_BindReferenceToTemporary: + case SK_BindReferenceToTemporary: { // Make sure the "temporary" is actually an rvalue. assert(CurInit.get()->isRValue() && "not a temporary"); @@ -5270,19 +5769,33 @@ InitializationSequence::Perform(Sema &S, if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType)) return ExprError(); + // Maybe lifetime-extend the temporary's subobjects to match the + // entity's lifetime. + const ValueDecl *ExtendingDecl = + getDeclForTemporaryLifetimeExtension(Entity); + if (ExtendingDecl) { + performLifetimeExtension(CurInit.get(), ExtendingDecl); + warnOnLifetimeExtension(S, Entity, CurInit.get(), false, ExtendingDecl); + } + // Materialize the temporary into memory. - CurInit = new (S.Context) MaterializeTemporaryExpr( - Entity.getType().getNonReferenceType(), - CurInit.get(), - Entity.getType()->isLValueReferenceType()); + MaterializeTemporaryExpr *MTE = new (S.Context) MaterializeTemporaryExpr( + Entity.getType().getNonReferenceType(), CurInit.get(), + Entity.getType()->isLValueReferenceType(), ExtendingDecl); // If we're binding to an Objective-C object that has lifetime, we - // need cleanups. - if (S.getLangOpts().ObjCAutoRefCount && - CurInit.get()->getType()->isObjCLifetimeType()) + // need cleanups. Likewise if we're extending this temporary to automatic + // storage duration -- we need to register its cleanup during the + // full-expression's cleanups. + if ((S.getLangOpts().ObjCAutoRefCount && + MTE->getType()->isObjCLifetimeType()) || + (MTE->getStorageDuration() == SD_Automatic && + MTE->getType().isDestructedType())) S.ExprNeedsCleanups = true; - + + CurInit = S.Owned(MTE); break; + } case SK_ExtraneousCopyToTemporary: CurInit = CopyObject(S, Step->Type, Entity, CurInit, @@ -5416,8 +5929,9 @@ InitializationSequence::Perform(Sema &S, break; } - case SK_ConversionSequence: { - Sema::CheckedConversionKind CCK + case SK_ConversionSequence: + case SK_ConversionSequenceNoNarrowing: { + Sema::CheckedConversionKind CCK = Kind.isCStyleCast()? Sema::CCK_CStyleCast : Kind.isFunctionalCast()? Sema::CCK_FunctionalCast : Kind.isExplicitCast()? Sema::CCK_OtherCast @@ -5428,31 +5942,32 @@ InitializationSequence::Perform(Sema &S, if (CurInitExprRes.isInvalid()) return ExprError(); CurInit = CurInitExprRes; + + if (Step->Kind == SK_ConversionSequenceNoNarrowing && + S.getLangOpts().CPlusPlus && !CurInit.get()->isValueDependent()) + DiagnoseNarrowingInInitList(S, *Step->ICS, SourceType, Entity.getType(), + CurInit.get()); break; } case SK_ListInitialization: { InitListExpr *InitList = cast<InitListExpr>(CurInit.get()); - // 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(); + // If we're not initializing the top-level entity, we need to create an + // InitializeTemporary entity for our target type. + QualType Ty = Step->Type; + bool IsTemporary = !S.Context.hasSameType(Entity.getType(), Ty); InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(Ty); InitializedEntity InitEntity = IsTemporary ? TempEntity : Entity; InitListChecker PerformInitList(S, InitEntity, - InitList, Ty, /*VerifyOnly=*/false, - Kind.getKind() != InitializationKind::IK_DirectList || - !S.getLangOpts().CPlusPlus11); + InitList, Ty, /*VerifyOnly=*/false); if (PerformInitList.HadError()) return ExprError(); - if (ResultType) { + // Hack: We must update *ResultType if available in order to set the + // bounds of arrays, e.g. in 'int ar[] = {1, 2, 3};'. + // Worst case: 'const int (&arref)[] = {1, 2, 3};'. + if (ResultType && + ResultType->getNonReferenceType()->isIncompleteArrayType()) { if ((*ResultType)->isRValueReferenceType()) Ty = S.Context.getRValueReferenceType(Ty); else if ((*ResultType)->isLValueReferenceType()) @@ -5489,7 +6004,9 @@ InitializationSequence::Perform(Sema &S, Entity, Kind, Arg, *Step, ConstructorInitRequiresZeroInit, - /*IsListInitialization*/ true); + /*IsListInitialization*/ true, + InitList->getLBraceLoc(), + InitList->getRBraceLoc()); break; } @@ -5523,7 +6040,9 @@ InitializationSequence::Perform(Sema &S, : Entity, Kind, Args, *Step, ConstructorInitRequiresZeroInit, - /*IsListInitialization*/ false); + /*IsListInitialization*/ false, + /*LBraceLoc*/ SourceLocation(), + /*RBraceLoc*/ SourceLocation()); break; } @@ -5558,7 +6077,8 @@ InitializationSequence::Perform(Sema &S, QualType SourceType = CurInit.get()->getType(); ExprResult Result = CurInit; Sema::AssignConvertType ConvTy = - S.CheckSingleAssignmentConstraints(Step->Type, Result); + S.CheckSingleAssignmentConstraints(Step->Type, Result, true, + Entity.getKind() == InitializedEntity::EK_Parameter_CF_Audited); if (Result.isInvalid()) return ExprError(); CurInit = Result; @@ -5566,7 +6086,7 @@ InitializationSequence::Perform(Sema &S, // If this is a call, allow conversion to a transparent union. ExprResult CurInitExprRes = CurInit; if (ConvTy != Sema::Compatible && - Entity.getKind() == InitializedEntity::EK_Parameter && + Entity.isParameterKind() && S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExprRes) == Sema::Compatible) ConvTy = Sema::Compatible; @@ -5578,7 +6098,7 @@ InitializationSequence::Perform(Sema &S, if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(), Step->Type, SourceType, CurInit.get(), - getAssignmentAction(Entity), + getAssignmentAction(Entity, true), &Complained)) { PrintInitLocationNote(S, Entity); return ExprError(); @@ -5645,67 +6165,46 @@ InitializationSequence::Perform(Sema &S, break; case SK_StdInitializerList: { - QualType Dest = Step->Type; - QualType E; - bool Success = S.isStdInitializerList(Dest.getNonReferenceType(), &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); - if (S.DiagnoseUseOfDecl(Destructor, Kind.getLocation())) - return ExprError(); - } - } - } + S.Diag(CurInit.get()->getExprLoc(), + diag::warn_cxx98_compat_initializer_list_init) + << CurInit.get()->getSourceRange(); - InitListExpr *ILE = cast<InitListExpr>(CurInit.take()); - S.Diag(ILE->getExprLoc(), diag::warn_cxx98_compat_initializer_list_init) - << ILE->getSourceRange(); - 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, - /*TopLevelOfInitList=*/ true); - assert(!Res.isInvalid() && "Result changed since try phase."); - Converted[i] = Res.take(); + // Maybe lifetime-extend the array temporary's subobjects to match the + // entity's lifetime. + const ValueDecl *ExtendingDecl = + getDeclForTemporaryLifetimeExtension(Entity); + if (ExtendingDecl) { + performLifetimeExtension(CurInit.get(), ExtendingDecl); + warnOnLifetimeExtension(S, Entity, CurInit.get(), true, ExtendingDecl); } - InitListExpr *Semantic = new (S.Context) - InitListExpr(S.Context, ILE->getLBraceLoc(), - Converted, ILE->getRBraceLoc()); - Semantic->setSyntacticForm(ILE); - Semantic->setType(Dest); - Semantic->setInitializesStdInitializerList(); - CurInit = S.Owned(Semantic); + + // Materialize the temporary into memory. + MaterializeTemporaryExpr *MTE = new (S.Context) + MaterializeTemporaryExpr(CurInit.get()->getType(), CurInit.get(), + /*lvalue reference*/ false, ExtendingDecl); + + // Wrap it in a construction of a std::initializer_list<T>. + CurInit = S.Owned( + new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE)); + + // Bind the result, in case the library has given initializer_list a + // non-trivial destructor. + if (shouldBindAsTemporary(Entity)) + CurInit = S.MaybeBindToTemporary(CurInit.take()); break; } + case SK_OCLSamplerInit: { assert(Step->Type->isSamplerT() && "Sampler initialization on non sampler type."); QualType SourceType = CurInit.get()->getType(); - InitializedEntity::EntityKind EntityKind = Entity.getKind(); - if (EntityKind == InitializedEntity::EK_Parameter) { + if (Entity.isParameterKind()) { if (!SourceType->isSamplerT()) S.Diag(Kind.getLocation(), diag::err_sampler_argument_required) << SourceType; - } else if (EntityKind != InitializedEntity::EK_Variable) { + } else if (Entity.getKind() != InitializedEntity::EK_Variable) { llvm_unreachable("Invalid EntityKind!"); } @@ -5794,6 +6293,28 @@ static void emitBadConversionNotes(Sema &S, const InitializedEntity &entity, } } +static void diagnoseListInit(Sema &S, const InitializedEntity &Entity, + InitListExpr *InitList) { + QualType DestType = Entity.getType(); + + QualType E; + if (S.getLangOpts().CPlusPlus11 && S.isStdInitializerList(DestType, &E)) { + QualType ArrayType = S.Context.getConstantArrayType( + E.withConst(), + llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()), + InitList->getNumInits()), + clang::ArrayType::Normal, 0); + InitializedEntity HiddenArray = + InitializedEntity::InitializeTemporary(ArrayType); + return diagnoseListInit(S, HiddenArray, InitList); + } + + InitListChecker DiagnoseInitList(S, Entity, InitList, DestType, + /*VerifyOnly=*/false); + assert(DiagnoseInitList.HadError() && + "Inconsistent init list check result."); +} + bool InitializationSequence::Diagnose(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, @@ -5821,14 +6342,27 @@ bool InitializationSequence::Diagnose(Sema &S, break; case FK_ArrayNeedsInitList: + S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 0; + break; case FK_ArrayNeedsInitListOrStringLiteral: - S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) - << (Failure == FK_ArrayNeedsInitListOrStringLiteral); + S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 1; + break; + case FK_ArrayNeedsInitListOrWideStringLiteral: + S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 2; + break; + case FK_NarrowStringIntoWideCharArray: + S.Diag(Kind.getLocation(), diag::err_array_init_narrow_string_into_wchar); + break; + case FK_WideStringIntoCharArray: + S.Diag(Kind.getLocation(), diag::err_array_init_wide_string_into_char); + break; + case FK_IncompatWideStringIntoWideChar: + S.Diag(Kind.getLocation(), + diag::err_array_init_incompat_wide_string_into_wchar); break; - case FK_ArrayTypeMismatch: case FK_NonConstantArrayInit: - S.Diag(Kind.getLocation(), + S.Diag(Kind.getLocation(), (Failure == FK_ArrayTypeMismatch ? diag::err_array_init_different_type : diag::err_array_init_non_constant_array)) @@ -5868,9 +6402,14 @@ bool InitializationSequence::Diagnose(Sema &S, break; case OR_No_Viable_Function: - S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition) - << Args[0]->getType() << DestType.getNonReferenceType() - << Args[0]->getSourceRange(); + if (!S.RequireCompleteType(Kind.getLocation(), + DestType.getNonReferenceType(), + diag::err_typecheck_nonviable_condition_incomplete, + Args[0]->getType(), Args[0]->getSourceRange())) + S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition) + << Args[0]->getType() << Args[0]->getSourceRange() + << DestType.getNonReferenceType(); + FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args); break; @@ -6115,14 +6654,8 @@ bool InitializationSequence::Diagnose(Sema &S, case FK_ListInitializationFailed: { // Run the init list checker again to emit diagnostics. - InitListExpr* InitList = cast<InitListExpr>(Args[0]); - QualType DestType = Entity.getType(); - InitListChecker DiagnoseInitList(S, Entity, InitList, - DestType, /*VerifyOnly=*/false, - Kind.getKind() != InitializationKind::IK_DirectList || - !S.getLangOpts().CPlusPlus11); - assert(DiagnoseInitList.HadError() && - "Inconsistent init list check result."); + InitListExpr *InitList = cast<InitListExpr>(Args[0]); + diagnoseListInit(S, Entity, InitList); break; } @@ -6131,37 +6664,6 @@ bool InitializationSequence::Diagnose(Sema &S, 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.getNonReferenceType(), &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(); @@ -6197,6 +6699,22 @@ void InitializationSequence::dump(raw_ostream &OS) const { OS << "array requires initializer list or string literal"; break; + case FK_ArrayNeedsInitListOrWideStringLiteral: + OS << "array requires initializer list or wide string literal"; + break; + + case FK_NarrowStringIntoWideCharArray: + OS << "narrow string into wide char array"; + break; + + case FK_WideStringIntoCharArray: + OS << "wide string into char array"; + break; + + case FK_IncompatWideStringIntoWideChar: + OS << "incompatible wide string into wide char array"; + break; + case FK_ArrayTypeMismatch: OS << "array type mismatch"; break; @@ -6285,10 +6803,6 @@ void InitializationSequence::dump(raw_ostream &OS) const { 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; @@ -6362,7 +6876,13 @@ void InitializationSequence::dump(raw_ostream &OS) const { case SK_ConversionSequence: OS << "implicit conversion sequence ("; - S->ICS->DebugPrint(); // FIXME: use OS + S->ICS->dump(); // FIXME: use OS + OS << ")"; + break; + + case SK_ConversionSequenceNoNarrowing: + OS << "implicit conversion sequence with narrowing prohibited ("; + S->ICS->dump(); // FIXME: use OS OS << ")"; break; @@ -6445,20 +6965,11 @@ void InitializationSequence::dump() const { dump(llvm::errs()); } -static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq, +static void DiagnoseNarrowingInInitList(Sema &S, + const ImplicitConversionSequence &ICS, + QualType PreNarrowingType, 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: @@ -6473,13 +6984,6 @@ static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq, 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; @@ -6494,11 +6998,9 @@ static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq, // narrowing conversion even if the value is a constant and can be // represented exactly as an integer. S.Diag(PostInit->getLocStart(), - S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11? - diag::warn_init_list_type_narrowing - : S.isSFINAEContext()? - diag::err_init_list_type_narrowing_sfinae - : diag::err_init_list_type_narrowing) + (S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11) + ? diag::warn_init_list_type_narrowing + : diag::ext_init_list_type_narrowing) << PostInit->getSourceRange() << PreNarrowingType.getLocalUnqualifiedType() << EntityType.getLocalUnqualifiedType(); @@ -6507,11 +7009,9 @@ static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq, case NK_Constant_Narrowing: // A constant value was narrowed. S.Diag(PostInit->getLocStart(), - S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11? - diag::warn_init_list_constant_narrowing - : S.isSFINAEContext()? - diag::err_init_list_constant_narrowing_sfinae - : diag::err_init_list_constant_narrowing) + (S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11) + ? diag::warn_init_list_constant_narrowing + : diag::ext_init_list_constant_narrowing) << PostInit->getSourceRange() << ConstantValue.getAsString(S.getASTContext(), ConstantType) << EntityType.getLocalUnqualifiedType(); @@ -6520,11 +7020,9 @@ static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq, case NK_Variable_Narrowing: // A variable's value may have been narrowed. S.Diag(PostInit->getLocStart(), - S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11? - diag::warn_init_list_variable_narrowing - : S.isSFINAEContext()? - diag::err_init_list_variable_narrowing_sfinae - : diag::err_init_list_variable_narrowing) + (S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11) + ? diag::warn_init_list_variable_narrowing + : diag::ext_init_list_variable_narrowing) << PostInit->getSourceRange() << PreNarrowingType.getLocalUnqualifiedType() << EntityType.getLocalUnqualifiedType(); @@ -6592,14 +7090,10 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity, InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(), EqualLoc, AllowExplicit); - InitializationSequence Seq(*this, Entity, Kind, InitE); + InitializationSequence Seq(*this, Entity, Kind, InitE, TopLevelOfInitList); Init.release(); ExprResult Result = Seq.Perform(*this, Entity, Kind, InitE); - 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 index c7ba3cc822f3..a7d5b6526464 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp @@ -11,27 +11,163 @@ // //===----------------------------------------------------------------------===// #include "clang/Sema/DeclSpec.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/ExprCXX.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaLambda.h" +#include "TypeLocBuilder.h" using namespace clang; using namespace sema; +// returns -1 if none of the lambdas on the scope stack can capture. +// A lambda 'L' is capture-ready for a certain variable 'V' if, +// - its enclosing context is non-dependent +// - and if the chain of lambdas between L and the lambda in which +// V is potentially used, call all capture or have captured V. +static inline int GetScopeIndexOfNearestCaptureReadyLambda( + ArrayRef<clang::sema::FunctionScopeInfo*> FunctionScopes, + DeclContext *const CurContext, VarDecl *VD) { + + DeclContext *EnclosingDC = CurContext; + // If VD is null, we are attempting to capture 'this' + const bool IsCapturingThis = !VD; + const bool IsCapturingVariable = !IsCapturingThis; + int RetIndex = -1; + unsigned CurScopeIndex = FunctionScopes.size() - 1; + while (!EnclosingDC->isTranslationUnit() && + EnclosingDC->isDependentContext() && isLambdaCallOperator(EnclosingDC)) { + RetIndex = CurScopeIndex; + clang::sema::LambdaScopeInfo *LSI = + cast<sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex]); + // We have crawled up to an intervening lambda that contains the + // variable declaration - so not only does it not need to capture; + // none of the enclosing lambdas need to capture it, and since all + // other nested lambdas are dependent (otherwise we wouldn't have + // arrived here) - we don't yet have a lambda that can capture the + // variable. + if (IsCapturingVariable && VD->getDeclContext()->Equals(EnclosingDC)) + return -1; + // All intervening lambda call operators have to be able to capture. + // If they do not have a default implicit capture, check to see + // if the entity has already been explicitly captured. + // If even a single dependent enclosing lambda lacks the capability + // to ever capture this variable, there is no further enclosing + // non-dependent lambda that can capture this variable. + if (LSI->ImpCaptureStyle == sema::LambdaScopeInfo::ImpCap_None) { + if (IsCapturingVariable && !LSI->isCaptured(VD)) + return -1; + if (IsCapturingThis && !LSI->isCXXThisCaptured()) + return -1; + } + EnclosingDC = getLambdaAwareParentOfDeclContext(EnclosingDC); + --CurScopeIndex; + } + // If the enclosingDC is not dependent, then the immediately nested lambda + // is capture-ready. + if (!EnclosingDC->isDependentContext()) + return RetIndex; + return -1; +} +// Given a lambda's call operator and a variable (or null for 'this'), +// compute the nearest enclosing lambda that is capture-ready (i.e +// the enclosing context is not dependent, and all intervening lambdas can +// either implicitly or explicitly capture Var) +// +// The approach is as follows, for the entity VD ('this' if null): +// - start with the current lambda +// - if it is non-dependent and can capture VD, return it. +// - if it is dependent and has an implicit or explicit capture, check its parent +// whether the parent is non-depdendent and all its intervening lambdas +// can capture, if so return the child. +// [Note: When we hit a generic lambda specialization, do not climb up +// the scope stack any further since not only do we not need to, +// the scope stack will often not be synchronized with any lambdas +// enclosing the specialized generic lambda] +// +// Return the CallOperator of the capturable lambda and set function scope +// index to the correct index within the function scope stack to correspond +// to the capturable lambda. +// If VarDecl *VD is null, we check for 'this' capture. +CXXMethodDecl* clang::GetInnermostEnclosingCapturableLambda( + ArrayRef<sema::FunctionScopeInfo*> FunctionScopes, + unsigned &FunctionScopeIndex, + DeclContext *const CurContext, VarDecl *VD, + Sema &S) { + + const int IndexOfCaptureReadyLambda = + GetScopeIndexOfNearestCaptureReadyLambda(FunctionScopes,CurContext, VD); + if (IndexOfCaptureReadyLambda == -1) return 0; + assert(IndexOfCaptureReadyLambda >= 0); + const unsigned IndexOfCaptureReadyLambdaU = + static_cast<unsigned>(IndexOfCaptureReadyLambda); + sema::LambdaScopeInfo *const CaptureReadyLambdaLSI = + cast<sema::LambdaScopeInfo>(FunctionScopes[IndexOfCaptureReadyLambdaU]); + // If VD is null, we are attempting to capture 'this' + const bool IsCapturingThis = !VD; + const bool IsCapturingVariable = !IsCapturingThis; + + if (IsCapturingVariable) { + // Now check to see if this lambda can truly capture, and also + // if all enclosing lambdas of this lambda allow this capture. + QualType CaptureType, DeclRefType; + const bool CanCaptureVariable = !S.tryCaptureVariable(VD, + /*ExprVarIsUsedInLoc*/SourceLocation(), clang::Sema::TryCapture_Implicit, + /*EllipsisLoc*/ SourceLocation(), + /*BuildAndDiagnose*/false, CaptureType, DeclRefType, + &IndexOfCaptureReadyLambdaU); + if (!CanCaptureVariable) return 0; + } else { + const bool CanCaptureThis = !S.CheckCXXThisCapture( + CaptureReadyLambdaLSI->PotentialThisCaptureLocation, false, false, + &IndexOfCaptureReadyLambdaU); + if (!CanCaptureThis) return 0; + } // end 'this' capture test + FunctionScopeIndex = IndexOfCaptureReadyLambdaU; + return CaptureReadyLambdaLSI->CallOperator; +} + +static inline TemplateParameterList * +getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) { + if (LSI->GLTemplateParameterList) + return LSI->GLTemplateParameterList; + + if (LSI->AutoTemplateParams.size()) { + SourceRange IntroRange = LSI->IntroducerRange; + SourceLocation LAngleLoc = IntroRange.getBegin(); + SourceLocation RAngleLoc = IntroRange.getEnd(); + LSI->GLTemplateParameterList = TemplateParameterList::Create( + SemaRef.Context, + /*Template kw loc*/SourceLocation(), + LAngleLoc, + (NamedDecl**)LSI->AutoTemplateParams.data(), + LSI->AutoTemplateParams.size(), RAngleLoc); + } + return LSI->GLTemplateParameterList; +} + + + CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange, TypeSourceInfo *Info, - bool KnownDependent) { + bool KnownDependent, + LambdaCaptureDefault CaptureDefault) { DeclContext *DC = CurContext; while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext())) DC = DC->getParent(); - + bool IsGenericLambda = getGenericLambdaTemplateParameterList(getCurLambda(), + *this); // Start constructing the lambda class. CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, Info, IntroducerRange.getBegin(), - KnownDependent); + KnownDependent, + IsGenericLambda, + CaptureDefault); DC->addDecl(Class); return Class; @@ -51,55 +187,12 @@ static bool isInInlineFunction(const DeclContext *DC) { return false; } -CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, - SourceRange IntroducerRange, - TypeSourceInfo *MethodType, - SourceLocation EndLoc, - ArrayRef<ParmVarDecl *> Params) { - // 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, - 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); - } - - // Allocate a mangling number for this lambda expression, if the ABI - // requires one. - Decl *ContextDecl = ExprEvalContexts.back().LambdaContextDecl; +MangleNumberingContext * +Sema::getCurrentMangleNumberContext(const DeclContext *DC, + Decl *&ManglingContextDecl) { + // Compute the context for allocating mangling numbers in the current + // expression, if the ABI requires them. + ManglingContextDecl = ExprEvalContexts.back().ManglingContextDecl; enum ContextKind { Normal, @@ -111,16 +204,16 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, // 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 (ManglingContextDecl) { + if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ManglingContextDecl)) { if (const DeclContext *LexicalDC = Param->getDeclContext()->getLexicalParent()) if (LexicalDC->isRecord()) Kind = DefaultArgument; - } else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) { + } else if (VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl)) { if (Var->getDeclContext()->isRecord()) Kind = StaticDataMember; - } else if (isa<FieldDecl>(ContextDecl)) { + } else if (isa<FieldDecl>(ManglingContextDecl)) { Kind = DataMember; } } @@ -130,57 +223,147 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, // types in different translation units to "correspond": bool IsInNonspecializedTemplate = !ActiveTemplateInstantiations.empty() || CurContext->isDependentContext(); - unsigned ManglingNumber; switch (Kind) { case Normal: // -- the bodies of non-exported nonspecialized template functions // -- the bodies of inline functions if ((IsInNonspecializedTemplate && - !(ContextDecl && isa<ParmVarDecl>(ContextDecl))) || - isInInlineFunction(CurContext)) - ManglingNumber = Context.getLambdaManglingNumber(Method); - else - ManglingNumber = 0; + !(ManglingContextDecl && isa<ParmVarDecl>(ManglingContextDecl))) || + isInInlineFunction(CurContext)) { + ManglingContextDecl = 0; + return &Context.getManglingNumberContext(DC); + } - // There is no special context for this lambda. - ContextDecl = 0; - break; + ManglingContextDecl = 0; + return 0; case StaticDataMember: // -- the initializers of nonspecialized static members of template classes if (!IsInNonspecializedTemplate) { - ManglingNumber = 0; - ContextDecl = 0; - break; + ManglingContextDecl = 0; + return 0; } - // Fall through to assign a mangling number. + // Fall through to get the current context. case DataMember: // -- the in-class initializers of class members case DefaultArgument: // -- default arguments appearing in class definitions - ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext() - .getManglingNumber(Method); - break; + return &ExprEvalContexts.back().getMangleNumberingContext(Context); } - Class->setLambdaMangling(ManglingNumber, ContextDecl); + llvm_unreachable("unexpected context"); +} + +MangleNumberingContext & +Sema::ExpressionEvaluationContextRecord::getMangleNumberingContext( + ASTContext &Ctx) { + assert(ManglingContextDecl && "Need to have a context declaration"); + if (!MangleNumbering) + MangleNumbering = Ctx.createMangleNumberingContext(); + return *MangleNumbering; +} + +CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, + SourceRange IntroducerRange, + TypeSourceInfo *MethodTypeInfo, + SourceLocation EndLoc, + ArrayRef<ParmVarDecl *> Params) { + QualType MethodType = MethodTypeInfo->getType(); + TemplateParameterList *TemplateParams = + getGenericLambdaTemplateParameterList(getCurLambda(), *this); + // If a lambda appears in a dependent context or is a generic lambda (has + // template parameters) and has an 'auto' return type, deduce it to a + // dependent type. + if (Class->isDependentContext() || TemplateParams) { + const FunctionProtoType *FPT = MethodType->castAs<FunctionProtoType>(); + QualType Result = FPT->getResultType(); + if (Result->isUndeducedType()) { + Result = SubstAutoType(Result, Context.DependentTy); + MethodType = Context.getFunctionType(Result, FPT->getArgTypes(), + FPT->getExtProtoInfo()); + } + } + + // 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, MethodTypeInfo, + 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); + // Create a function template if we have a template parameter list + FunctionTemplateDecl *const TemplateMethod = TemplateParams ? + FunctionTemplateDecl::Create(Context, Class, + Method->getLocation(), MethodName, + TemplateParams, + Method) : 0; + if (TemplateMethod) { + TemplateMethod->setLexicalDeclContext(CurContext); + TemplateMethod->setAccess(AS_public); + Method->setDescribedFunctionTemplate(TemplateMethod); + } + + // 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); + } + + Decl *ManglingContextDecl; + if (MangleNumberingContext *MCtx = + getCurrentMangleNumberContext(Class->getDeclContext(), + ManglingContextDecl)) { + unsigned ManglingNumber = MCtx->getManglingNumber(Method); + Class->setLambdaMangling(ManglingNumber, ManglingContextDecl); + } return Method; } -LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator, +void Sema::buildLambdaScope(LambdaScopeInfo *LSI, + CXXMethodDecl *CallOperator, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, + SourceLocation CaptureDefaultLoc, bool ExplicitParams, bool ExplicitResultType, bool Mutable) { - PushLambdaScope(CallOperator->getParent(), CallOperator); - LambdaScopeInfo *LSI = getCurLambda(); + LSI->CallOperator = CallOperator; + CXXRecordDecl *LambdaClass = CallOperator->getParent(); + LSI->Lambda = LambdaClass; if (CaptureDefault == LCD_ByCopy) LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval; else if (CaptureDefault == LCD_ByRef) LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref; + LSI->CaptureDefaultLoc = CaptureDefaultLoc; LSI->IntroducerRange = IntroducerRange; LSI->ExplicitParams = ExplicitParams; LSI->Mutable = Mutable; @@ -193,16 +376,11 @@ LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator, 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) { @@ -275,11 +453,12 @@ static EnumDecl *findEnumForBlockReturn(Expr *E) { // - it is an implicit integral conversion applied to an // enumerator-like expression of type T or if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { - // We can only see integral conversions in valid enumerator-like - // expressions. + // We can sometimes see integral conversions in valid + // enumerator-like expressions. if (ICE->getCastKind() == CK_IntegralCast) return findEnumForBlockReturn(ICE->getSubExpr()); - return 0; + + // Otherwise, just rely on the type. } // - it is an expression of that formal enum type. @@ -351,6 +530,8 @@ static void adjustBlockReturnsToEnum(Sema &S, ArrayRef<ReturnStmt*> returns, void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { assert(CSI.HasImplicitReturnType); + // If it was ever a placeholder, it had to been deduced to DependentTy. + assert(CSI.ReturnType.isNull() || !CSI.ReturnType->isUndeducedType()); // C++ Core Issue #975, proposed resolution: // If a lambda-expression does not include a trailing-return-type, @@ -428,16 +609,160 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { } } +QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc, + bool ByRef, + IdentifierInfo *Id, + Expr *&Init) { + + // We do not need to distinguish between direct-list-initialization + // and copy-list-initialization here, because we will always deduce + // std::initializer_list<T>, and direct- and copy-list-initialization + // always behave the same for such a type. + // FIXME: We should model whether an '=' was present. + const bool IsDirectInit = isa<ParenListExpr>(Init) || isa<InitListExpr>(Init); + + // Create an 'auto' or 'auto&' TypeSourceInfo that we can use to + // deduce against. + QualType DeductType = Context.getAutoDeductType(); + TypeLocBuilder TLB; + TLB.pushTypeSpec(DeductType).setNameLoc(Loc); + if (ByRef) { + DeductType = BuildReferenceType(DeductType, true, Loc, Id); + assert(!DeductType.isNull() && "can't build reference to auto"); + TLB.push<ReferenceTypeLoc>(DeductType).setSigilLoc(Loc); + } + TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType); + + // Are we a non-list direct initialization? + ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); + + 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) { + Diag(CXXDirectInit->getLocStart(), diag::err_init_capture_no_expression) + << DeclarationName(Id) << TSI->getType() << Loc; + return QualType(); + } else if (CXXDirectInit->getNumExprs() > 1) { + Diag(CXXDirectInit->getExpr(1)->getLocStart(), + diag::err_init_capture_multiple_expressions) + << DeclarationName(Id) << TSI->getType() << Loc; + return QualType(); + } else { + DeduceInit = CXXDirectInit->getExpr(0); + } + } + + // Now deduce against the initialization expression and store the deduced + // type below. + QualType DeducedType; + if (DeduceAutoType(TSI, DeduceInit, DeducedType) == DAR_Failed) { + if (isa<InitListExpr>(Init)) + Diag(Loc, diag::err_init_capture_deduction_failure_from_init_list) + << DeclarationName(Id) + << (DeduceInit->getType().isNull() ? TSI->getType() + : DeduceInit->getType()) + << DeduceInit->getSourceRange(); + else + Diag(Loc, diag::err_init_capture_deduction_failure) + << DeclarationName(Id) << TSI->getType() + << (DeduceInit->getType().isNull() ? TSI->getType() + : DeduceInit->getType()) + << DeduceInit->getSourceRange(); + } + if (DeducedType.isNull()) + return QualType(); + + // Perform initialization analysis and ensure any implicit conversions + // (such as lvalue-to-rvalue) are enforced. + InitializedEntity Entity = + InitializedEntity::InitializeLambdaCapture(Id, DeducedType, Loc); + InitializationKind Kind = + IsDirectInit + ? (CXXDirectInit ? InitializationKind::CreateDirect( + Loc, Init->getLocStart(), Init->getLocEnd()) + : InitializationKind::CreateDirectList(Loc)) + : InitializationKind::CreateCopy(Loc, Init->getLocStart()); + + MultiExprArg Args = Init; + if (CXXDirectInit) + Args = + MultiExprArg(CXXDirectInit->getExprs(), CXXDirectInit->getNumExprs()); + QualType DclT; + InitializationSequence InitSeq(*this, Entity, Kind, Args); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT); + + if (Result.isInvalid()) + return QualType(); + Init = Result.takeAs<Expr>(); + + // The init-capture initialization is a full-expression that must be + // processed as one before we enter the declcontext of the lambda's + // call-operator. + Result = ActOnFinishFullExpr(Init, Loc, /*DiscardedValue*/ false, + /*IsConstexpr*/ false, + /*IsLambdaInitCaptureInitalizer*/ true); + if (Result.isInvalid()) + return QualType(); + + Init = Result.takeAs<Expr>(); + return DeducedType; +} + +VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc, + QualType InitCaptureType, IdentifierInfo *Id, Expr *Init) { + + TypeSourceInfo *TSI = Context.getTrivialTypeSourceInfo(InitCaptureType, + Loc); + // Create a dummy variable representing the init-capture. This is not actually + // used as a variable, and only exists as a way to name and refer to the + // init-capture. + // FIXME: Pass in separate source locations for '&' and identifier. + VarDecl *NewVD = VarDecl::Create(Context, CurContext, Loc, + Loc, Id, InitCaptureType, TSI, SC_Auto); + NewVD->setInitCapture(true); + NewVD->setReferenced(true); + NewVD->markUsed(Context); + NewVD->setInit(Init); + return NewVD; + +} + +FieldDecl *Sema::buildInitCaptureField(LambdaScopeInfo *LSI, VarDecl *Var) { + FieldDecl *Field = FieldDecl::Create( + Context, LSI->Lambda, Var->getLocation(), Var->getLocation(), + 0, Var->getType(), Var->getTypeSourceInfo(), 0, false, ICIS_NoInit); + Field->setImplicit(true); + Field->setAccess(AS_private); + LSI->Lambda->addDecl(Field); + + LSI->addCapture(Var, /*isBlock*/false, Var->getType()->isReferenceType(), + /*isNested*/false, Var->getLocation(), SourceLocation(), + Var->getType(), Var->getInit()); + return Field; +} + void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, - Declarator &ParamInfo, - Scope *CurScope) { + 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()) + LambdaScopeInfo *const LSI = getCurLambda(); + assert(LSI && "LambdaScopeInfo should be on stack!"); + TemplateParameterList *TemplateParams = + getGenericLambdaTemplateParameterList(LSI, *this); + + if (Scope *TmplScope = CurScope->getTemplateParamParent()) { + // Since we have our own TemplateParams, so check if an outer scope + // has template params, only then are we in a dependent scope. + if (TemplateParams) { + TmplScope = TmplScope->getParent(); + TmplScope = TmplScope ? TmplScope->getTemplateParamParent() : 0; + } + if (TmplScope && !TmplScope->decl_empty()) KnownDependent = true; - + } // Determine the signature of the call operator. TypeSourceInfo *MethodTyInfo; bool ExplicitParams = true; @@ -449,11 +774,21 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // 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; + FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention( + /*IsVariadic=*/false, /*IsCXXMethod=*/true)); EPI.HasTrailingReturn = true; EPI.TypeQuals |= DeclSpec::TQ_const; - QualType MethodTy = Context.getFunctionType(Context.DependentTy, None, - EPI); + // C++1y [expr.prim.lambda]: + // The lambda return type is 'auto', which is replaced by the + // trailing-return type if provided and/or deduced from 'return' + // statements + // We don't do this before C++1y, because we don't support deduced return + // types there. + QualType DefaultTypeForNoTrailingReturn = + getLangOpts().CPlusPlus1y ? Context.getAutoDeductType() + : Context.DependentTy; + QualType MethodTy = + Context.getFunctionType(DefaultTypeForNoTrailingReturn, None, EPI); MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy); ExplicitParams = false; ExplicitResultType = false; @@ -462,21 +797,19 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, 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; + + ExplicitResultType = FTI.hasTrailingReturnType(); if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) { @@ -494,11 +827,10 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, } CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo, - KnownDependent); + KnownDependent, Intro.Default); CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params); - if (ExplicitParams) CheckCXXDefaultArguments(Method); @@ -508,19 +840,24 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // 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, + // Build the lambda scope. + buildLambdaScope(LSI, Method, + Intro.Range, + Intro.Default, Intro.DefaultLoc, + ExplicitParams, ExplicitResultType, !Method->isConst()); - + + // Distinct capture names, for diagnostics. + llvm::SmallSet<IdentifierInfo*, 8> CaptureNames; + // Handle explicit captures. SourceLocation PrevCaptureLoc = Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc; - for (SmallVector<LambdaCapture, 4>::const_iterator - C = Intro.Captures.begin(), - E = Intro.Captures.end(); - C != E; + for (SmallVectorImpl<LambdaCapture>::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: @@ -560,44 +897,89 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, 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)); + if (C->Init.isInvalid()) continue; + + VarDecl *Var = 0; + if (C->Init.isUsable()) { + Diag(C->Loc, getLangOpts().CPlusPlus1y + ? diag::warn_cxx11_compat_init_capture + : diag::ext_init_capture); + + if (C->Init.get()->containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; + // If the initializer expression is usable, but the InitCaptureType + // is not, then an error has occurred - so ignore the capture for now. + // for e.g., [n{0}] { }; <-- if no <initializer_list> is included. + // FIXME: we should create the init capture variable and mark it invalid + // in this case. + if (C->InitCaptureType.get().isNull()) + continue; + Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(), + C->Id, C->Init.take()); + // C++1y [expr.prim.lambda]p11: + // An init-capture behaves as if it declares and explicitly + // captures a variable [...] whose declarative region is the + // lambda-expression's compound-statement + if (Var) + PushOnScopeChains(Var, CurScope, false); + } else { + // 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; + } + + // 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) + 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; + } + + Var = R.getAsSingle<VarDecl>(); } - DeclarationNameInfo Name(C->Id, C->Loc); - LookupResult R(*this, Name, LookupOrdinaryName); - LookupName(R, CurScope); - if (R.isAmbiguous()) + // C++11 [expr.prim.lambda]p8: + // An identifier or this shall not appear more than once in a + // lambda-capture. + if (!CaptureNames.insert(C->Id)) { + if (Var && LSI->isCaptured(Var)) { + Diag(C->Loc, diag::err_capture_more_than_once) + << C->Id << SourceRange(LSI->getCapture(Var).getLocation()) + << FixItHint::CreateRemoval( + SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc)); + } else + // Previous capture captured something different (one or both was + // an init-cpature): no fixit. + Diag(C->Loc, diag::err_capture_more_than_once) << C->Id; 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. - // + // [...] 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; @@ -613,18 +995,6 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, 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; @@ -640,10 +1010,14 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, } else if (Var->isParameterPack()) { ContainsUnexpandedParameterPack = true; } - - TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef : - TryCapture_ExplicitByVal; - tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc); + + if (C->Init.isUsable()) { + buildInitCaptureField(LSI, Var); + } else { + TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef : + TryCapture_ExplicitByVal; + tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc); + } } finishLambdaExplicitCaptures(LSI); @@ -689,72 +1063,173 @@ static void addFunctionPointerConversion(Sema &S, CXXRecordDecl *Class, CXXMethodDecl *CallOperator) { // Add the conversion to function pointer. - const FunctionProtoType *Proto - = CallOperator->getType()->getAs<FunctionProtoType>(); - QualType FunctionPtrTy; - QualType FunctionTy; + const FunctionProtoType *CallOpProto = + CallOperator->getType()->getAs<FunctionProtoType>(); + const FunctionProtoType::ExtProtoInfo CallOpExtInfo = + CallOpProto->getExtProtoInfo(); + QualType PtrToFunctionTy; + QualType InvokerFunctionTy; { - FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo(); - ExtInfo.TypeQuals = 0; - FunctionTy = - S.Context.getFunctionType(Proto->getResultType(), - ArrayRef<QualType>(Proto->arg_type_begin(), - Proto->getNumArgs()), - ExtInfo); - FunctionPtrTy = S.Context.getPointerType(FunctionTy); + FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo; + CallingConv CC = S.Context.getDefaultCallingConvention( + CallOpProto->isVariadic(), /*IsCXXMethod=*/false); + InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC); + InvokerExtInfo.TypeQuals = 0; + assert(InvokerExtInfo.RefQualifier == RQ_None && + "Lambda's call operator should not have a reference qualifier"); + InvokerFunctionTy = S.Context.getFunctionType(CallOpProto->getResultType(), + CallOpProto->getArgTypes(), InvokerExtInfo); + PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy); } - - FunctionProtoType::ExtProtoInfo ExtInfo; - ExtInfo.TypeQuals = Qualifiers::Const; - QualType ConvTy = - S.Context.getFunctionType(FunctionPtrTy, None, ExtInfo); - + + // Create the type of the conversion function. + FunctionProtoType::ExtProtoInfo ConvExtInfo( + S.Context.getDefaultCallingConvention( + /*IsVariadic=*/false, /*IsCXXMethod=*/true)); + // The conversion function is always const. + ConvExtInfo.TypeQuals = Qualifiers::Const; + QualType ConvTy = + S.Context.getFunctionType(PtrToFunctionTy, None, ConvExtInfo); + SourceLocation Loc = IntroducerRange.getBegin(); - DeclarationName Name + DeclarationName ConversionName = S.Context.DeclarationNames.getCXXConversionFunctionName( - S.Context.getCanonicalType(FunctionPtrTy)); - DeclarationNameLoc NameLoc; - NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(FunctionPtrTy, - Loc); + S.Context.getCanonicalType(PtrToFunctionTy)); + DeclarationNameLoc ConvNameLoc; + // Construct a TypeSourceInfo for the conversion function, and wire + // all the parameters appropriately for the FunctionProtoTypeLoc + // so that everything works during transformation/instantiation of + // generic lambdas. + // The main reason for wiring up the parameters of the conversion + // function with that of the call operator is so that constructs + // like the following work: + // auto L = [](auto b) { <-- 1 + // return [](auto a) -> decltype(a) { <-- 2 + // return a; + // }; + // }; + // int (*fp)(int) = L(5); + // Because the trailing return type can contain DeclRefExprs that refer + // to the original call operator's variables, we hijack the call + // operators ParmVarDecls below. + TypeSourceInfo *ConvNamePtrToFunctionTSI = + S.Context.getTrivialTypeSourceInfo(PtrToFunctionTy, Loc); + ConvNameLoc.NamedType.TInfo = ConvNamePtrToFunctionTSI; + + // The conversion function is a conversion to a pointer-to-function. + TypeSourceInfo *ConvTSI = S.Context.getTrivialTypeSourceInfo(ConvTy, Loc); + FunctionProtoTypeLoc ConvTL = + ConvTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>(); + // Get the result of the conversion function which is a pointer-to-function. + PointerTypeLoc PtrToFunctionTL = + ConvTL.getResultLoc().getAs<PointerTypeLoc>(); + // Do the same for the TypeSourceInfo that is used to name the conversion + // operator. + PointerTypeLoc ConvNamePtrToFunctionTL = + ConvNamePtrToFunctionTSI->getTypeLoc().getAs<PointerTypeLoc>(); + + // Get the underlying function types that the conversion function will + // be converting to (should match the type of the call operator). + FunctionProtoTypeLoc CallOpConvTL = + PtrToFunctionTL.getPointeeLoc().getAs<FunctionProtoTypeLoc>(); + FunctionProtoTypeLoc CallOpConvNameTL = + ConvNamePtrToFunctionTL.getPointeeLoc().getAs<FunctionProtoTypeLoc>(); + + // Wire up the FunctionProtoTypeLocs with the call operator's parameters. + // These parameter's are essentially used to transform the name and + // the type of the conversion operator. By using the same parameters + // as the call operator's we don't have to fix any back references that + // the trailing return type of the call operator's uses (such as + // decltype(some_type<decltype(a)>::type{} + decltype(a){}) etc.) + // - we can simply use the return type of the call operator, and + // everything should work. + SmallVector<ParmVarDecl *, 4> InvokerParams; + for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) { + ParmVarDecl *From = CallOperator->getParamDecl(I); + + InvokerParams.push_back(ParmVarDecl::Create(S.Context, + // Temporarily add to the TU. This is set to the invoker below. + S.Context.getTranslationUnitDecl(), + From->getLocStart(), + From->getLocation(), + From->getIdentifier(), + From->getType(), + From->getTypeSourceInfo(), + From->getStorageClass(), + /*DefaultArg=*/0)); + CallOpConvTL.setArg(I, From); + CallOpConvNameTL.setArg(I, From); + } + CXXConversionDecl *Conversion = CXXConversionDecl::Create(S.Context, Class, Loc, - DeclarationNameInfo(Name, Loc, NameLoc), + DeclarationNameInfo(ConversionName, + Loc, ConvNameLoc), ConvTy, - S.Context.getTrivialTypeSourceInfo(ConvTy, - Loc), - /*isInline=*/false, /*isExplicit=*/false, + ConvTSI, + /*isInline=*/true, /*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"); + + if (Class->isGenericLambda()) { + // Create a template version of the conversion operator, using the template + // parameter list of the function call operator. + FunctionTemplateDecl *TemplateCallOperator = + CallOperator->getDescribedFunctionTemplate(); + FunctionTemplateDecl *ConversionTemplate = + FunctionTemplateDecl::Create(S.Context, Class, + Loc, ConversionName, + TemplateCallOperator->getTemplateParameters(), + Conversion); + ConversionTemplate->setAccess(AS_public); + ConversionTemplate->setImplicit(true); + Conversion->setDescribedFunctionTemplate(ConversionTemplate); + Class->addDecl(ConversionTemplate); + } else + Class->addDecl(Conversion); + // Add a non-static member function that will be the result of + // the conversion with a certain unique ID. + DeclarationName InvokerName = &S.Context.Idents.get( + getLambdaStaticInvokerName()); + // FIXME: Instead of passing in the CallOperator->getTypeSourceInfo() + // we should get a prebuilt TrivialTypeSourceInfo from Context + // using FunctionTy & Loc and get its TypeLoc as a FunctionProtoTypeLoc + // then rewire the parameters accordingly, by hoisting up the InvokeParams + // loop below and then use its Params to set Invoke->setParams(...) below. + // This would avoid the 'const' qualifier of the calloperator from + // contaminating the type of the invoker, which is currently adjusted + // in SemaTemplateDeduction.cpp:DeduceTemplateArguments. Fixing the + // trailing return type of the invoker would require a visitor to rebuild + // the trailing return type and adjusting all back DeclRefExpr's to refer + // to the new static invoker parameters - not the call operator's. CXXMethodDecl *Invoke = CXXMethodDecl::Create(S.Context, Class, Loc, - DeclarationNameInfo(Name, Loc), FunctionTy, - CallOperator->getTypeSourceInfo(), + DeclarationNameInfo(InvokerName, Loc), + InvokerFunctionTy, + CallOperator->getTypeSourceInfo(), 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(), - /*DefaultArg=*/0)); - } - Invoke->setParams(InvokeParams); + for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) + InvokerParams[I]->setOwningFunction(Invoke); + Invoke->setParams(InvokerParams); Invoke->setAccess(AS_private); Invoke->setImplicit(true); - Class->addDecl(Invoke); + if (Class->isGenericLambda()) { + FunctionTemplateDecl *TemplateCallOperator = + CallOperator->getDescribedFunctionTemplate(); + FunctionTemplateDecl *StaticInvokerTemplate = FunctionTemplateDecl::Create( + S.Context, Class, Loc, InvokerName, + TemplateCallOperator->getTemplateParameters(), + Invoke); + StaticInvokerTemplate->setAccess(AS_private); + StaticInvokerTemplate->setImplicit(true); + Invoke->setDescribedFunctionTemplate(StaticInvokerTemplate); + Class->addDecl(StaticInvokerTemplate); + } else + Class->addDecl(Invoke); } /// \brief Add a lambda's conversion to block pointer. @@ -768,15 +1243,13 @@ static void addBlockPointerConversion(Sema &S, { FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo(); ExtInfo.TypeQuals = 0; - QualType FunctionTy - = S.Context.getFunctionType(Proto->getResultType(), - ArrayRef<QualType>(Proto->arg_type_begin(), - Proto->getNumArgs()), - ExtInfo); + QualType FunctionTy = S.Context.getFunctionType( + Proto->getResultType(), Proto->getArgTypes(), ExtInfo); BlockPtrTy = S.Context.getBlockPointerType(FunctionTy); } - - FunctionProtoType::ExtProtoInfo ExtInfo; + + FunctionProtoType::ExtProtoInfo ExtInfo(S.Context.getDefaultCallingConvention( + /*IsVariadic=*/false, /*IsCXXMethod=*/true)); ExtInfo.TypeQuals = Qualifiers::Const; QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ExtInfo); @@ -791,7 +1264,7 @@ static void addBlockPointerConversion(Sema &S, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy, S.Context.getTrivialTypeSourceInfo(ConvTy, Loc), - /*isInline=*/false, /*isExplicit=*/false, + /*isInline=*/true, /*isExplicit=*/false, /*isConstexpr=*/false, CallOperator->getBody()->getLocEnd()); Conversion->setAccess(AS_public); @@ -806,6 +1279,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, SmallVector<LambdaExpr::Capture, 4> Captures; SmallVector<Expr *, 4> CaptureInits; LambdaCaptureDefault CaptureDefault; + SourceLocation CaptureDefaultLoc; CXXRecordDecl *Class; CXXMethodDecl *CallOperator; SourceRange IntroducerRange; @@ -848,7 +1322,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, 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()); + CaptureInits.push_back(From.getInitExpr()); } switch (LSI->ImpCaptureStyle) { @@ -869,13 +1343,18 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, llvm_unreachable("block capture in lambda"); break; } + CaptureDefaultLoc = LSI->CaptureDefaultLoc; // 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: + // + // Skip for C++1y return type deduction semantics which uses + // different machinery. + // FIXME: Refactor and Merge the return type deduction machinery. // FIXME: Assumes current resolution to core issue 975. - if (LSI->HasImplicitReturnType) { + if (LSI->HasImplicitReturnType && !getLangOpts().CPlusPlus1y) { deduceClosureReturnType(*LSI); // - if there are no return statements in the @@ -889,20 +1368,23 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, // Create a function type with the inferred return type. const FunctionProtoType *Proto = CallOperator->getType()->getAs<FunctionProtoType>(); - QualType FunctionTy - = Context.getFunctionType(LSI->ReturnType, - ArrayRef<QualType>(Proto->arg_type_begin(), - Proto->getNumArgs()), - Proto->getExtProtoInfo()); + QualType FunctionTy = Context.getFunctionType( + LSI->ReturnType, Proto->getArgTypes(), 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); + Decl *TemplateOrNonTemplateCallOperatorDecl = + CallOperator->getDescribedFunctionTemplate() + ? CallOperator->getDescribedFunctionTemplate() + : cast<Decl>(CallOperator); + + TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class); + Class->addDecl(TemplateOrNonTemplateCallOperatorDecl); + PopExpressionEvaluationContext(); // C++11 [expr.prim.lambda]p6: @@ -919,7 +1401,9 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, // 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) + // FIXME: Fix generic lambda to block conversions. + if (getLangOpts().Blocks && getLangOpts().ObjC1 && + !Class->isGenericLambda()) addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator); // Finalize the lambda class. @@ -936,32 +1420,42 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, ExprNeedsCleanups = true; LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, - CaptureDefault, Captures, + CaptureDefault, CaptureDefaultLoc, + Captures, ExplicitParams, ExplicitResultType, CaptureInits, ArrayIndexVars, ArrayIndexStarts, Body->getLocEnd(), ContainsUnexpandedParameterPack); - // 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) { + // C++11 [expr.prim.lambda]p2: + // A lambda-expression shall not appear in an unevaluated operand + // (Clause 5). case Unevaluated: case UnevaluatedAbstract: + // C++1y [expr.const]p2: + // A conditional-expression e is a core constant expression unless the + // evaluation of e, following the rules of the abstract machine, would + // evaluate [...] a lambda-expression. + // + // This is technically incorrect, there are some constant evaluated contexts + // where this should be allowed. We should probably fix this when DR1607 is + // ratified, it lays out the exact set of conditions where we shouldn't + // allow a lambda-expression. + case ConstantEvaluated: // 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); } @@ -976,7 +1470,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, Lambda->lookup( Context.DeclarationNames.getCXXOperatorName(OO_Call)).front()); CallOperator->setReferenced(); - CallOperator->setUsed(); + CallOperator->markUsed(Context); ExprResult Init = PerformCopyInitialization( InitializedEntity::InitializeBlock(ConvLocation, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp index 9ab3b2d08ec0..919c6ad61ab2 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp @@ -102,15 +102,14 @@ namespace { // During unqualified name lookup, the names appear as if they // were declared in the nearest enclosing namespace which contains // both the using-directive and the nominated namespace. - DeclContext *InnermostFileDC - = static_cast<DeclContext*>(InnermostFileScope->getEntity()); + DeclContext *InnermostFileDC = InnermostFileScope->getEntity(); assert(InnermostFileDC && InnermostFileDC->isFileContext()); for (; S; S = S->getParent()) { // 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()); + DeclContext *Ctx = S->getEntity(); if (Ctx && Ctx->isFileContext()) { visit(Ctx, Ctx); } else if (!Ctx || Ctx->isFunctionOrMethod()) { @@ -167,8 +166,7 @@ namespace { if (queue.empty()) return; - DC = queue.back(); - queue.pop_back(); + DC = queue.pop_back_val(); } } @@ -217,12 +215,15 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind, case Sema::LookupObjCImplicitSelfParam: case Sema::LookupOrdinaryName: case Sema::LookupRedeclarationWithLinkage: + case Sema::LookupLocalFriendName: IDNS = Decl::IDNS_Ordinary; if (CPlusPlus) { IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Namespace; if (Redeclaration) IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend; } + if (Redeclaration) + IDNS |= Decl::IDNS_LocalExtern; break; case Sema::LookupOperatorName: @@ -336,10 +337,19 @@ void LookupResult::deletePaths(CXXBasePaths *Paths) { delete Paths; } -static NamedDecl *getVisibleDecl(NamedDecl *D); - -NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const { - return getVisibleDecl(D); +/// Get a representative context for a declaration such that two declarations +/// will have the same context if they were found within the same scope. +static DeclContext *getContextForScopeMatching(Decl *D) { + // For function-local declarations, use that function as the context. This + // doesn't account for scopes within the function; the caller must deal with + // those. + DeclContext *DC = D->getLexicalDeclContext(); + if (DC->isFunctionOrMethod()) + return DC; + + // Otherwise, look at the semantic context of the declaration. The + // declaration must have been found there. + return D->getDeclContext()->getRedeclContext(); } /// Resolves the result kind of this lookup. @@ -442,8 +452,8 @@ void LookupResult::resolveKind() { // even if they're not visible. (ref?) if (HideTags && HasTag && !Ambiguous && (HasFunction || HasNonFunction || HasUnresolved)) { - if (Decls[UniqueTagIndex]->getDeclContext()->getRedeclContext()->Equals( - Decls[UniqueTagIndex? 0 : N-1]->getDeclContext()->getRedeclContext())) + if (getContextForScopeMatching(Decls[UniqueTagIndex])->Equals( + getContextForScopeMatching(Decls[UniqueTagIndex ? 0 : N - 1]))) Decls[UniqueTagIndex] = Decls[--N]; else Ambiguous = true; @@ -511,6 +521,14 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) { NameKind == Sema::LookupRedeclarationWithLinkage) { IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo(); if (II) { + if (S.getLangOpts().CPlusPlus11 && S.getLangOpts().GNUMode && + II == S.getFloat128Identifier()) { + // libstdc++4.7's type_traits expects type __float128 to exist, so + // insert a dummy type to make that header build in gnu++11 mode. + R.addDecl(S.getASTContext().getFloat128StubType()); + return true; + } + // If this is a builtin on this (or all) targets, create the decl. if (unsigned BuiltinID = II->getBuiltinID()) { // In C++, we don't have any predefined library functions like @@ -726,7 +744,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { // function to have, if it were to match the name given. // FIXME: Calling convention! FunctionProtoType::ExtProtoInfo EPI = ConvProto->getExtProtoInfo(); - EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_Default); + EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_C); EPI.ExceptionSpecType = EST_None; EPI.NumExceptions = 0; QualType ExpectedType @@ -771,7 +789,7 @@ CppNamespaceLookup(Sema &S, LookupResult &R, ASTContext &Context, } static bool isNamespaceOrTranslationUnitScope(Scope *S) { - if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) + if (DeclContext *Ctx = S->getEntity()) return Ctx->isFileContext(); return false; } @@ -784,12 +802,12 @@ static bool isNamespaceOrTranslationUnitScope(Scope *S) { // name lookup should continue searching in this semantic context when // it leaves the current template parameter scope. static std::pair<DeclContext *, bool> findOuterContext(Scope *S) { - DeclContext *DC = static_cast<DeclContext *>(S->getEntity()); + DeclContext *DC = S->getEntity(); DeclContext *Lexical = 0; for (Scope *OuterS = S->getParent(); OuterS; OuterS = OuterS->getParent()) { if (OuterS->getEntity()) { - Lexical = static_cast<DeclContext *>(OuterS->getEntity()); + Lexical = OuterS->getEntity(); break; } } @@ -845,16 +863,37 @@ static std::pair<DeclContext *, bool> findOuterContext(Scope *S) { return std::make_pair(Lexical, false); } +namespace { +/// An RAII object to specify that we want to find block scope extern +/// declarations. +struct FindLocalExternScope { + FindLocalExternScope(LookupResult &R) + : R(R), OldFindLocalExtern(R.getIdentifierNamespace() & + Decl::IDNS_LocalExtern) { + R.setFindLocalExtern(R.getIdentifierNamespace() & Decl::IDNS_Ordinary); + } + void restore() { + R.setFindLocalExtern(OldFindLocalExtern); + } + ~FindLocalExternScope() { + restore(); + } + LookupResult &R; + bool OldFindLocalExtern; +}; +} + bool Sema::CppLookupName(LookupResult &R, Scope *S) { assert(getLangOpts().CPlusPlus && "Can perform only C++ lookup"); DeclarationName Name = R.getLookupName(); + Sema::LookupNameKind NameKind = R.getLookupKind(); // If this is the name of an implicitly-declared special member function, // go through the scope stack to implicitly declare if (isImplicitlyDeclaredMemberFunctionName(Name)) { for (Scope *PreS = S; PreS; PreS = PreS->getParent()) - if (DeclContext *DC = static_cast<DeclContext *>(PreS->getEntity())) + if (DeclContext *DC = PreS->getEntity()) DeclareImplicitMemberFunctionsWithName(*this, Name, DC); } @@ -886,14 +925,35 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // UnqualUsingDirectiveSet UDirs; bool VisitedUsingDirectives = false; + bool LeftStartingScope = false; DeclContext *OutsideOfTemplateParamDC = 0; + + // When performing a scope lookup, we want to find local extern decls. + FindLocalExternScope FindLocals(R); + for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) { - DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()); + DeclContext *Ctx = S->getEntity(); // Check whether the IdResolver has anything in this scope. bool Found = false; for (; I != IEnd && S->isDeclScope(*I); ++I) { if (NamedDecl *ND = R.getAcceptableDecl(*I)) { + if (NameKind == LookupRedeclarationWithLinkage) { + // Determine whether this (or a previous) declaration is + // out-of-scope. + if (!LeftStartingScope && !Initial->isDeclScope(*I)) + LeftStartingScope = true; + + // If we found something outside of our starting scope that + // does not have linkage, skip it. If it's a template parameter, + // we still find it, so we can diagnose the invalid redeclaration. + if (LeftStartingScope && !((*I)->hasLinkage()) && + !(*I)->isTemplateParameter()) { + R.setShadowed(); + continue; + } + } + Found = true; R.addDecl(ND); } @@ -906,6 +966,15 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { return true; } + if (NameKind == LookupLocalFriendName && !S->isClassScope()) { + // C++11 [class.friend]p11: + // If a friend declaration appears in a local class and the name + // specified is an unqualified name, a prior declaration is + // looked up without considering scopes that are outside the + // innermost enclosing non-class scope. + return false; + } + if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC && S->getParent() && !S->getParent()->isTemplateParamScope()) { // We've just searched the last template parameter scope and @@ -1007,7 +1076,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { if (!S) return false; // If we are looking for members, no need to look into global/namespace scope. - if (R.getLookupKind() == LookupMemberName) + if (NameKind == LookupMemberName) return false; // Collect UsingDirectiveDecls in all scopes, and recursively all @@ -1019,7 +1088,12 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { UDirs.visitScopeChain(Initial, S); UDirs.done(); } - + + // If we're not performing redeclaration lookup, do not look for local + // extern declarations outside of a function scope. + if (!R.isForRedeclaration()) + FindLocals.restore(); + // Lookup namespace scope, and global scope. // Unqualified name lookup in C++ requires looking into scopes // that aren't strictly lexical, and therefore we walk through the @@ -1043,7 +1117,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { return true; } - DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity()); + DeclContext *Ctx = S->getEntity(); if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC && S->getParent() && !S->getParent()->isTemplateParamScope()) { // We've just searched the last template parameter scope and @@ -1098,29 +1172,127 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { return !R.empty(); } +/// \brief Find the declaration that a class temploid member specialization was +/// instantiated from, or the member itself if it is an explicit specialization. +static Decl *getInstantiatedFrom(Decl *D, MemberSpecializationInfo *MSInfo) { + return MSInfo->isExplicitSpecialization() ? D : MSInfo->getInstantiatedFrom(); +} + +/// \brief Find the module in which the given declaration was defined. +static Module *getDefiningModule(Decl *Entity) { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Entity)) { + // If this function was instantiated from a template, the defining module is + // the module containing the pattern. + if (FunctionDecl *Pattern = FD->getTemplateInstantiationPattern()) + Entity = Pattern; + } else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Entity)) { + // If it's a class template specialization, find the template or partial + // specialization from which it was instantiated. + if (ClassTemplateSpecializationDecl *SpecRD = + dyn_cast<ClassTemplateSpecializationDecl>(RD)) { + llvm::PointerUnion<ClassTemplateDecl*, + ClassTemplatePartialSpecializationDecl*> From = + SpecRD->getInstantiatedFrom(); + if (ClassTemplateDecl *FromTemplate = From.dyn_cast<ClassTemplateDecl*>()) + Entity = FromTemplate->getTemplatedDecl(); + else if (From) + Entity = From.get<ClassTemplatePartialSpecializationDecl*>(); + // Otherwise, it's an explicit specialization. + } else if (MemberSpecializationInfo *MSInfo = + RD->getMemberSpecializationInfo()) + Entity = getInstantiatedFrom(RD, MSInfo); + } else if (EnumDecl *ED = dyn_cast<EnumDecl>(Entity)) { + if (MemberSpecializationInfo *MSInfo = ED->getMemberSpecializationInfo()) + Entity = getInstantiatedFrom(ED, MSInfo); + } else if (VarDecl *VD = dyn_cast<VarDecl>(Entity)) { + // FIXME: Map from variable template specializations back to the template. + if (MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo()) + Entity = getInstantiatedFrom(VD, MSInfo); + } + + // Walk up to the containing context. That might also have been instantiated + // from a template. + DeclContext *Context = Entity->getDeclContext(); + if (Context->isFileContext()) + return Entity->getOwningModule(); + return getDefiningModule(cast<Decl>(Context)); +} + +llvm::DenseSet<Module*> &Sema::getLookupModules() { + unsigned N = ActiveTemplateInstantiations.size(); + for (unsigned I = ActiveTemplateInstantiationLookupModules.size(); + I != N; ++I) { + Module *M = getDefiningModule(ActiveTemplateInstantiations[I].Entity); + if (M && !LookupModulesCache.insert(M).second) + M = 0; + ActiveTemplateInstantiationLookupModules.push_back(M); + } + return LookupModulesCache; +} + +/// \brief Determine whether a declaration is visible to name lookup. +/// +/// This routine determines whether the declaration D is visible in the current +/// lookup context, taking into account the current template instantiation +/// stack. During template instantiation, a declaration is visible if it is +/// visible from a module containing any entity on the template instantiation +/// path (by instantiating a template, you allow it to see the declarations that +/// your module can see, including those later on in your module). +bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { + assert(D->isHidden() && !SemaRef.ActiveTemplateInstantiations.empty() && + "should not call this: not in slow case"); + Module *DeclModule = D->getOwningModule(); + assert(DeclModule && "hidden decl not from a module"); + + // Find the extra places where we need to look. + llvm::DenseSet<Module*> &LookupModules = SemaRef.getLookupModules(); + if (LookupModules.empty()) + return false; + + // If our lookup set contains the decl's module, it's visible. + if (LookupModules.count(DeclModule)) + return true; + + // If the declaration isn't exported, it's not visible in any other module. + if (D->isModulePrivate()) + return false; + + // Check whether DeclModule is transitively exported to an import of + // the lookup set. + for (llvm::DenseSet<Module *>::iterator I = LookupModules.begin(), + E = LookupModules.end(); + I != E; ++I) + if ((*I)->isModuleVisible(DeclModule)) + return true; + return false; +} + /// \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; - +static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) { + assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case"); + for (Decl::redecl_iterator RD = D->redecls_begin(), RDEnd = D->redecls_end(); RD != RDEnd; ++RD) { if (NamedDecl *ND = dyn_cast<NamedDecl>(*RD)) { - if (LookupResult::isVisible(ND)) + if (LookupResult::isVisible(SemaRef, ND)) return ND; } } - + return 0; } +NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const { + return findAcceptableDecl(SemaRef, D); +} + /// @brief Perform unqualified name lookup starting from a given /// scope. /// @@ -1161,13 +1333,12 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { if (NameKind == Sema::LookupRedeclarationWithLinkage) { // Find the nearest non-transparent declaration scope. while (!(S->getFlags() & Scope::DeclScope) || - (S->getEntity() && - static_cast<DeclContext *>(S->getEntity()) - ->isTransparentContext())) + (S->getEntity() && S->getEntity()->isTransparentContext())) S = S->getParent(); } - unsigned IDNS = R.getIdentifierNamespace(); + // When performing a scope lookup, we want to find local extern decls. + FindLocalExternScope FindLocals(R); // Scan up the scope chain looking for a decl that matches this // identifier that is in the appropriate namespace. This search @@ -1178,7 +1349,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { for (IdentifierResolver::iterator I = IdResolver.begin(Name), IEnd = IdResolver.end(); I != IEnd; ++I) - if ((*I)->isInIdentifierNamespace(IDNS)) { + if (NamedDecl *D = R.getAcceptableDecl(*I)) { if (NameKind == LookupRedeclarationWithLinkage) { // Determine whether this (or a previous) declaration is // out-of-scope. @@ -1187,19 +1358,15 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { // If we found something outside of our starting scope that // does not have linkage, skip it. - if (LeftStartingScope && !((*I)->hasLinkage())) + if (LeftStartingScope && !((*I)->hasLinkage())) { + R.setShadowed(); continue; + } } else if (NameKind == LookupObjCImplicitSelfParam && !isa<ImplicitParamDecl>(*I)) continue; - - // 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 @@ -1234,18 +1401,15 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { 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); + + // If the declaration is in the right namespace and visible, add it. + if (NamedDecl *LastD = R.getAcceptableDecl(*LastI)) + R.addDecl(LastD); } R.resolveKind(); } + return true; } } else { @@ -1330,8 +1494,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, bool Found = false; while (!Queue.empty()) { - NamespaceDecl *ND = Queue.back(); - Queue.pop_back(); + NamespaceDecl *ND = Queue.pop_back_val(); // We go through some convolutions here to avoid copying results // between LookupResults. @@ -1510,6 +1673,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, case LookupOrdinaryName: case LookupMemberName: case LookupRedeclarationWithLinkage: + case LookupLocalFriendName: BaseCallback = &CXXRecordDecl::FindOrdinaryMember; break; @@ -1681,9 +1845,7 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, /// from name lookup. /// /// \param Result The result of the ambiguous lookup to be diagnosed. -/// -/// \returns true -bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { +void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { assert(Result.isAmbiguous() && "Lookup result must be ambiguous"); DeclarationName Name = Result.getLookupName(); @@ -1704,8 +1866,7 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { ++Found; Diag((*Found)->getLocation(), diag::note_ambiguous_member_found); - - return true; + break; } case LookupResult::AmbiguousBaseSubobjectTypes: { @@ -1721,8 +1882,7 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { if (DeclsPrinted.insert(D).second) Diag(D->getLocation(), diag::note_ambiguous_member_found); } - - return true; + break; } case LookupResult::AmbiguousTagHiding: { @@ -1748,8 +1908,7 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { F.erase(); } F.done(); - - return true; + break; } case LookupResult::AmbiguousReference: { @@ -1758,12 +1917,9 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { LookupResult::iterator DI = Result.begin(), DE = Result.end(); for (; DI != DE; ++DI) Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI; - - return true; + break; } } - - llvm_unreachable("unknown ambiguity kind"); } namespace { @@ -1922,8 +2078,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, Bases.push_back(Class); while (!Bases.empty()) { // Pop this class off the stack. - Class = Bases.back(); - Bases.pop_back(); + Class = Bases.pop_back_val(); // Visit the base classes. for (CXXRecordDecl::base_class_iterator Base = Class->bases_begin(), @@ -2107,9 +2262,9 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { continue; } - if (Queue.empty()) break; - T = Queue.back(); - Queue.pop_back(); + if (Queue.empty()) + break; + T = Queue.pop_back_val(); } } @@ -2120,11 +2275,10 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { /// This routine computes the sets of associated classes and associated /// namespaces searched by argument-dependent lookup /// (C++ [basic.lookup.argdep]) for a given set of arguments. -void -Sema::FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc, - llvm::ArrayRef<Expr *> Args, - AssociatedNamespaceSet &AssociatedNamespaces, - AssociatedClassSet &AssociatedClasses) { +void Sema::FindAssociatedClassesAndNamespaces( + SourceLocation InstantiationLoc, ArrayRef<Expr *> Args, + AssociatedNamespaceSet &AssociatedNamespaces, + AssociatedClassSet &AssociatedClasses) { AssociatedNamespaces.clear(); AssociatedClasses.clear(); @@ -2393,11 +2547,17 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, // will always be a (possibly implicit) declaration to shadow any others. OverloadCandidateSet OCS((SourceLocation())); DeclContext::lookup_result R = RD->lookup(Name); - assert(!R.empty() && "lookup for a constructor or assignment operator was empty"); - for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { - Decl *Cand = *I; + + // Copy the candidates as our processing of them may load new declarations + // from an external source and invalidate lookup_result. + SmallVector<NamedDecl *, 8> Candidates(R.begin(), R.end()); + + for (SmallVectorImpl<NamedDecl *>::iterator I = Candidates.begin(), + E = Candidates.end(); + I != E; ++I) { + NamedDecl *Cand = *I; if (Cand->isInvalidDecl()) continue; @@ -2565,7 +2725,8 @@ CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) { Sema::LiteralOperatorLookupResult Sema::LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef<QualType> ArgTys, - bool AllowRawAndTemplate) { + bool AllowRaw, bool AllowTemplate, + bool AllowStringTemplate) { LookupName(R, S); assert(R.getResultKind() != LookupResult::Ambiguous && "literal operator lookup can't be ambiguous"); @@ -2573,8 +2734,9 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, // Filter the lookup results appropriately. LookupResult::Filter F = R.makeFilter(); - bool FoundTemplate = false; bool FoundRaw = false; + bool FoundTemplate = false; + bool FoundStringTemplate = false; bool FoundExactMatch = false; while (F.hasNext()) { @@ -2582,16 +2744,17 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) D = USD->getTargetDecl(); - bool IsTemplate = isa<FunctionTemplateDecl>(D); - bool IsRaw = false; - bool IsExactMatch = false; - // If the declaration we found is invalid, skip it. if (D->isInvalidDecl()) { F.erase(); continue; } + bool IsRaw = false; + bool IsTemplate = false; + bool IsStringTemplate = false; + bool IsExactMatch = false; + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (FD->getNumParams() == 1 && FD->getParamDecl(0)->getType()->getAs<PointerType>()) @@ -2607,19 +2770,31 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, } } } + if (FunctionTemplateDecl *FD = dyn_cast<FunctionTemplateDecl>(D)) { + TemplateParameterList *Params = FD->getTemplateParameters(); + if (Params->size() == 1) + IsTemplate = true; + else + IsStringTemplate = true; + } if (IsExactMatch) { FoundExactMatch = true; - AllowRawAndTemplate = false; - if (FoundRaw || FoundTemplate) { + AllowRaw = false; + AllowTemplate = false; + AllowStringTemplate = false; + if (FoundRaw || FoundTemplate || FoundStringTemplate) { // Go through again and remove the raw and template decls we've // already found. F.restart(); - FoundRaw = FoundTemplate = false; + FoundRaw = FoundTemplate = FoundStringTemplate = false; } - } else if (AllowRawAndTemplate && (IsTemplate || IsRaw)) { - FoundTemplate |= IsTemplate; - FoundRaw |= IsRaw; + } else if (AllowRaw && IsRaw) { + FoundRaw = true; + } else if (AllowTemplate && IsTemplate) { + FoundTemplate = true; + } else if (AllowStringTemplate && IsStringTemplate) { + FoundStringTemplate = true; } else { F.erase(); } @@ -2654,10 +2829,14 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, if (FoundTemplate) return LOLR_Template; + if (FoundStringTemplate) + return LOLR_StringTemplate; + // 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; + << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRaw + << (AllowTemplate || AllowStringTemplate); return LOLR_Error; } @@ -2699,8 +2878,7 @@ void ADLResult::insert(NamedDecl *New) { } void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, - SourceLocation Loc, - llvm::ArrayRef<Expr *> Args, + SourceLocation Loc, ArrayRef<Expr *> Args, ADLResult &Result) { // Find all of the associated namespaces and classes based on the // arguments we have. @@ -2748,9 +2926,21 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, NamedDecl *D = *I; // If the only declaration here is an ordinary friend, consider // it only if it was declared in an associated classes. - if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) { - DeclContext *LexDC = D->getLexicalDeclContext(); - if (!AssociatedClasses.count(cast<CXXRecordDecl>(LexDC))) + if ((D->getIdentifierNamespace() & Decl::IDNS_Ordinary) == 0) { + // If it's neither ordinarily visible nor a friend, we can't find it. + if ((D->getIdentifierNamespace() & Decl::IDNS_OrdinaryFriend) == 0) + continue; + + bool DeclaredInAssociatedClass = false; + for (Decl *DI = D; DI; DI = DI->getPreviousDecl()) { + DeclContext *LexDC = DI->getLexicalDeclContext(); + if (isa<CXXRecordDecl>(LexDC) && + AssociatedClasses.count(cast<CXXRecordDecl>(LexDC))) { + DeclaredInAssociatedClass = true; + break; + } + } + if (!DeclaredInAssociatedClass) continue; } @@ -2775,6 +2965,8 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, //---------------------------------------------------------------------------- VisibleDeclConsumer::~VisibleDeclConsumer() { } +bool VisibleDeclConsumer::includeHiddenDecls() const { return false; } + namespace { class ShadowContextRAII; @@ -3038,8 +3230,9 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, if (!S->getEntity() || (!S->getParent() && - !Visited.alreadyVisitedContext((DeclContext *)S->getEntity())) || - ((DeclContext *)S->getEntity())->isFunctionOrMethod()) { + !Visited.alreadyVisitedContext(S->getEntity())) || + (S->getEntity())->isFunctionOrMethod()) { + FindLocalExternScope FindLocals(Result); // Walk through the declarations in this Scope. for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); D != DEnd; ++D) { @@ -3057,7 +3250,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, // Look into this scope's declaration context, along with any of its // parent lookup contexts (e.g., enclosing classes), up to the point // where we hit the context stored in the next outer scope. - Entity = (DeclContext *)S->getEntity(); + Entity = S->getEntity(); DeclContext *OuterCtx = findOuterContext(S).first; // FIXME for (DeclContext *Ctx = Entity; Ctx && !Ctx->Equals(OuterCtx); @@ -3069,7 +3262,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, Result.getNameLoc(), Sema::LookupMemberName); if (ObjCInterfaceDecl *IFace = Method->getClassInterface()) { LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false, - /*InBaseClass=*/false, Consumer, Visited); + /*InBaseClass=*/false, Consumer, Visited); } } @@ -3134,6 +3327,7 @@ void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind, // Look for visible declarations. LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind); + Result.setAllowHidden(Consumer.includeHiddenDecls()); VisibleDeclsRecord Visited; if (!IncludeGlobalScope) Visited.visitedContext(Context.getTranslationUnitDecl()); @@ -3145,6 +3339,7 @@ void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, VisibleDeclConsumer &Consumer, bool IncludeGlobalScope) { LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind); + Result.setAllowHidden(Consumer.includeHiddenDecls()); VisibleDeclsRecord Visited; if (!IncludeGlobalScope) Visited.visitedContext(Context.getTranslationUnitDecl()); @@ -3214,14 +3409,16 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer { public: explicit TypoCorrectionConsumer(Sema &SemaRef, IdentifierInfo *Typo) : Typo(Typo->getName()), - SemaRef(SemaRef) { } + SemaRef(SemaRef) {} + + bool includeHiddenDecls() const { return true; } virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, bool InBaseClass); void FoundName(StringRef Name); void addKeywordResult(StringRef Keyword); - void addName(StringRef Name, NamedDecl *ND, unsigned Distance, - NestedNameSpecifier *NNS=NULL, bool isKeyword=false); + void addName(StringRef Name, NamedDecl *ND, NestedNameSpecifier *NNS = NULL, + bool isKeyword = false); void addCorrection(TypoCorrection Correction); typedef TypoResultsMap::iterator result_iterator; @@ -3265,37 +3462,42 @@ void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding, if (!Name) return; + // Only consider visible declarations and declarations from modules with + // names that exactly match. + if (!LookupResult::isVisible(SemaRef, ND) && Name->getName() != Typo && + !findAcceptableDecl(SemaRef, ND)) + return; + FoundName(Name->getName()); } 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 && 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 = (Typo.size() + 2) / 3; - // Compute the edit distance between the typo and the name of this // entity, and add the identifier to the list of results. - addName(Name, NULL, Typo.edit_distance(Name, true, UpperBound)); + addName(Name, NULL); } void TypoCorrectionConsumer::addKeywordResult(StringRef Keyword) { // Compute the edit distance between the typo and this keyword, // and add the keyword to the list of results. - addName(Keyword, NULL, Typo.edit_distance(Keyword), NULL, true); + addName(Keyword, NULL, NULL, true); } -void TypoCorrectionConsumer::addName(StringRef Name, - NamedDecl *ND, - unsigned Distance, - NestedNameSpecifier *NNS, - bool isKeyword) { - TypoCorrection TC(&SemaRef.Context.Idents.get(Name), ND, NNS, Distance); +void TypoCorrectionConsumer::addName(StringRef Name, NamedDecl *ND, + NestedNameSpecifier *NNS, bool isKeyword) { + // Use a simple length-based heuristic to determine the minimum possible + // edit distance. If the minimum isn't good enough, bail out early. + unsigned MinED = abs((int)Name.size() - (int)Typo.size()); + if (MinED && Typo.size() / MinED < 3) + return; + + // Compute an upper bound on the allowable edit distance, so that the + // edit-distance algorithm can short-circuit. + unsigned UpperBound = (Typo.size() + 2) / 3 + 1; + unsigned ED = Typo.edit_distance(Name, true, UpperBound); + if (ED >= UpperBound) return; + + TypoCorrection TC(&SemaRef.Context.Idents.get(Name), ND, NNS, ED); if (isKeyword) TC.makeKeyword(); addCorrection(TC); } @@ -3388,6 +3590,7 @@ typedef SmallVector<SpecifierInfo, 16> SpecifierInfoList; class NamespaceSpecifierSet { ASTContext &Context; DeclContextList CurContextChain; + std::string CurNameSpecifier; SmallVector<const IdentifierInfo*, 4> CurContextIdentifiers; SmallVector<const IdentifierInfo*, 4> CurNameSpecifierIdentifiers; bool isSorted; @@ -3406,10 +3609,14 @@ class NamespaceSpecifierSet { NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext, CXXScopeSpec *CurScopeSpec) : Context(Context), CurContextChain(BuildContextChain(CurContext)), - isSorted(true) { - if (CurScopeSpec && CurScopeSpec->getScopeRep()) - getNestedNameSpecifierIdentifiers(CurScopeSpec->getScopeRep(), - CurNameSpecifierIdentifiers); + isSorted(false) { + if (NestedNameSpecifier *NNS = + CurScopeSpec ? CurScopeSpec->getScopeRep() : 0) { + llvm::raw_string_ostream SpecifierOStream(CurNameSpecifier); + NNS->print(SpecifierOStream, Context.getPrintingPolicy()); + + getNestedNameSpecifierIdentifiers(NNS, CurNameSpecifierIdentifiers); + } // Build the list of identifiers that would be used for an absolute // (from the global context) NestedNameSpecifier referring to the current // context. @@ -3419,11 +3626,17 @@ class NamespaceSpecifierSet { if (NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C)) CurContextIdentifiers.push_back(ND->getIdentifier()); } + + // Add the global context as a NestedNameSpecifier + Distances.insert(1); + DistanceMap[1].push_back( + SpecifierInfo(cast<DeclContext>(Context.getTranslationUnitDecl()), + NestedNameSpecifier::GlobalSpecifier(Context), 1)); } - /// \brief Add the namespace to the set, computing the corresponding - /// NestedNameSpecifier and its distance in the process. - void AddNamespace(NamespaceDecl *ND); + /// \brief Add the DeclContext (a namespace or record) to the set, computing + /// the corresponding NestedNameSpecifier and its distance in the process. + void AddNameSpecifier(DeclContext *Ctx); typedef SpecifierInfoList::iterator iterator; iterator begin() { @@ -3456,8 +3669,8 @@ void NamespaceSpecifierSet::SortNamespaces() { std::sort(sortedDistances.begin(), sortedDistances.end()); Specifiers.clear(); - for (SmallVector<unsigned, 4>::iterator DI = sortedDistances.begin(), - DIEnd = sortedDistances.end(); + for (SmallVectorImpl<unsigned>::iterator DI = sortedDistances.begin(), + DIEnd = sortedDistances.end(); DI != DIEnd; ++DI) { SpecifierInfoList &SpecList = DistanceMap[*DI]; Specifiers.append(SpecList.begin(), SpecList.end()); @@ -3466,8 +3679,26 @@ void NamespaceSpecifierSet::SortNamespaces() { isSorted = true; } -void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) { - DeclContext *Ctx = cast<DeclContext>(ND); +static unsigned BuildNestedNameSpecifier(ASTContext &Context, + DeclContextList &DeclChain, + NestedNameSpecifier *&NNS) { + unsigned NumSpecifiers = 0; + for (DeclContextList::reverse_iterator C = DeclChain.rbegin(), + CEnd = DeclChain.rend(); + C != CEnd; ++C) { + if (NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C)) { + NNS = NestedNameSpecifier::Create(Context, NNS, ND); + ++NumSpecifiers; + } else if (RecordDecl *RD = dyn_cast_or_null<RecordDecl>(*C)) { + NNS = NestedNameSpecifier::Create(Context, NNS, RD->isTemplateDecl(), + RD->getTypeForDecl()); + ++NumSpecifiers; + } + } + return NumSpecifiers; +} + +void NamespaceSpecifierSet::AddNameSpecifier(DeclContext *Ctx) { NestedNameSpecifier *NNS = NULL; unsigned NumSpecifiers = 0; DeclContextList NamespaceDeclChain(BuildContextChain(Ctx)); @@ -3481,29 +3712,37 @@ void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) { NamespaceDeclChain.pop_back(); } + // Build the NestedNameSpecifier from what is left of the NamespaceDeclChain + NumSpecifiers = BuildNestedNameSpecifier(Context, NamespaceDeclChain, NNS); + // Add an explicit leading '::' specifier if needed. - if (NamespaceDecl *ND = - NamespaceDeclChain.empty() ? NULL : - dyn_cast_or_null<NamespaceDecl>(NamespaceDeclChain.back())) { + if (NamespaceDeclChain.empty()) { + // Rebuild the NestedNameSpecifier as a globally-qualified specifier. + NNS = NestedNameSpecifier::GlobalSpecifier(Context); + NumSpecifiers = + BuildNestedNameSpecifier(Context, FullNamespaceDeclChain, NNS); + } else if (NamedDecl *ND = + dyn_cast_or_null<NamedDecl>(NamespaceDeclChain.back())) { IdentifierInfo *Name = ND->getIdentifier(); - if (std::find(CurContextIdentifiers.begin(), CurContextIdentifiers.end(), - Name) != CurContextIdentifiers.end() || - std::find(CurNameSpecifierIdentifiers.begin(), + bool SameNameSpecifier = false; + if (std::find(CurNameSpecifierIdentifiers.begin(), CurNameSpecifierIdentifiers.end(), Name) != CurNameSpecifierIdentifiers.end()) { - NamespaceDeclChain = FullNamespaceDeclChain; - NNS = NestedNameSpecifier::GlobalSpecifier(Context); + std::string NewNameSpecifier; + llvm::raw_string_ostream SpecifierOStream(NewNameSpecifier); + SmallVector<const IdentifierInfo *, 4> NewNameSpecifierIdentifiers; + getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers); + NNS->print(SpecifierOStream, Context.getPrintingPolicy()); + SpecifierOStream.flush(); + SameNameSpecifier = NewNameSpecifier == CurNameSpecifier; } - } - - // Build the NestedNameSpecifier from what is left of the NamespaceDeclChain - for (DeclContextList::reverse_iterator C = NamespaceDeclChain.rbegin(), - CEnd = NamespaceDeclChain.rend(); - C != CEnd; ++C) { - NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C); - if (ND) { - NNS = NestedNameSpecifier::Create(Context, NNS, ND); - ++NumSpecifiers; + if (SameNameSpecifier || + std::find(CurContextIdentifiers.begin(), CurContextIdentifiers.end(), + Name) != CurContextIdentifiers.end()) { + // Rebuild the NestedNameSpecifier as a globally-qualified specifier. + NNS = NestedNameSpecifier::GlobalSpecifier(Context); + NumSpecifiers = + BuildNestedNameSpecifier(Context, FullNamespaceDeclChain, NNS); } } @@ -3515,8 +3754,8 @@ void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) { SmallVector<const IdentifierInfo*, 4> NewNameSpecifierIdentifiers; getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers); NumSpecifiers = llvm::ComputeEditDistance( - llvm::ArrayRef<const IdentifierInfo*>(CurNameSpecifierIdentifiers), - llvm::ArrayRef<const IdentifierInfo*>(NewNameSpecifierIdentifiers)); + ArrayRef<const IdentifierInfo *>(CurNameSpecifierIdentifiers), + ArrayRef<const IdentifierInfo *>(NewNameSpecifierIdentifiers)); } isSorted = false; @@ -3531,10 +3770,12 @@ static void LookupPotentialTypoResult(Sema &SemaRef, Scope *S, CXXScopeSpec *SS, DeclContext *MemberContext, bool EnteringContext, - bool isObjCIvarLookup) { + bool isObjCIvarLookup, + bool FindHidden) { Res.suppressDiagnostics(); Res.clear(); Res.setLookupName(Name); + Res.setAllowHidden(FindHidden); if (MemberContext) { if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(MemberContext)) { if (isObjCIvarLookup) { @@ -3593,7 +3834,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef, if (CCC.WantTypeSpecifiers) { // Add type-specifier keywords to the set of results. - const char *CTypeSpecs[] = { + static const char *const CTypeSpecs[] = { "char", "const", "double", "enum", "float", "int", "long", "short", "signed", "struct", "union", "unsigned", "void", "volatile", "_Complex", "_Imaginary", @@ -3601,7 +3842,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef, "extern", "inline", "static", "typedef" }; - const unsigned NumCTypeSpecs = sizeof(CTypeSpecs) / sizeof(CTypeSpecs[0]); + const unsigned NumCTypeSpecs = llvm::array_lengthof(CTypeSpecs); for (unsigned I = 0; I != NumCTypeSpecs; ++I) Consumer.addKeywordResult(CTypeSpecs[I]); @@ -3645,10 +3886,10 @@ static void AddKeywordsToConsumer(Sema &SemaRef, } if (SemaRef.getLangOpts().CPlusPlus) { - const char *CXXExprs[] = { + static const char *const CXXExprs[] = { "delete", "new", "operator", "throw", "typeid" }; - const unsigned NumCXXExprs = sizeof(CXXExprs) / sizeof(CXXExprs[0]); + const unsigned NumCXXExprs = llvm::array_lengthof(CXXExprs); for (unsigned I = 0; I != NumCXXExprs; ++I) Consumer.addKeywordResult(CXXExprs[I]); @@ -3672,9 +3913,9 @@ static void AddKeywordsToConsumer(Sema &SemaRef, if (CCC.WantRemainingKeywords) { if (SemaRef.getCurFunctionOrMethodDecl() || SemaRef.getCurBlock()) { // Statements. - const char *CStmts[] = { + static const char *const CStmts[] = { "do", "else", "for", "goto", "if", "return", "switch", "while" }; - const unsigned NumCStmts = sizeof(CStmts) / sizeof(CStmts[0]); + const unsigned NumCStmts = llvm::array_lengthof(CStmts); for (unsigned I = 0; I != NumCStmts; ++I) Consumer.addKeywordResult(CStmts[I]); @@ -3725,6 +3966,50 @@ static bool isCandidateViable(CorrectionCandidateCallback &CCC, return Candidate.getEditDistance(false) != TypoCorrection::InvalidDistance; } +/// \brief Check whether the declarations found for a typo correction are +/// visible, and if none of them are, convert the correction to an 'import +/// a module' correction. +static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC, + DeclarationName TypoName) { + if (TC.begin() == TC.end()) + return; + + TypoCorrection::decl_iterator DI = TC.begin(), DE = TC.end(); + + for (/**/; DI != DE; ++DI) + if (!LookupResult::isVisible(SemaRef, *DI)) + break; + // Nothing to do if all decls are visible. + if (DI == DE) + return; + + llvm::SmallVector<NamedDecl*, 4> NewDecls(TC.begin(), DI); + bool AnyVisibleDecls = !NewDecls.empty(); + + for (/**/; DI != DE; ++DI) { + NamedDecl *VisibleDecl = *DI; + if (!LookupResult::isVisible(SemaRef, *DI)) + VisibleDecl = findAcceptableDecl(SemaRef, *DI); + + if (VisibleDecl) { + if (!AnyVisibleDecls) { + // Found a visible decl, discard all hidden ones. + AnyVisibleDecls = true; + NewDecls.clear(); + } + NewDecls.push_back(VisibleDecl); + } else if (!AnyVisibleDecls && !(*DI)->isModulePrivate()) + NewDecls.push_back(*DI); + } + + if (NewDecls.empty()) + TC = TypoCorrection(); + else { + TC.setCorrectionDecls(NewDecls); + TC.setRequiresImport(!AnyVisibleDecls); + } +} + /// \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. @@ -3762,8 +4047,18 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, CorrectionCandidateCallback &CCC, DeclContext *MemberContext, bool EnteringContext, - const ObjCObjectPointerType *OPT) { - if (Diags.hasFatalErrorOccurred() || !getLangOpts().SpellChecking) + const ObjCObjectPointerType *OPT, + bool RecordFailure) { + // Always let the ExternalSource have the first chance at correction, even + // if we would otherwise have given up. + if (ExternalSource) { + if (TypoCorrection Correction = ExternalSource->CorrectTypo( + TypoName, LookupKind, S, SS, CCC, MemberContext, EnteringContext, OPT)) + return Correction; + } + + if (Diags.hasFatalErrorOccurred() || !getLangOpts().SpellChecking || + DisableTypoCorrection) return TypoCorrection(); // In Microsoft mode, don't perform typo correction in a template member @@ -3792,6 +4087,18 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, if (S && S->isInObjcMethodScope() && Typo == getSuperIdentifier()) return TypoCorrection(); + // Abort if typo correction already failed for this specific typo. + IdentifierSourceLocations::iterator locs = TypoCorrectionFailures.find(Typo); + if (locs != TypoCorrectionFailures.end() && + locs->second.count(TypoName.getLoc())) + return TypoCorrection(); + + // Don't try to correct the identifier "vector" when in AltiVec mode. + // TODO: Figure out why typo correction misbehaves in this case, fix it, and + // remove this workaround. + if (getLangOpts().AltiVec && Typo->isStr("vector")) + return TypoCorrection(); + NamespaceSpecifierSet Namespaces(Context, CurContext, SS); TypoCorrectionConsumer Consumer(*this, Typo); @@ -3836,8 +4143,15 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // 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); + isCandidateViable(CCC, Cached->second)) { + // Do not use correction that is unaccessible in the given scope. + NamedDecl *CorrectionDecl = Cached->second.getCorrectionDecl(); + DeclarationNameInfo NameInfo(CorrectionDecl->getDeclName(), + CorrectionDecl->getLocation()); + LookupResult R(*this, NameInfo, LookupOrdinaryName); + if (LookupName(R, S)) + Consumer.addCorrection(Cached->second); + } } else { // Only honor no-correction cache hits when a callback that will validate // correction candidates is not being used. @@ -3858,11 +4172,12 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // corrections. bool SearchNamespaces = getLangOpts().CPlusPlus && - (IsUnqualifiedLookup || (QualifiedDC && QualifiedDC->isNamespace())); - // In a few cases we *only* want to search for corrections bases on just + (IsUnqualifiedLookup || (SS && SS->isSet())); + // In a few cases we *only* want to search for corrections based on just // adding or changing the nested name specifier. - bool AllowOnlyNNSChanges = Typo->getName().size() < 3; - + unsigned TypoLen = Typo->getName().size(); + bool AllowOnlyNNSChanges = TypoLen < 3; + if (IsUnqualifiedLookup || SearchNamespaces) { // For unqualified lookup, look through all of the names that we have // seen in this translation unit. @@ -3890,24 +4205,16 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, AddKeywordsToConsumer(*this, Consumer, S, CCC, SS && SS->isNotEmpty()); // If we haven't found anything, we're done. - if (Consumer.empty()) { - // If this was an unqualified lookup, note that no correction was found. - if (IsUnqualifiedLookup) - (void)UnqualifiedTyposCorrected[Typo]; - - return TypoCorrection(); - } + if (Consumer.empty()) + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure, + IsUnqualifiedLookup); // Make sure the best edit distance (prior to adding any namespace qualifiers) // is not more that about a third of the length of the typo's identifier. 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) - (void)UnqualifiedTyposCorrected[Typo]; - - return TypoCorrection(); - } + if (ED > 0 && TypoLen / ED < 3) + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure, + IsUnqualifiedLookup); // Build the NestedNameSpecifiers for the KnownNamespaces, if we're going // to search those namespaces. @@ -3920,12 +4227,24 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, for (unsigned I = 0, N = ExternalKnownNamespaces.size(); I != N; ++I) KnownNamespaces[ExternalKnownNamespaces[I]] = true; } - - for (llvm::MapVector<NamespaceDecl*, bool>::iterator + + for (llvm::MapVector<NamespaceDecl*, bool>::iterator KNI = KnownNamespaces.begin(), KNIEnd = KnownNamespaces.end(); KNI != KNIEnd; ++KNI) - Namespaces.AddNamespace(KNI->first); + Namespaces.AddNameSpecifier(KNI->first); + + for (ASTContext::type_iterator TI = Context.types_begin(), + TIEnd = Context.types_end(); + TI != TIEnd; ++TI) { + if (CXXRecordDecl *CD = (*TI)->getAsCXXRecordDecl()) { + CD = CD->getCanonicalDecl(); + if (!CD->isDependentType() && !CD->isAnonymousStructOrUnion() && + !CD->isUnion() && + (CD->isBeingDefined() || CD->isCompleteDefinition())) + Namespaces.AddNameSpecifier(CD); + } + } } // Weed out any names that could not be found by name lookup or, if a @@ -3935,7 +4254,6 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, TmpRes.suppressDiagnostics(); while (!Consumer.empty()) { TypoCorrectionConsumer::distance_iterator DI = Consumer.begin(); - unsigned ED = DI->first; for (TypoCorrectionConsumer::result_iterator I = DI->second.begin(), IEnd = DI->second.end(); I != IEnd; /* Increment in loop. */) { @@ -3976,13 +4294,31 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // Perform name lookup on this name. TypoCorrection &Candidate = I->second.front(); IdentifierInfo *Name = Candidate.getCorrectionAsIdentifierInfo(); - LookupPotentialTypoResult(*this, TmpRes, Name, S, SS, MemberContext, - EnteringContext, CCC.IsObjCIvarLookup); + DeclContext *TempMemberContext = MemberContext; + CXXScopeSpec *TempSS = SS; +retry_lookup: + LookupPotentialTypoResult(*this, TmpRes, Name, S, TempSS, + TempMemberContext, EnteringContext, + CCC.IsObjCIvarLookup, + Name == TypoName.getName() && + !Candidate.WillReplaceSpecifier()); switch (TmpRes.getResultKind()) { case LookupResult::NotFound: case LookupResult::NotFoundInCurrentInstantiation: case LookupResult::FoundUnresolvedValue: + if (TempSS) { + // Immediately retry the lookup without the given CXXScopeSpec + TempSS = NULL; + Candidate.WillReplaceSpecifier(true); + goto retry_lookup; + } + if (TempMemberContext) { + if (SS && !TempSS) + TempSS = SS; + TempMemberContext = NULL; + goto retry_lookup; + } QualifiedResults.push_back(Candidate); // We didn't find this name in our scope, or didn't like what we found; // ignore it. @@ -3996,7 +4332,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, case LookupResult::Ambiguous: // We don't deal with ambiguities. - return TypoCorrection(); + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); case LookupResult::FoundOverloaded: { TypoCorrectionConsumer::result_iterator Prev = I; @@ -4006,8 +4342,10 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, TRD != TRDEnd; ++TRD) Candidate.addCorrectionDecl(*TRD); ++I; - if (!isCandidateViable(CCC, Candidate)) + if (!isCandidateViable(CCC, Candidate)) { + QualifiedResults.push_back(Candidate); DI->second.erase(Prev); + } break; } @@ -4015,8 +4353,10 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, TypoCorrectionConsumer::result_iterator Prev = I; Candidate.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>()); ++I; - if (!isCandidateViable(CCC, Candidate)) + if (!isCandidateViable(CCC, Candidate)) { + QualifiedResults.push_back(Candidate); DI->second.erase(Prev); + } break; } @@ -4025,7 +4365,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, if (DI->second.empty()) Consumer.erase(DI); - else if (!getLangOpts().CPlusPlus || QualifiedResults.empty() || !ED) + else if (!getLangOpts().CPlusPlus || QualifiedResults.empty() || !DI->first) // If there are results in the closest possible bucket, stop break; @@ -4040,10 +4380,31 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, NIEnd = Namespaces.end(); NI != NIEnd; ++NI) { DeclContext *Ctx = NI->DeclCtx; + const Type *NSType = NI->NameSpecifier->getAsType(); + + // If the current NestedNameSpecifier refers to a class and the + // current correction candidate is the name of that class, then skip + // it as it is unlikely a qualified version of the class' constructor + // is an appropriate correction. + if (CXXRecordDecl *NSDecl = + NSType ? NSType->getAsCXXRecordDecl() : 0) { + if (NSDecl->getIdentifier() == QRI->getCorrectionAsIdentifierInfo()) + continue; + } - // 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). + TypoCorrection TC(*QRI); + TC.ClearCorrectionDecls(); + TC.setCorrectionSpecifier(NI->NameSpecifier); + TC.setQualifierDistance(NI->EditDistance); + TC.setCallbackDistance(0); // Reset the callback distance + + // If the current correction candidate and namespace combination are + // too far away from the original typo based on the normalized edit + // distance, then skip performing a qualified name lookup. + unsigned TmpED = TC.getEditDistance(true); + if (QRI->getCorrectionAsIdentifierInfo() != Typo && + TmpED && TypoLen / TmpED < 3) + continue; TmpRes.clear(); TmpRes.setLookupName(QRI->getCorrectionAsIdentifierInfo()); @@ -4052,23 +4413,30 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // 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: { - TypoCorrection TC(*QRI); - TC.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>()); - TC.setCorrectionSpecifier(NI->NameSpecifier); - TC.setQualifierDistance(NI->EditDistance); - Consumer.addCorrection(TC); - break; - } + case LookupResult::Found: case LookupResult::FoundOverloaded: { - TypoCorrection TC(*QRI); - TC.setCorrectionSpecifier(NI->NameSpecifier); - TC.setQualifierDistance(NI->EditDistance); + if (SS && SS->isValid()) { + std::string NewQualified = TC.getAsString(getLangOpts()); + std::string OldQualified; + llvm::raw_string_ostream OldOStream(OldQualified); + SS->getScopeRep()->print(OldOStream, getPrintingPolicy()); + OldOStream << TypoName; + // If correction candidate would be an identical written qualified + // identifer, then the existing CXXScopeSpec probably included a + // typedef that didn't get accounted for properly. + if (OldOStream.str() == NewQualified) + break; + } for (LookupResult::iterator TRD = TmpRes.begin(), TRDEnd = TmpRes.end(); - TRD != TRDEnd; ++TRD) - TC.addCorrectionDecl(*TRD); - Consumer.addCorrection(TC); + TRD != TRDEnd; ++TRD) { + if (CheckMemberAccess(TC.getCorrectionRange().getBegin(), + NSType ? NSType->getAsCXXRecordDecl() : 0, + TRD.getPair()) == AR_accessible) + TC.addCorrectionDecl(*TRD); + } + if (TC.isResolved()) + Consumer.addCorrection(TC); break; } case LookupResult::NotFound: @@ -4085,30 +4453,31 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, } // No corrections remain... - if (Consumer.empty()) return TypoCorrection(); + if (Consumer.empty()) + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); TypoResultsMap &BestResults = Consumer.getBestResults(); ED = Consumer.getBestEditDistance(true); - if (!AllowOnlyNNSChanges && ED > 0 && Typo->getName().size() / ED < 3) { + if (!AllowOnlyNNSChanges && ED > 0 && TypoLen / ED < 3) { // 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(); + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure, + IsUnqualifiedLookup && !ValidatingCallback); } // If only a single name remains, return that result. if (BestResults.size() == 1) { const TypoResultList &CorrectionList = BestResults.begin()->second; const TypoCorrection &Result = CorrectionList.front(); - if (CorrectionList.size() != 1) return TypoCorrection(); + if (CorrectionList.size() != 1) + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); // Don't correct to a keyword that's the same as the typo; the keyword // wasn't actually in scope. - if (ED == 0 && Result.isKeyword()) return TypoCorrection(); + if (ED == 0 && Result.isKeyword()) + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); // Record the correction for unqualified lookup. if (IsUnqualifiedLookup) @@ -4116,6 +4485,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, TypoCorrection TC = Result; TC.setCorrectionRange(SS, TypoName); + checkCorrectionVisibility(*this, TC, TypoName.getName()); return TC; } else if (BestResults.size() > 1 @@ -4130,7 +4500,8 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // Don't correct to a keyword that's the same as the typo; the keyword // wasn't actually in scope. - if (ED == 0) return TypoCorrection(); + if (ED == 0) + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); // Record the correction for unqualified lookup. if (IsUnqualifiedLookup) @@ -4146,7 +4517,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, if (IsUnqualifiedLookup && !ValidatingCallback) (void)UnqualifiedTyposCorrected[Typo]; - return TypoCorrection(); + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); } void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) { @@ -4166,7 +4537,7 @@ std::string TypoCorrection::getAsString(const LangOptions &LO) const { std::string tmpBuffer; llvm::raw_string_ostream PrefixOStream(tmpBuffer); CorrectionNameSpec->print(PrefixOStream, PrintingPolicy(LO)); - CorrectionName.printName(PrefixOStream); + PrefixOStream << CorrectionName; return PrefixOStream.str(); } @@ -4190,3 +4561,122 @@ bool CorrectionCandidateCallback::ValidateCandidate(const TypoCorrection &candid return WantTypeSpecifiers; } + +FunctionCallFilterCCC::FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs, + bool HasExplicitTemplateArgs) + : NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs) { + WantTypeSpecifiers = SemaRef.getLangOpts().CPlusPlus; + WantRemainingKeywords = false; +} + +bool FunctionCallFilterCCC::ValidateCandidate(const TypoCorrection &candidate) { + if (!candidate.getCorrectionDecl()) + return candidate.isKeyword(); + + for (TypoCorrection::const_decl_iterator DI = candidate.begin(), + DIEnd = candidate.end(); + DI != DIEnd; ++DI) { + FunctionDecl *FD = 0; + NamedDecl *ND = (*DI)->getUnderlyingDecl(); + 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; +} + +void Sema::diagnoseTypo(const TypoCorrection &Correction, + const PartialDiagnostic &TypoDiag, + bool ErrorRecovery) { + diagnoseTypo(Correction, TypoDiag, PDiag(diag::note_previous_decl), + ErrorRecovery); +} + +/// Find which declaration we should import to provide the definition of +/// the given declaration. +static const NamedDecl *getDefinitionToImport(const NamedDecl *D) { + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) + return VD->getDefinition(); + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + return FD->isDefined(FD) ? FD : 0; + if (const TagDecl *TD = dyn_cast<TagDecl>(D)) + return TD->getDefinition(); + if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) + return ID->getDefinition(); + if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) + return PD->getDefinition(); + if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) + return getDefinitionToImport(TD->getTemplatedDecl()); + return 0; +} + +/// \brief Diagnose a successfully-corrected typo. Separated from the correction +/// itself to allow external validation of the result, etc. +/// +/// \param Correction The result of performing typo correction. +/// \param TypoDiag The diagnostic to produce. This will have the corrected +/// string added to it (and usually also a fixit). +/// \param PrevNote A note to use when indicating the location of the entity to +/// which we are correcting. Will have the correction string added to it. +/// \param ErrorRecovery If \c true (the default), the caller is going to +/// recover from the typo as if the corrected string had been typed. +/// In this case, \c PDiag must be an error, and we will attach a fixit +/// to it. +void Sema::diagnoseTypo(const TypoCorrection &Correction, + const PartialDiagnostic &TypoDiag, + const PartialDiagnostic &PrevNote, + bool ErrorRecovery) { + std::string CorrectedStr = Correction.getAsString(getLangOpts()); + std::string CorrectedQuotedStr = Correction.getQuoted(getLangOpts()); + FixItHint FixTypo = FixItHint::CreateReplacement( + Correction.getCorrectionRange(), CorrectedStr); + + // Maybe we're just missing a module import. + if (Correction.requiresImport()) { + NamedDecl *Decl = Correction.getCorrectionDecl(); + assert(Decl && "import required but no declaration to import"); + + // Suggest importing a module providing the definition of this entity, if + // possible. + const NamedDecl *Def = getDefinitionToImport(Decl); + if (!Def) + Def = Decl; + Module *Owner = Def->getOwningModule(); + assert(Owner && "definition of hidden declaration is not in a module"); + + Diag(Correction.getCorrectionRange().getBegin(), + diag::err_module_private_declaration) + << Def << Owner->getFullModuleName(); + Diag(Def->getLocation(), diag::note_previous_declaration); + + // Recover by implicitly importing this module. + if (!isSFINAEContext() && ErrorRecovery) + createImplicitModuleImport(Correction.getCorrectionRange().getBegin(), + Owner); + return; + } + + Diag(Correction.getCorrectionRange().getBegin(), TypoDiag) + << CorrectedQuotedStr << (ErrorRecovery ? FixTypo : FixItHint()); + + NamedDecl *ChosenDecl = + Correction.isKeyword() ? 0 : Correction.getCorrectionDecl(); + if (PrevNote.getDiagID() && ChosenDecl) + Diag(ChosenDecl->getLocation(), PrevNote) + << CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp index 91f0881ae09c..d9d9cec1b700 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp @@ -126,7 +126,7 @@ CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop, DeclContext::lookup_result R = Proto->lookup(Prop->getDeclName()); for (unsigned I = 0, N = R.size(); I != N; ++I) { if (ObjCPropertyDecl *ProtoProp = dyn_cast<ObjCPropertyDecl>(R[I])) { - S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier()); + S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier(), true); return; } } @@ -208,7 +208,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, DeclContext::lookup_result R = Super->lookup(Res->getDeclName()); for (unsigned I = 0, N = R.size(); I != N; ++I) { if (ObjCPropertyDecl *SuperProp = dyn_cast<ObjCPropertyDecl>(R[I])) { - DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier()); + DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier(), false); FoundInSuper = true; break; } @@ -321,6 +321,21 @@ static unsigned getOwnershipRule(unsigned attr) { ObjCPropertyDecl::OBJC_PR_unsafe_unretained); } +static const char *NameOfOwnershipAttribute(unsigned attr) { + if (attr & ObjCPropertyDecl::OBJC_PR_assign) + return "assign"; + if (attr & ObjCPropertyDecl::OBJC_PR_retain ) + return "retain"; + if (attr & ObjCPropertyDecl::OBJC_PR_copy) + return "copy"; + if (attr & ObjCPropertyDecl::OBJC_PR_weak) + return "weak"; + if (attr & ObjCPropertyDecl::OBJC_PR_strong) + return "strong"; + assert(attr & ObjCPropertyDecl::OBJC_PR_unsafe_unretained); + return "unsafe_unretained"; +} + ObjCPropertyDecl * Sema::HandlePropertyInClassExtension(Scope *S, SourceLocation AtLoc, @@ -434,6 +449,8 @@ Sema::HandlePropertyInClassExtension(Scope *S, // with continuation class's readwrite property attribute! unsigned PIkind = PIDecl->getPropertyAttributesAsWritten(); if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) { + PIkind &= ~ObjCPropertyDecl::OBJC_PR_readonly; + PIkind |= ObjCPropertyDecl::OBJC_PR_readwrite; PIkind |= deduceWeakPropertyFromType(*this, PIDecl->getType()); unsigned ClassExtensionMemoryModel = getOwnershipRule(Attributes); unsigned PrimaryClassMemoryModel = getOwnershipRule(PIkind); @@ -442,6 +459,22 @@ Sema::HandlePropertyInClassExtension(Scope *S, Diag(AtLoc, diag::warn_property_attr_mismatch); Diag(PIDecl->getLocation(), diag::note_property_declare); } + else if (getLangOpts().ObjCAutoRefCount) { + QualType PrimaryPropertyQT = + Context.getCanonicalType(PIDecl->getType()).getUnqualifiedType(); + if (isa<ObjCObjectPointerType>(PrimaryPropertyQT)) { + bool PropertyIsWeak = ((PIkind & ObjCPropertyDecl::OBJC_PR_weak) != 0); + Qualifiers::ObjCLifetime PrimaryPropertyLifeTime = + PrimaryPropertyQT.getObjCLifetime(); + if (PrimaryPropertyLifeTime == Qualifiers::OCL_None && + (Attributes & ObjCDeclSpec::DQ_PR_weak) && + !PropertyIsWeak) { + Diag(AtLoc, diag::warn_property_implicitly_mismatched); + Diag(PIDecl->getLocation(), diag::note_property_declare); + } + } + } + DeclContext *DC = cast<DeclContext>(CCPrimary); if (!ObjCPropertyDecl::findPropertyDecl(DC, PIDecl->getDeclName().getAsIdentifierInfo())) { @@ -529,8 +562,16 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, if (IDecl->ClassImplementsProtocol(PNSCopying, true)) Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId; } - if (T->isObjCObjectType()) - Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object); + + if (T->isObjCObjectType()) { + SourceLocation StarLoc = TInfo->getTypeLoc().getLocEnd(); + StarLoc = PP.getLocForEndOfToken(StarLoc); + Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object) + << FixItHint::CreateInsertion(StarLoc, "*"); + T = Context.getObjCObjectPointerType(T); + SourceLocation TLoc = TInfo->getTypeLoc().getLocStart(); + TInfo = Context.getTrivialTypeSourceInfo(T, TLoc); + } DeclContext *DC = cast<DeclContext>(CDecl); ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC, @@ -714,73 +755,57 @@ static void setImpliedPropertyAttributeForReadOnlyProperty( return; } -/// DiagnoseClassAndClassExtPropertyMismatch - diagnose inconsistant property -/// attribute declared in primary class and attributes overridden in any of its -/// class extensions. +/// DiagnosePropertyMismatchDeclInProtocols - diagnose properties declared +/// in inherited protocols with mismatched types. Since any of them can +/// be candidate for synthesis. static void -DiagnoseClassAndClassExtPropertyMismatch(Sema &S, ObjCInterfaceDecl *ClassDecl, - ObjCPropertyDecl *property) { - unsigned Attributes = property->getPropertyAttributesAsWritten(); - bool warn = (Attributes & ObjCDeclSpec::DQ_PR_readonly); - for (ObjCInterfaceDecl::known_extensions_iterator - Ext = ClassDecl->known_extensions_begin(), - ExtEnd = ClassDecl->known_extensions_end(); - Ext != ExtEnd; ++Ext) { - ObjCPropertyDecl *ClassExtProperty = 0; - DeclContext::lookup_result R = Ext->lookup(property->getDeclName()); - for (unsigned I = 0, N = R.size(); I != N; ++I) { - ClassExtProperty = dyn_cast<ObjCPropertyDecl>(R[0]); - if (ClassExtProperty) - break; - } - - if (ClassExtProperty) { - warn = false; - unsigned classExtPropertyAttr = - ClassExtProperty->getPropertyAttributesAsWritten(); - // We are issuing the warning that we postponed because class extensions - // can override readonly->readwrite and 'setter' attributes originally - // placed on class's property declaration now make sense in the overridden - // property. - if (Attributes & ObjCDeclSpec::DQ_PR_readonly) { - if (!classExtPropertyAttr || - (classExtPropertyAttr & - (ObjCDeclSpec::DQ_PR_readwrite| - ObjCDeclSpec::DQ_PR_assign | - ObjCDeclSpec::DQ_PR_unsafe_unretained | - ObjCDeclSpec::DQ_PR_copy | - ObjCDeclSpec::DQ_PR_retain | - ObjCDeclSpec::DQ_PR_strong))) - continue; - warn = true; - break; - } - } +DiagnosePropertyMismatchDeclInProtocols(Sema &S, SourceLocation AtLoc, + ObjCInterfaceDecl *ClassDecl, + ObjCPropertyDecl *Property) { + ObjCInterfaceDecl::ProtocolPropertyMap PropMap; + for (ObjCInterfaceDecl::all_protocol_iterator + PI = ClassDecl->all_referenced_protocol_begin(), + E = ClassDecl->all_referenced_protocol_end(); PI != E; ++PI) { + if (const ObjCProtocolDecl *PDecl = (*PI)->getDefinition()) + PDecl->collectInheritedProtocolProperties(Property, PropMap); } - if (warn) { - unsigned setterAttrs = (ObjCDeclSpec::DQ_PR_assign | - ObjCDeclSpec::DQ_PR_unsafe_unretained | - ObjCDeclSpec::DQ_PR_copy | - ObjCDeclSpec::DQ_PR_retain | - ObjCDeclSpec::DQ_PR_strong); - if (Attributes & setterAttrs) { - const char * which = - (Attributes & ObjCDeclSpec::DQ_PR_assign) ? - "assign" : - (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) ? - "unsafe_unretained" : - (Attributes & ObjCDeclSpec::DQ_PR_copy) ? - "copy" : - (Attributes & ObjCDeclSpec::DQ_PR_retain) ? - "retain" : "strong"; - - S.Diag(property->getLocation(), - diag::warn_objc_property_attr_mutually_exclusive) - << "readonly" << which; + if (ObjCInterfaceDecl *SDecl = ClassDecl->getSuperClass()) + while (SDecl) { + for (ObjCInterfaceDecl::all_protocol_iterator + PI = SDecl->all_referenced_protocol_begin(), + E = SDecl->all_referenced_protocol_end(); PI != E; ++PI) { + if (const ObjCProtocolDecl *PDecl = (*PI)->getDefinition()) + PDecl->collectInheritedProtocolProperties(Property, PropMap); + } + SDecl = SDecl->getSuperClass(); } - } + if (PropMap.empty()) + return; + QualType RHSType = S.Context.getCanonicalType(Property->getType()); + bool FirsTime = true; + for (ObjCInterfaceDecl::ProtocolPropertyMap::iterator + I = PropMap.begin(), E = PropMap.end(); I != E; I++) { + ObjCPropertyDecl *Prop = I->second; + QualType LHSType = S.Context.getCanonicalType(Prop->getType()); + if (!S.Context.propertyTypesAreCompatible(LHSType, RHSType)) { + bool IncompatibleObjC = false; + QualType ConvertedType; + if (!S.isObjCPointerConversion(RHSType, LHSType, ConvertedType, IncompatibleObjC) + || IncompatibleObjC) { + if (FirsTime) { + S.Diag(Property->getLocation(), diag::warn_protocol_property_mismatch) + << Property->getType(); + FirsTime = false; + } + S.Diag(Prop->getLocation(), diag::note_protocol_property_declare) + << Prop->getType(); + } + } + } + if (!FirsTime && AtLoc.isValid()) + S.Diag(AtLoc, diag::note_property_synthesize); } /// ActOnPropertyImplDecl - This routine performs semantic checks and @@ -879,8 +904,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, } } } - - DiagnoseClassAndClassExtPropertyMismatch(*this, IDecl, property); + if (Synthesize && isa<ObjCProtocolDecl>(property->getDeclContext())) + DiagnosePropertyMismatchDeclInProtocols(*this, AtLoc, IDecl, property); } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) { if (Synthesize) { @@ -1027,8 +1052,14 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, PropertyIvarType, /*Dinfo=*/0, ObjCIvarDecl::Private, (Expr *)0, true); - if (CompleteTypeErr) + if (RequireNonAbstractType(PropertyIvarLoc, + PropertyIvarType, + diag::err_abstract_type_in_decl, + AbstractSynthesizedIvarType)) { + Diag(property->getLocation(), diag::note_property_declare); Ivar->setInvalidDecl(); + } else if (CompleteTypeErr) + Ivar->setInvalidDecl(); ClassImpDecl->addDecl(Ivar); IDecl->makeDeclVisibleInContext(Ivar); @@ -1158,6 +1189,18 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, diag::warn_property_getter_owning_mismatch); Diag(property->getLocation(), diag::note_property_declare); } + if (getLangOpts().ObjCAutoRefCount && Synthesize) + switch (getterMethod->getMethodFamily()) { + case OMF_retain: + case OMF_retainCount: + case OMF_release: + case OMF_autorelease: + Diag(getterMethod->getLocation(), diag::err_arc_illegal_method_def) + << 1 << getterMethod->getSelector(); + break; + default: + break; + } } if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) { setterMethod->createImplicitParams(Context, IDecl); @@ -1272,31 +1315,41 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, void Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, ObjCPropertyDecl *SuperProperty, - const IdentifierInfo *inheritedName) { + const IdentifierInfo *inheritedName, + bool OverridingProtocolProperty) { ObjCPropertyDecl::PropertyAttributeKind CAttr = - Property->getPropertyAttributes(); + Property->getPropertyAttributes(); ObjCPropertyDecl::PropertyAttributeKind SAttr = - SuperProperty->getPropertyAttributes(); - if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly) - && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite)) - Diag(Property->getLocation(), diag::warn_readonly_property) - << Property->getDeclName() << inheritedName; - if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy) - != (SAttr & ObjCPropertyDecl::OBJC_PR_copy)) - Diag(Property->getLocation(), diag::warn_property_attribute) - << Property->getDeclName() << "copy" << inheritedName; - else if (!(SAttr & ObjCPropertyDecl::OBJC_PR_readonly)){ - unsigned CAttrRetain = - (CAttr & - (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); - unsigned SAttrRetain = - (SAttr & - (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); - bool CStrong = (CAttrRetain != 0); - bool SStrong = (SAttrRetain != 0); - if (CStrong != SStrong) + SuperProperty->getPropertyAttributes(); + + // We allow readonly properties without an explicit ownership + // (assign/unsafe_unretained/weak/retain/strong/copy) in super class + // to be overridden by a property with any explicit ownership in the subclass. + if (!OverridingProtocolProperty && + !getOwnershipRule(SAttr) && getOwnershipRule(CAttr)) + ; + else { + if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly) + && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite)) + Diag(Property->getLocation(), diag::warn_readonly_property) + << Property->getDeclName() << inheritedName; + if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy) + != (SAttr & ObjCPropertyDecl::OBJC_PR_copy)) Diag(Property->getLocation(), diag::warn_property_attribute) - << Property->getDeclName() << "retain (or strong)" << inheritedName; + << Property->getDeclName() << "copy" << inheritedName; + else if (!(SAttr & ObjCPropertyDecl::OBJC_PR_readonly)){ + unsigned CAttrRetain = + (CAttr & + (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); + unsigned SAttrRetain = + (SAttr & + (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); + bool CStrong = (CAttrRetain != 0); + bool SStrong = (SAttrRetain != 0); + if (CStrong != SStrong) + Diag(Property->getLocation(), diag::warn_property_attribute) + << Property->getDeclName() << "retain (or strong)" << inheritedName; + } } if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic) @@ -1378,110 +1431,6 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, return false; } -/// MatchOneProtocolPropertiesInClass - This routine goes thru the list -/// of properties declared in a protocol and compares their attribute against -/// the same property declared in the class or category. -void -Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl, ObjCProtocolDecl *PDecl) { - if (!CDecl) - return; - - // Category case. - if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) { - // FIXME: We should perform this check when the property in the category - // is declared. - assert (CatDecl && "MatchOneProtocolPropertiesInClass"); - if (!CatDecl->IsClassExtension()) - for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), - E = PDecl->prop_end(); P != E; ++P) { - ObjCPropertyDecl *ProtoProp = *P; - DeclContext::lookup_result R - = CatDecl->lookup(ProtoProp->getDeclName()); - for (unsigned I = 0, N = R.size(); I != N; ++I) { - if (ObjCPropertyDecl *CatProp = dyn_cast<ObjCPropertyDecl>(R[I])) { - if (CatProp != ProtoProp) { - // Property protocol already exist in class. Diagnose any mismatch. - DiagnosePropertyMismatch(CatProp, ProtoProp, - PDecl->getIdentifier()); - } - } - } - } - return; - } - - // Class - // FIXME: We should perform this check when the property in the class - // is declared. - ObjCInterfaceDecl *IDecl = cast<ObjCInterfaceDecl>(CDecl); - for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), - E = PDecl->prop_end(); P != E; ++P) { - ObjCPropertyDecl *ProtoProp = *P; - DeclContext::lookup_result R - = IDecl->lookup(ProtoProp->getDeclName()); - for (unsigned I = 0, N = R.size(); I != N; ++I) { - if (ObjCPropertyDecl *ClassProp = dyn_cast<ObjCPropertyDecl>(R[I])) { - if (ClassProp != ProtoProp) { - // Property protocol already exist in class. Diagnose any mismatch. - DiagnosePropertyMismatch(ClassProp, ProtoProp, - PDecl->getIdentifier()); - } - } - } - } -} - -/// isPropertyReadonly - Return true if property is readonly, by searching -/// for the property in the class and in its categories and implementations -/// -bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl, - ObjCInterfaceDecl *IDecl) { - // by far the most common case. - if (!PDecl->isReadOnly()) - return false; - // Even if property is ready only, if interface has a user defined setter, - // it is not considered read only. - if (IDecl->getInstanceMethod(PDecl->getSetterName())) - return false; - - // Main class has the property as 'readonly'. Must search - // through the category list to see if the property's - // attribute has been over-ridden to 'readwrite'. - for (ObjCInterfaceDecl::visible_categories_iterator - Cat = IDecl->visible_categories_begin(), - CatEnd = IDecl->visible_categories_end(); - Cat != CatEnd; ++Cat) { - if (Cat->getInstanceMethod(PDecl->getSetterName())) - return false; - ObjCPropertyDecl *P = - Cat->FindPropertyDeclaration(PDecl->getIdentifier()); - if (P && !P->isReadOnly()) - return false; - } - - // Also, check for definition of a setter method in the implementation if - // all else failed. - if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurContext)) { - if (ObjCImplementationDecl *IMD = - dyn_cast<ObjCImplementationDecl>(OMD->getDeclContext())) { - if (IMD->getInstanceMethod(PDecl->getSetterName())) - return false; - } else if (ObjCCategoryImplDecl *CIMD = - dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) { - if (CIMD->getInstanceMethod(PDecl->getSetterName())) - return false; - } - } - // Lastly, look through the implementation (if one is in scope). - if (ObjCImplementationDecl *ImpDecl = IDecl->getImplementation()) - if (ImpDecl->getInstanceMethod(PDecl->getSetterName())) - return false; - // If all fails, look at the super class. - if (ObjCInterfaceDecl *SIDecl = IDecl->getSuperClass()) - return isPropertyReadonly(PDecl, SIDecl); - return true; -} - /// CollectImmediateProperties - This routine collects all properties in /// the class and its conforming protocols; but not those in its super class. void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, @@ -1588,6 +1537,19 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, for (unsigned i = 0, e = PropertyOrder.size(); i != e; i++) { ObjCPropertyDecl *Prop = PropertyOrder[i]; + // Is there a matching property synthesize/dynamic? + if (Prop->isInvalidDecl() || + Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional) + continue; + // Property may have been synthesized by user. + if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier())) + continue; + if (IMPDecl->getInstanceMethod(Prop->getGetterName())) { + if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly) + continue; + if (IMPDecl->getInstanceMethod(Prop->getSetterName())) + continue; + } // If property to be implemented in the super class, ignore. if (SuperPropMap[Prop->getIdentifier()]) { ObjCPropertyDecl *PropInSuperClass = SuperPropMap[Prop->getIdentifier()]; @@ -1602,29 +1564,16 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, } continue; } - // Is there a matching property synthesize/dynamic? - if (Prop->isInvalidDecl() || - Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional) - continue; if (ObjCPropertyImplDecl *PID = - IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) { + IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) { if (PID->getPropertyDecl() != Prop) { Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property) - << Prop->getIdentifier()->getName(); + << Prop->getIdentifier()->getName(); if (!PID->getLocation().isInvalid()) Diag(PID->getLocation(), diag::note_property_synthesize); } continue; } - // Property may have been synthesized by user. - if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier())) - continue; - if (IMPDecl->getInstanceMethod(Prop->getGetterName())) { - if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly) - continue; - if (IMPDecl->getInstanceMethod(Prop->getSetterName())) - continue; - } if (isa<ObjCProtocolDecl>(Prop->getDeclContext())) { // We won't auto-synthesize properties declared in protocols. Diag(IMPDecl->getLocation(), @@ -1966,6 +1915,10 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, if (property->hasAttr<NSReturnsNotRetainedAttr>()) GetterMethod->addAttr( ::new (Context) NSReturnsNotRetainedAttr(Loc, Context)); + + if (property->hasAttr<ObjCReturnsInnerPointerAttr>()) + GetterMethod->addAttr( + ::new (Context) ObjCReturnsInnerPointerAttr(Loc, Context)); if (getLangOpts().ObjCAutoRefCount) CheckARCMethodDecl(GetterMethod); @@ -2064,55 +2017,30 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl, // FIXME: Improve the reported location. if (!PDecl || PDecl->isInvalidDecl()) return; - + + if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && + (Attributes & ObjCDeclSpec::DQ_PR_readwrite)) + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "readonly" << "readwrite"; + 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) + QualType PropertyTy = PropertyDecl->getType(); + unsigned PropertyOwnership = getOwnershipRule(Attributes); + + if (Attributes & ObjCDeclSpec::DQ_PR_readonly) { + if (getLangOpts().ObjCAutoRefCount && + PropertyTy->isObjCRetainableType() && + !PropertyOwnership) { + // 'readonly' property with no obvious lifetime. + // its life time will be determined by its backing ivar. return; - } - - if (propertyInPrimaryClass) { - // we postpone most property diagnosis until class's implementation - // because, its readonly attribute may be overridden in its class - // extensions making other attributes, which make no sense, to make sense. - if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && - (Attributes & ObjCDeclSpec::DQ_PR_readwrite)) - Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) - << "readonly" << "readwrite"; - } - // readonly and readwrite/assign/retain/copy conflict. - else if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && - (Attributes & (ObjCDeclSpec::DQ_PR_readwrite | - ObjCDeclSpec::DQ_PR_assign | - ObjCDeclSpec::DQ_PR_unsafe_unretained | - ObjCDeclSpec::DQ_PR_copy | - ObjCDeclSpec::DQ_PR_retain | - ObjCDeclSpec::DQ_PR_strong))) { - const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ? - "readwrite" : - (Attributes & ObjCDeclSpec::DQ_PR_assign) ? - "assign" : - (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) ? - "unsafe_unretained" : - (Attributes & ObjCDeclSpec::DQ_PR_copy) ? - "copy" : "retain"; - - Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ? - diag::err_objc_property_attr_mutually_exclusive : - diag::warn_objc_property_attr_mutually_exclusive) - << "readonly" << which; + } + else if (PropertyOwnership) { + if (!getSourceManager().isInSystemHeader(Loc)) + Diag(Loc, diag::warn_objc_property_attr_mutually_exclusive) + << "readonly" << NameOfOwnershipAttribute(Attributes); + return; + } } // Check for copy or retain on non-object types. @@ -2151,6 +2079,8 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl, << "assign" << "weak"; Attributes &= ~ObjCDeclSpec::DQ_PR_weak; } + if (PropertyDecl->getAttr<IBOutletCollectionAttr>()) + Diag(Loc, diag::warn_iboutletcollection_property_assign); } else if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) { if (Attributes & ObjCDeclSpec::DQ_PR_copy) { Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp index c815d4f9abc7..c63caf46b9e0 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp @@ -8,131 +8,516 @@ //===----------------------------------------------------------------------===// /// \file /// \brief This file implements semantic analysis for OpenMP directives and -/// clauses +/// clauses. /// //===----------------------------------------------------------------------===// #include "clang/Basic/OpenMPKinds.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclOpenMP.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtOpenMP.h" +#include "clang/AST/StmtVisitor.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Initialization.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" using namespace clang; +//===----------------------------------------------------------------------===// +// Stack of data-sharing attributes for variables +//===----------------------------------------------------------------------===// + namespace { +/// \brief Default data sharing attributes, which can be applied to directive. +enum DefaultDataSharingAttributes { + DSA_unspecified = 0, /// \brief Data sharing attribute not specified. + DSA_none = 1 << 0, /// \brief Default data sharing attribute 'none'. + DSA_shared = 1 << 1 /// \brief Default data sharing attribute 'shared'. +}; + +/// \brief Stack for tracking declarations used in OpenMP directives and +/// clauses and their data-sharing attributes. +class DSAStackTy { +public: + struct DSAVarData { + OpenMPDirectiveKind DKind; + OpenMPClauseKind CKind; + DeclRefExpr *RefExpr; + DSAVarData() : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(0) { } + }; +private: + struct DSAInfo { + OpenMPClauseKind Attributes; + DeclRefExpr *RefExpr; + }; + typedef llvm::SmallDenseMap<VarDecl *, DSAInfo, 64> DeclSAMapTy; + + struct SharingMapTy { + DeclSAMapTy SharingMap; + DefaultDataSharingAttributes DefaultAttr; + OpenMPDirectiveKind Directive; + DeclarationNameInfo DirectiveName; + Scope *CurScope; + SharingMapTy(OpenMPDirectiveKind DKind, + const DeclarationNameInfo &Name, + Scope *CurScope) + : SharingMap(), DefaultAttr(DSA_unspecified), Directive(DKind), + DirectiveName(Name), CurScope(CurScope) { } + SharingMapTy() + : SharingMap(), DefaultAttr(DSA_unspecified), + Directive(OMPD_unknown), DirectiveName(), + CurScope(0) { } + }; + + typedef SmallVector<SharingMapTy, 64> StackTy; + + /// \brief Stack of used declaration and their data-sharing attributes. + StackTy Stack; + Sema &Actions; + + typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator; + + DSAVarData getDSA(StackTy::reverse_iterator Iter, VarDecl *D); +public: + explicit DSAStackTy(Sema &S) : Stack(1), Actions(S) { } + + void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName, + Scope *CurScope) { + Stack.push_back(SharingMapTy(DKind, DirName, CurScope)); + } + + void pop() { + assert(Stack.size() > 1 && "Data-sharing attributes stack is empty!"); + Stack.pop_back(); + } + + /// \brief Adds explicit data sharing attribute to the specified declaration. + void addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A); + + /// \brief Checks if the variable is a local for OpenMP region. + bool isOpenMPLocal(VarDecl *D); + + /// \brief Returns data sharing attributes from top of the stack for the + /// specified declaration. + DSAVarData getTopDSA(VarDecl *D); + /// \brief Returns data-sharing attributes for the specified declaration. + DSAVarData getImplicitDSA(VarDecl *D); + /// \brief Checks if the specified variables has \a CKind data-sharing + /// attribute in \a DKind directive. + DSAVarData hasDSA(VarDecl *D, OpenMPClauseKind CKind, + OpenMPDirectiveKind DKind = OMPD_unknown); + + + /// \brief Returns currently analyzed directive. + OpenMPDirectiveKind getCurrentDirective() const { + return Stack.back().Directive; + } + + /// \brief Set default data sharing attribute to none. + void setDefaultDSANone() { Stack.back().DefaultAttr = DSA_none; } + /// \brief Set default data sharing attribute to shared. + void setDefaultDSAShared() { Stack.back().DefaultAttr = DSA_shared; } + + DefaultDataSharingAttributes getDefaultDSA() const { + return Stack.back().DefaultAttr; + } + + Scope *getCurScope() { return Stack.back().CurScope; } +}; +} // end anonymous namespace. + +DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter, + VarDecl *D) { + DSAVarData DVar; + if (Iter == Stack.rend() - 1) { + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a region but not in construct] + // File-scope or namespace-scope variables referenced in called routines + // in the region are shared unless they appear in a threadprivate + // directive. + // TODO + if (!D->isFunctionOrMethodVarDecl()) + DVar.CKind = OMPC_shared; + + // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced + // in a region but not in construct] + // Variables with static storage duration that are declared in called + // routines in the region are shared. + if (D->hasGlobalStorage()) + DVar.CKind = OMPC_shared; + + return DVar; + } + DVar.DKind = Iter->Directive; + // Explicitly specified attributes and local variables with predetermined + // attributes. + if (Iter->SharingMap.count(D)) { + DVar.RefExpr = Iter->SharingMap[D].RefExpr; + DVar.CKind = Iter->SharingMap[D].Attributes; + return DVar; + } + + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct, C/C++, implicitly determined, p.1] + // In a parallel or task construct, the data-sharing attributes of these + // variables are determined by the default clause, if present. + switch (Iter->DefaultAttr) { + case DSA_shared: + DVar.CKind = OMPC_shared; + return DVar; + case DSA_none: + return DVar; + case DSA_unspecified: + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct, implicitly determined, p.2] + // In a parallel construct, if no default clause is present, these + // variables are shared. + if (DVar.DKind == OMPD_parallel) { + DVar.CKind = OMPC_shared; + return DVar; + } - class VarDeclFilterCCC : public CorrectionCandidateCallback { - private: - Sema &Actions; - public: - VarDeclFilterCCC(Sema &S) : Actions(S) { } - virtual bool ValidateCandidate(const TypoCorrection &Candidate) { - NamedDecl *ND = Candidate.getCorrectionDecl(); - if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) { - return VD->hasGlobalStorage() && - Actions.isDeclInScope(ND, Actions.getCurLexicalContext(), - Actions.getCurScope()); + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct, implicitly determined, p.4] + // In a task construct, if no default clause is present, a variable that in + // the enclosing context is determined to be shared by all implicit tasks + // bound to the current team is shared. + // TODO + if (DVar.DKind == OMPD_task) { + DSAVarData DVarTemp; + for (StackTy::reverse_iterator I = Iter + 1, + EE = Stack.rend() - 1; + I != EE; ++I) { + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct, implicitly determined, p.6] + // In a task construct, if no default clause is present, a variable + // whose data-sharing attribute is not determined by the rules above is + // firstprivate. + DVarTemp = getDSA(I, D); + if (DVarTemp.CKind != OMPC_shared) { + DVar.RefExpr = 0; + DVar.DKind = OMPD_task; + DVar.CKind = OMPC_firstprivate; + return DVar; } - return false; + if (I->Directive == OMPD_parallel) break; } - }; + DVar.DKind = OMPD_task; + DVar.CKind = + (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared; + return DVar; + } + } + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct, implicitly determined, p.3] + // For constructs other than task, if no default clause is present, these + // variables inherit their data-sharing attributes from the enclosing + // context. + return getDSA(Iter + 1, D); } -Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective( - SourceLocation Loc, - Scope *CurScope, - ArrayRef<DeclarationNameInfo> IdList) { - SmallVector<DeclRefExpr *, 5> Vars; - for (ArrayRef<DeclarationNameInfo>::iterator I = IdList.begin(), - E = IdList.end(); + +void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) { + if (A == OMPC_threadprivate) { + Stack[0].SharingMap[D].Attributes = A; + Stack[0].SharingMap[D].RefExpr = E; + } else { + assert(Stack.size() > 1 && "Data-sharing attributes stack is empty"); + Stack.back().SharingMap[D].Attributes = A; + Stack.back().SharingMap[D].RefExpr = E; + } +} + +bool DSAStackTy::isOpenMPLocal(VarDecl *D) { + Scope *CurScope = getCurScope(); + while (CurScope && !CurScope->isDeclScope(D)) + CurScope = CurScope->getParent(); + while (CurScope && !CurScope->isOpenMPDirectiveScope()) + CurScope = CurScope->getParent(); + bool isOpenMPLocal = !!CurScope; + if (!isOpenMPLocal) { + CurScope = getCurScope(); + while (CurScope && !CurScope->isOpenMPDirectiveScope()) + CurScope = CurScope->getParent(); + isOpenMPLocal = + CurScope && + isa<CapturedDecl>(D->getDeclContext()) && + CurScope->getFnParent()->getEntity()->Encloses(D->getDeclContext()); + } + return isOpenMPLocal; +} + +DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) { + DSAVarData DVar; + + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct, C/C++, predetermined, p.1] + // Variables appearing in threadprivate directives are threadprivate. + if (D->getTLSKind() != VarDecl::TLS_None) { + DVar.CKind = OMPC_threadprivate; + return DVar; + } + if (Stack[0].SharingMap.count(D)) { + DVar.RefExpr = Stack[0].SharingMap[D].RefExpr; + DVar.CKind = OMPC_threadprivate; + return DVar; + } + + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct, C/C++, predetermined, p.1] + // Variables with automatic storage duration that are declared in a scope + // inside the construct are private. + if (isOpenMPLocal(D) && D->isLocalVarDecl() && + (D->getStorageClass() == SC_Auto || + D->getStorageClass() == SC_None)) { + DVar.CKind = OMPC_private; + return DVar; + } + + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct, C/C++, predetermined, p.4] + // Static data memebers are shared. + if (D->isStaticDataMember()) { + // Variables with const-qualified type having no mutable member may be listed + // in a firstprivate clause, even if they are static data members. + DSAVarData DVarTemp = hasDSA(D, OMPC_firstprivate); + if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr) + return DVar; + + DVar.CKind = OMPC_shared; + return DVar; + } + + QualType Type = D->getType().getNonReferenceType().getCanonicalType(); + bool IsConstant = Type.isConstant(Actions.getASTContext()); + while (Type->isArrayType()) { + QualType ElemType = cast<ArrayType>(Type.getTypePtr())->getElementType(); + Type = ElemType.getNonReferenceType().getCanonicalType(); + } + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct, C/C++, predetermined, p.6] + // Variables with const qualified type having no mutable member are + // shared. + CXXRecordDecl *RD = Actions.getLangOpts().CPlusPlus ? + Type->getAsCXXRecordDecl() : 0; + if (IsConstant && + !(Actions.getLangOpts().CPlusPlus && RD && RD->hasMutableFields())) { + // Variables with const-qualified type having no mutable member may be + // listed in a firstprivate clause, even if they are static data members. + DSAVarData DVarTemp = hasDSA(D, OMPC_firstprivate); + if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr) + return DVar; + + DVar.CKind = OMPC_shared; + return DVar; + } + + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct, C/C++, predetermined, p.7] + // Variables with static storage duration that are declared in a scope + // inside the construct are shared. + if (isOpenMPLocal(D) && D->isStaticLocal()) { + DVar.CKind = OMPC_shared; + return DVar; + } + + // Explicitly specified attributes and local variables with predetermined + // attributes. + if (Stack.back().SharingMap.count(D)) { + DVar.RefExpr = Stack.back().SharingMap[D].RefExpr; + DVar.CKind = Stack.back().SharingMap[D].Attributes; + } + + return DVar; +} + +DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D) { + return getDSA(Stack.rbegin() + 1, D); +} + +DSAStackTy::DSAVarData DSAStackTy::hasDSA(VarDecl *D, OpenMPClauseKind CKind, + OpenMPDirectiveKind DKind) { + for (StackTy::reverse_iterator I = Stack.rbegin() + 1, + E = Stack.rend() - 1; I != E; ++I) { - LookupResult Lookup(*this, *I, LookupOrdinaryName); - LookupParsedName(Lookup, CurScope, NULL, true); - - if (Lookup.isAmbiguous()) - continue; - - VarDecl *VD; - if (!Lookup.isSingleResult()) { - VarDeclFilterCCC Validator(*this); - TypoCorrection Corrected = CorrectTypo(*I, LookupOrdinaryName, CurScope, - 0, Validator); - std::string CorrectedStr = Corrected.getAsString(getLangOpts()); - std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOpts()); - if (Lookup.empty()) { - if (Corrected.isResolved()) { - Diag(I->getLoc(), diag::err_undeclared_var_use_suggest) - << I->getName() << CorrectedQuotedStr - << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr); - } else { - Diag(I->getLoc(), diag::err_undeclared_var_use) - << I->getName(); - } - } else { - Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest) - << I->getName() << Corrected.isResolved() << CorrectedQuotedStr - << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr); - } - if (!Corrected.isResolved()) continue; + if (DKind != OMPD_unknown && DKind != I->Directive) continue; + DSAVarData DVar = getDSA(I, D); + if (DVar.CKind == CKind) + return DVar; + } + return DSAVarData(); +} + +void Sema::InitDataSharingAttributesStack() { + VarDataSharingAttributesStack = new DSAStackTy(*this); +} + +#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack) + +void Sema::DestroyDataSharingAttributesStack() { + delete DSAStack; +} + +void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind, + const DeclarationNameInfo &DirName, + Scope *CurScope) { + DSAStack->push(DKind, DirName, CurScope); + PushExpressionEvaluationContext(PotentiallyEvaluated); +} + +void Sema::EndOpenMPDSABlock(Stmt *CurDirective) { + DSAStack->pop(); + DiscardCleanupsInEvaluationContext(); + PopExpressionEvaluationContext(); +} + +namespace { + +class VarDeclFilterCCC : public CorrectionCandidateCallback { +private: + Sema &Actions; +public: + VarDeclFilterCCC(Sema &S) : Actions(S) { } + virtual bool ValidateCandidate(const TypoCorrection &Candidate) { + NamedDecl *ND = Candidate.getCorrectionDecl(); + if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) { + return VD->hasGlobalStorage() && + Actions.isDeclInScope(ND, Actions.getCurLexicalContext(), + Actions.getCurScope()); + } + return false; + } +}; +} + +ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope, + CXXScopeSpec &ScopeSpec, + const DeclarationNameInfo &Id) { + LookupResult Lookup(*this, Id, LookupOrdinaryName); + LookupParsedName(Lookup, CurScope, &ScopeSpec, true); + + if (Lookup.isAmbiguous()) + return ExprError(); + + VarDecl *VD; + if (!Lookup.isSingleResult()) { + VarDeclFilterCCC Validator(*this); + if (TypoCorrection Corrected = CorrectTypo(Id, LookupOrdinaryName, CurScope, + 0, Validator)) { + diagnoseTypo(Corrected, + PDiag(Lookup.empty()? diag::err_undeclared_var_use_suggest + : diag::err_omp_expected_var_arg_suggest) + << Id.getName()); VD = Corrected.getCorrectionDeclAs<VarDecl>(); } else { - if (!(VD = Lookup.getAsSingle<VarDecl>())) { - Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest) - << I->getName() << 0; - Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at); - continue; - } + Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use + : diag::err_omp_expected_var_arg) + << Id.getName(); + return ExprError(); + } + } else { + if (!(VD = Lookup.getAsSingle<VarDecl>())) { + Diag(Id.getLoc(), diag::err_omp_expected_var_arg) + << Id.getName(); + Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at); + return ExprError(); } + } + Lookup.suppressDiagnostics(); - // OpenMP [2.9.2, Syntax, C/C++] - // Variables must be file-scope, namespace-scope, or static block-scope. - if (!VD->hasGlobalStorage()) { - Diag(I->getLoc(), diag::err_omp_global_var_arg) - << getOpenMPDirectiveName(OMPD_threadprivate) - << !VD->isStaticLocal(); - Diag(VD->getLocation(), diag::note_forward_declaration) << VD; - continue; - } - - // OpenMP [2.9.2, Restrictions, C/C++, p.2] - // A threadprivate directive for file-scope variables must appear outside - // any definition or declaration. - // OpenMP [2.9.2, Restrictions, C/C++, p.3] - // A threadprivate directive for static class member variables must appear - // in the class definition, in the same scope in which the member - // variables are declared. - // OpenMP [2.9.2, Restrictions, C/C++, p.4] - // A threadprivate directive for namespace-scope variables must appear - // outside any definition or declaration other than the namespace - // definition itself. - // OpenMP [2.9.2, Restrictions, C/C++, p.6] - // A threadprivate directive for static block-scope variables must appear - // in the scope of the variable and not in a nested scope. - NamedDecl *ND = cast<NamedDecl>(VD); - if (!isDeclInScope(ND, getCurLexicalContext(), CurScope)) { - Diag(I->getLoc(), diag::err_omp_var_scope) - << getOpenMPDirectiveName(OMPD_threadprivate) << VD; - Diag(VD->getLocation(), diag::note_forward_declaration) << VD; - continue; - } - - // OpenMP [2.9.2, Restrictions, C/C++, p.2-6] - // A threadprivate directive must lexically precede all references to any - // of the variables in its list. - if (VD->isUsed()) { - Diag(I->getLoc(), diag::err_omp_var_used) - << getOpenMPDirectiveName(OMPD_threadprivate) << VD; - continue; - } - - QualType ExprType = VD->getType().getNonReferenceType(); - DeclRefExpr *Var = cast<DeclRefExpr>(BuildDeclRefExpr(VD, - ExprType, - VK_RValue, - I->getLoc()).take()); - Vars.push_back(Var); - } - if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, Vars)) { + // OpenMP [2.9.2, Syntax, C/C++] + // Variables must be file-scope, namespace-scope, or static block-scope. + if (!VD->hasGlobalStorage()) { + Diag(Id.getLoc(), diag::err_omp_global_var_arg) + << getOpenMPDirectiveName(OMPD_threadprivate) + << !VD->isStaticLocal(); + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), + IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD; + return ExprError(); + } + + VarDecl *CanonicalVD = VD->getCanonicalDecl(); + NamedDecl *ND = cast<NamedDecl>(CanonicalVD); + // OpenMP [2.9.2, Restrictions, C/C++, p.2] + // A threadprivate directive for file-scope variables must appear outside + // any definition or declaration. + if (CanonicalVD->getDeclContext()->isTranslationUnit() && + !getCurLexicalContext()->isTranslationUnit()) { + Diag(Id.getLoc(), diag::err_omp_var_scope) + << getOpenMPDirectiveName(OMPD_threadprivate) << VD; + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : + diag::note_defined_here) << VD; + return ExprError(); + } + // OpenMP [2.9.2, Restrictions, C/C++, p.3] + // A threadprivate directive for static class member variables must appear + // in the class definition, in the same scope in which the member + // variables are declared. + if (CanonicalVD->isStaticDataMember() && + !CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) { + Diag(Id.getLoc(), diag::err_omp_var_scope) + << getOpenMPDirectiveName(OMPD_threadprivate) << VD; + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : + diag::note_defined_here) << VD; + return ExprError(); + } + // OpenMP [2.9.2, Restrictions, C/C++, p.4] + // A threadprivate directive for namespace-scope variables must appear + // outside any definition or declaration other than the namespace + // definition itself. + if (CanonicalVD->getDeclContext()->isNamespace() && + (!getCurLexicalContext()->isFileContext() || + !getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) { + Diag(Id.getLoc(), diag::err_omp_var_scope) + << getOpenMPDirectiveName(OMPD_threadprivate) << VD; + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : + diag::note_defined_here) << VD; + return ExprError(); + } + // OpenMP [2.9.2, Restrictions, C/C++, p.6] + // A threadprivate directive for static block-scope variables must appear + // in the scope of the variable and not in a nested scope. + if (CanonicalVD->isStaticLocal() && CurScope && + !isDeclInScope(ND, getCurLexicalContext(), CurScope)) { + Diag(Id.getLoc(), diag::err_omp_var_scope) + << getOpenMPDirectiveName(OMPD_threadprivate) << VD; + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : + diag::note_defined_here) << VD; + return ExprError(); + } + + // OpenMP [2.9.2, Restrictions, C/C++, p.2-6] + // A threadprivate directive must lexically precede all references to any + // of the variables in its list. + if (VD->isUsed()) { + Diag(Id.getLoc(), diag::err_omp_var_used) + << getOpenMPDirectiveName(OMPD_threadprivate) << VD; + return ExprError(); + } + + QualType ExprType = VD->getType().getNonReferenceType(); + ExprResult DE = BuildDeclRefExpr(VD, ExprType, VK_RValue, Id.getLoc()); + DSAStack->addDSA(VD, cast<DeclRefExpr>(DE.get()), OMPC_threadprivate); + return DE; +} + +Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective( + SourceLocation Loc, + ArrayRef<Expr *> VarList) { + if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) { CurContext->addDecl(D); return DeclGroupPtrTy::make(DeclGroupRef(D)); } @@ -141,18 +526,19 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective( OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl( SourceLocation Loc, - ArrayRef<DeclRefExpr *> VarList) { - SmallVector<DeclRefExpr *, 5> Vars; - for (ArrayRef<DeclRefExpr *>::iterator I = VarList.begin(), + ArrayRef<Expr *> VarList) { + SmallVector<Expr *, 8> Vars; + for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end(); I != E; ++I) { - VarDecl *VD = cast<VarDecl>((*I)->getDecl()); - SourceLocation ILoc = (*I)->getLocation(); + DeclRefExpr *DE = cast<DeclRefExpr>(*I); + VarDecl *VD = cast<VarDecl>(DE->getDecl()); + SourceLocation ILoc = DE->getExprLoc(); // OpenMP [2.9.2, Restrictions, C/C++, p.10] // A threadprivate variable must not have an incomplete type. if (RequireCompleteType(ILoc, VD->getType(), - diag::err_omp_incomplete_type)) { + diag::err_omp_threadprivate_incomplete_type)) { continue; } @@ -160,15 +546,22 @@ OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl( // A threadprivate variable must not have a reference type. if (VD->getType()->isReferenceType()) { Diag(ILoc, diag::err_omp_ref_type_arg) - << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType(); - Diag(VD->getLocation(), diag::note_forward_declaration) << VD; + << getOpenMPDirectiveName(OMPD_threadprivate) + << VD->getType(); + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : + diag::note_defined_here) << VD; continue; } // Check if this is a TLS variable. if (VD->getTLSKind()) { Diag(ILoc, diag::err_omp_var_thread_local) << VD; - Diag(VD->getLocation(), diag::note_forward_declaration) << VD; + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : + diag::note_defined_here) << VD; continue; } @@ -179,3 +572,591 @@ OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl( getCurLexicalContext(), Loc, Vars); } + +namespace { +class DSAAttrChecker : public StmtVisitor<DSAAttrChecker, void> { + DSAStackTy *Stack; + Sema &Actions; + bool ErrorFound; + CapturedStmt *CS; + llvm::SmallVector<Expr *, 8> ImplicitFirstprivate; +public: + void VisitDeclRefExpr(DeclRefExpr *E) { + if(VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) { + // Skip internally declared variables. + if (VD->isLocalVarDecl() && !CS->capturesVariable(VD)) return; + + SourceLocation ELoc = E->getExprLoc(); + + OpenMPDirectiveKind DKind = Stack->getCurrentDirective(); + DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD); + if (DVar.CKind != OMPC_unknown) { + if (DKind == OMPD_task && DVar.CKind != OMPC_shared && + DVar.CKind != OMPC_threadprivate && !DVar.RefExpr) + ImplicitFirstprivate.push_back(DVar.RefExpr); + return; + } + // The default(none) clause requires that each variable that is referenced + // in the construct, and does not have a predetermined data-sharing + // attribute, must have its data-sharing attribute explicitly determined + // by being listed in a data-sharing attribute clause. + if (DVar.CKind == OMPC_unknown && Stack->getDefaultDSA() == DSA_none && + (DKind == OMPD_parallel || DKind == OMPD_task)) { + ErrorFound = true; + Actions.Diag(ELoc, diag::err_omp_no_dsa_for_variable) << VD; + return; + } + + // OpenMP [2.9.3.6, Restrictions, p.2] + // A list item that appears in a reduction clause of the innermost + // enclosing worksharing or parallel construct may not be accessed in an + // explicit task. + // TODO: + + // Define implicit data-sharing attributes for task. + DVar = Stack->getImplicitDSA(VD); + if (DKind == OMPD_task && DVar.CKind != OMPC_shared) + ImplicitFirstprivate.push_back(DVar.RefExpr); + } + } + void VisitOMPExecutableDirective(OMPExecutableDirective *S) { + for (ArrayRef<OMPClause *>::iterator I = S->clauses().begin(), + E = S->clauses().end(); + I != E; ++I) + if (OMPClause *C = *I) + for (StmtRange R = C->children(); R; ++R) + if (Stmt *Child = *R) + Visit(Child); + } + void VisitStmt(Stmt *S) { + for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); + I != E; ++I) + if (Stmt *Child = *I) + if (!isa<OMPExecutableDirective>(Child)) + Visit(Child); + } + + bool isErrorFound() { return ErrorFound; } + ArrayRef<Expr *> getImplicitFirstprivate() { return ImplicitFirstprivate; } + + DSAAttrChecker(DSAStackTy *S, Sema &Actions, CapturedStmt *CS) + : Stack(S), Actions(Actions), ErrorFound(false), CS(CS) { } +}; +} + +StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, + ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc) { + assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); + + StmtResult Res = StmtError(); + + // Check default data sharing attributes for referenced variables. + DSAAttrChecker DSAChecker(DSAStack, *this, cast<CapturedStmt>(AStmt)); + DSAChecker.Visit(cast<CapturedStmt>(AStmt)->getCapturedStmt()); + if (DSAChecker.isErrorFound()) + return StmtError(); + // Generate list of implicitly defined firstprivate variables. + llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit; + ClausesWithImplicit.append(Clauses.begin(), Clauses.end()); + + bool ErrorFound = false; + if (!DSAChecker.getImplicitFirstprivate().empty()) { + if (OMPClause *Implicit = + ActOnOpenMPFirstprivateClause(DSAChecker.getImplicitFirstprivate(), + SourceLocation(), SourceLocation(), + SourceLocation())) { + ClausesWithImplicit.push_back(Implicit); + ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() != + DSAChecker.getImplicitFirstprivate().size(); + } else + ErrorFound = true; + } + + switch (Kind) { + case OMPD_parallel: + Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, + StartLoc, EndLoc); + break; + case OMPD_threadprivate: + case OMPD_task: + llvm_unreachable("OpenMP Directive is not allowed"); + case OMPD_unknown: + case NUM_OPENMP_DIRECTIVES: + llvm_unreachable("Unknown OpenMP directive"); + } + + if (ErrorFound) return StmtError(); + return Res; +} + +StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc) { + getCurFunction()->setHasBranchProtectedScope(); + + return Owned(OMPParallelDirective::Create(Context, StartLoc, EndLoc, + Clauses, AStmt)); +} + +OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, + unsigned Argument, + SourceLocation ArgumentLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + OMPClause *Res = 0; + switch (Kind) { + case OMPC_default: + Res = + ActOnOpenMPDefaultClause(static_cast<OpenMPDefaultClauseKind>(Argument), + ArgumentLoc, StartLoc, LParenLoc, EndLoc); + break; + case OMPC_private: + case OMPC_firstprivate: + case OMPC_shared: + case OMPC_threadprivate: + case OMPC_unknown: + case NUM_OPENMP_CLAUSES: + llvm_unreachable("Clause is not allowed."); + } + return Res; +} + +OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind, + SourceLocation KindKwLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + if (Kind == OMPC_DEFAULT_unknown) { + std::string Values; + std::string Sep(NUM_OPENMP_DEFAULT_KINDS > 1 ? ", " : ""); + for (unsigned i = OMPC_DEFAULT_unknown + 1; + i < NUM_OPENMP_DEFAULT_KINDS; ++i) { + Values += "'"; + Values += getOpenMPSimpleClauseTypeName(OMPC_default, i); + Values += "'"; + switch (i) { + case NUM_OPENMP_DEFAULT_KINDS - 2: + Values += " or "; + break; + case NUM_OPENMP_DEFAULT_KINDS - 1: + break; + default: + Values += Sep; + break; + } + } + Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) + << Values << getOpenMPClauseName(OMPC_default); + return 0; + } + switch (Kind) { + case OMPC_DEFAULT_none: + DSAStack->setDefaultDSANone(); + break; + case OMPC_DEFAULT_shared: + DSAStack->setDefaultDSAShared(); + break; + default: + break; + } + return new (Context) OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, + EndLoc); +} + +OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, + ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + OMPClause *Res = 0; + switch (Kind) { + case OMPC_private: + Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc); + break; + case OMPC_firstprivate: + Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc); + break; + case OMPC_shared: + Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc); + break; + case OMPC_default: + case OMPC_threadprivate: + case OMPC_unknown: + case NUM_OPENMP_CLAUSES: + llvm_unreachable("Clause is not allowed."); + } + return Res; +} + +OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + SmallVector<Expr *, 8> Vars; + for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end(); + I != E; ++I) { + assert(*I && "NULL expr in OpenMP private clause."); + if (isa<DependentScopeDeclRefExpr>(*I)) { + // It will be analyzed later. + Vars.push_back(*I); + continue; + } + + SourceLocation ELoc = (*I)->getExprLoc(); + // OpenMP [2.1, C/C++] + // A list item is a variable name. + // OpenMP [2.9.3.3, Restrictions, p.1] + // A variable that is part of another variable (as an array or + // structure element) cannot appear in a private clause. + DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(*I); + if (!DE || !isa<VarDecl>(DE->getDecl())) { + Diag(ELoc, diag::err_omp_expected_var_name) + << (*I)->getSourceRange(); + continue; + } + Decl *D = DE->getDecl(); + VarDecl *VD = cast<VarDecl>(D); + + QualType Type = VD->getType(); + if (Type->isDependentType() || Type->isInstantiationDependentType()) { + // It will be analyzed later. + Vars.push_back(DE); + continue; + } + + // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] + // A variable that appears in a private clause must not have an incomplete + // type or a reference type. + if (RequireCompleteType(ELoc, Type, + diag::err_omp_private_incomplete_type)) { + continue; + } + if (Type->isReferenceType()) { + Diag(ELoc, diag::err_omp_clause_ref_type_arg) + << getOpenMPClauseName(OMPC_private) << Type; + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : + diag::note_defined_here) << VD; + continue; + } + + // OpenMP [2.9.3.3, Restrictions, C/C++, p.1] + // A variable of class type (or array thereof) that appears in a private + // clause requires an accesible, unambiguous default constructor for the + // class type. + while (Type.getNonReferenceType()->isArrayType()) { + Type = cast<ArrayType>( + Type.getNonReferenceType().getTypePtr())->getElementType(); + } + CXXRecordDecl *RD = getLangOpts().CPlusPlus ? + Type.getNonReferenceType()->getAsCXXRecordDecl() : 0; + if (RD) { + CXXConstructorDecl *CD = LookupDefaultConstructor(RD); + PartialDiagnostic PD = + PartialDiagnostic(PartialDiagnostic::NullDiagnostic()); + if (!CD || + CheckConstructorAccess(ELoc, CD, + InitializedEntity::InitializeTemporary(Type), + CD->getAccess(), PD) == AR_inaccessible || + CD->isDeleted()) { + Diag(ELoc, diag::err_omp_required_method) + << getOpenMPClauseName(OMPC_private) << 0; + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : + diag::note_defined_here) << VD; + Diag(RD->getLocation(), diag::note_previous_decl) << RD; + continue; + } + MarkFunctionReferenced(ELoc, CD); + DiagnoseUseOfDecl(CD, ELoc); + + CXXDestructorDecl *DD = RD->getDestructor(); + if (DD) { + if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible || + DD->isDeleted()) { + Diag(ELoc, diag::err_omp_required_method) + << getOpenMPClauseName(OMPC_private) << 4; + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : + diag::note_defined_here) << VD; + Diag(RD->getLocation(), diag::note_previous_decl) << RD; + continue; + } + MarkFunctionReferenced(ELoc, DD); + DiagnoseUseOfDecl(DD, ELoc); + } + } + + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct] + // Variables with the predetermined data-sharing attributes may not be + // listed in data-sharing attributes clauses, except for the cases + // listed below. For these exceptions only, listing a predetermined + // variable in a data-sharing attribute clause is allowed and overrides + // the variable's predetermined data-sharing attributes. + DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD); + if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) { + Diag(ELoc, diag::err_omp_wrong_dsa) + << getOpenMPClauseName(DVar.CKind) + << getOpenMPClauseName(OMPC_private); + if (DVar.RefExpr) { + Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa) + << getOpenMPClauseName(DVar.CKind); + } else { + Diag(VD->getLocation(), diag::note_omp_predetermined_dsa) + << getOpenMPClauseName(DVar.CKind); + } + continue; + } + + DSAStack->addDSA(VD, DE, OMPC_private); + Vars.push_back(DE); + } + + if (Vars.empty()) return 0; + + return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars); +} + +OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + SmallVector<Expr *, 8> Vars; + for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end(); + I != E; ++I) { + assert(*I && "NULL expr in OpenMP firstprivate clause."); + if (isa<DependentScopeDeclRefExpr>(*I)) { + // It will be analyzed later. + Vars.push_back(*I); + continue; + } + + SourceLocation ELoc = (*I)->getExprLoc(); + // OpenMP [2.1, C/C++] + // A list item is a variable name. + // OpenMP [2.9.3.3, Restrictions, p.1] + // A variable that is part of another variable (as an array or + // structure element) cannot appear in a private clause. + DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(*I); + if (!DE || !isa<VarDecl>(DE->getDecl())) { + Diag(ELoc, diag::err_omp_expected_var_name) + << (*I)->getSourceRange(); + continue; + } + Decl *D = DE->getDecl(); + VarDecl *VD = cast<VarDecl>(D); + + QualType Type = VD->getType(); + if (Type->isDependentType() || Type->isInstantiationDependentType()) { + // It will be analyzed later. + Vars.push_back(DE); + continue; + } + + // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] + // A variable that appears in a private clause must not have an incomplete + // type or a reference type. + if (RequireCompleteType(ELoc, Type, + diag::err_omp_firstprivate_incomplete_type)) { + continue; + } + if (Type->isReferenceType()) { + Diag(ELoc, diag::err_omp_clause_ref_type_arg) + << getOpenMPClauseName(OMPC_firstprivate) << Type; + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : + diag::note_defined_here) << VD; + continue; + } + + // OpenMP [2.9.3.4, Restrictions, C/C++, p.1] + // A variable of class type (or array thereof) that appears in a private + // clause requires an accesible, unambiguous copy constructor for the + // class type. + Type = Context.getBaseElementType(Type); + CXXRecordDecl *RD = getLangOpts().CPlusPlus ? + Type.getNonReferenceType()->getAsCXXRecordDecl() : 0; + if (RD) { + CXXConstructorDecl *CD = LookupCopyingConstructor(RD, 0); + PartialDiagnostic PD = + PartialDiagnostic(PartialDiagnostic::NullDiagnostic()); + if (!CD || + CheckConstructorAccess(ELoc, CD, + InitializedEntity::InitializeTemporary(Type), + CD->getAccess(), PD) == AR_inaccessible || + CD->isDeleted()) { + Diag(ELoc, diag::err_omp_required_method) + << getOpenMPClauseName(OMPC_firstprivate) << 1; + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : + diag::note_defined_here) << VD; + Diag(RD->getLocation(), diag::note_previous_decl) << RD; + continue; + } + MarkFunctionReferenced(ELoc, CD); + DiagnoseUseOfDecl(CD, ELoc); + + CXXDestructorDecl *DD = RD->getDestructor(); + if (DD) { + if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible || + DD->isDeleted()) { + Diag(ELoc, diag::err_omp_required_method) + << getOpenMPClauseName(OMPC_firstprivate) << 4; + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : + diag::note_defined_here) << VD; + Diag(RD->getLocation(), diag::note_previous_decl) << RD; + continue; + } + MarkFunctionReferenced(ELoc, DD); + DiagnoseUseOfDecl(DD, ELoc); + } + } + + // If StartLoc and EndLoc are invalid - this is an implicit firstprivate + // variable and it was checked already. + if (StartLoc.isValid() && EndLoc.isValid()) { + DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD); + Type = Type.getNonReferenceType().getCanonicalType(); + bool IsConstant = Type.isConstant(Context); + Type = Context.getBaseElementType(Type); + // OpenMP [2.4.13, Data-sharing Attribute Clauses] + // A list item that specifies a given variable may not appear in more + // than one clause on the same directive, except that a variable may be + // specified in both firstprivate and lastprivate clauses. + // TODO: add processing for lastprivate. + if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate && + DVar.RefExpr) { + Diag(ELoc, diag::err_omp_wrong_dsa) + << getOpenMPClauseName(DVar.CKind) + << getOpenMPClauseName(OMPC_firstprivate); + Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa) + << getOpenMPClauseName(DVar.CKind); + continue; + } + + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct] + // Variables with the predetermined data-sharing attributes may not be + // listed in data-sharing attributes clauses, except for the cases + // listed below. For these exceptions only, listing a predetermined + // variable in a data-sharing attribute clause is allowed and overrides + // the variable's predetermined data-sharing attributes. + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct, C/C++, p.2] + // Variables with const-qualified type having no mutable member may be + // listed in a firstprivate clause, even if they are static data members. + if (!(IsConstant || VD->isStaticDataMember()) && !DVar.RefExpr && + DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) { + Diag(ELoc, diag::err_omp_wrong_dsa) + << getOpenMPClauseName(DVar.CKind) + << getOpenMPClauseName(OMPC_firstprivate); + Diag(VD->getLocation(), diag::note_omp_predetermined_dsa) + << getOpenMPClauseName(DVar.CKind); + continue; + } + + // OpenMP [2.9.3.4, Restrictions, p.2] + // A list item that is private within a parallel region must not appear + // in a firstprivate clause on a worksharing construct if any of the + // worksharing regions arising from the worksharing construct ever bind + // to any of the parallel regions arising from the parallel construct. + // OpenMP [2.9.3.4, Restrictions, p.3] + // A list item that appears in a reduction clause of a parallel construct + // must not appear in a firstprivate clause on a worksharing or task + // construct if any of the worksharing or task regions arising from the + // worksharing or task construct ever bind to any of the parallel regions + // arising from the parallel construct. + // OpenMP [2.9.3.4, Restrictions, p.4] + // A list item that appears in a reduction clause in worksharing + // construct must not appear in a firstprivate clause in a task construct + // encountered during execution of any of the worksharing regions arising + // from the worksharing construct. + // TODO: + } + + DSAStack->addDSA(VD, DE, OMPC_firstprivate); + Vars.push_back(DE); + } + + if (Vars.empty()) return 0; + + return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, + Vars); +} + +OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + SmallVector<Expr *, 8> Vars; + for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end(); + I != E; ++I) { + assert(*I && "NULL expr in OpenMP shared clause."); + if (isa<DependentScopeDeclRefExpr>(*I)) { + // It will be analyzed later. + Vars.push_back(*I); + continue; + } + + SourceLocation ELoc = (*I)->getExprLoc(); + // OpenMP [2.1, C/C++] + // A list item is a variable name. + // OpenMP [2.9.3.4, Restrictions, p.1] + // A variable that is part of another variable (as an array or + // structure element) cannot appear in a private clause. + DeclRefExpr *DE = dyn_cast<DeclRefExpr>(*I); + if (!DE || !isa<VarDecl>(DE->getDecl())) { + Diag(ELoc, diag::err_omp_expected_var_name) + << (*I)->getSourceRange(); + continue; + } + Decl *D = DE->getDecl(); + VarDecl *VD = cast<VarDecl>(D); + + QualType Type = VD->getType(); + if (Type->isDependentType() || Type->isInstantiationDependentType()) { + // It will be analyzed later. + Vars.push_back(DE); + continue; + } + + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct] + // Variables with the predetermined data-sharing attributes may not be + // listed in data-sharing attributes clauses, except for the cases + // listed below. For these exceptions only, listing a predetermined + // variable in a data-sharing attribute clause is allowed and overrides + // the variable's predetermined data-sharing attributes. + DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD); + if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared && DVar.RefExpr) { + Diag(ELoc, diag::err_omp_wrong_dsa) + << getOpenMPClauseName(DVar.CKind) + << getOpenMPClauseName(OMPC_shared); + Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa) + << getOpenMPClauseName(DVar.CKind); + continue; + } + + DSAStack->addDSA(VD, DE, OMPC_shared); + Vars.push_back(DE); + } + + if (Vars.empty()) return 0; + + return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars); +} + +#undef DSAStack diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp index 529ba127cbab..802f2b7290b3 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp @@ -21,6 +21,7 @@ #include "clang/AST/TypeOrdering.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -43,8 +44,15 @@ CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl, SourceLocation Loc = SourceLocation(), const DeclarationNameLoc &LocInfo = DeclarationNameLoc()){ if (S.DiagnoseUseOfDecl(FoundDecl, Loc)) + return ExprError(); + // If FoundDecl is different from Fn (such as if one is a template + // and the other a specialization), make sure DiagnoseUseOfDecl is + // called on both. + // FIXME: This would be more comprehensively addressed by modifying + // DiagnoseUseOfDecl to accept both the FoundDecl and the decl + // being used. + if (FoundDecl != Fn && S.DiagnoseUseOfDecl(Fn, Loc)) return ExprError(); - DeclRefExpr *DRE = new (S.Context) DeclRefExpr(Fn, false, Fn->getType(), VK_LValue, Loc, LocInfo); if (HadMultipleCandidates) @@ -74,7 +82,8 @@ static OverloadingResult IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, UserDefinedConversionSequence& User, OverloadCandidateSet& Conversions, - bool AllowExplicit); + bool AllowExplicit, + bool AllowObjCConversionOnExplicit); static ImplicitConversionSequence::CompareKind @@ -441,9 +450,9 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx, } } -/// DebugPrint - Print this standard conversion sequence to standard +/// dump - Print this standard conversion sequence to standard /// error. Useful for debugging overloading issues. -void StandardConversionSequence::DebugPrint() const { +void StandardConversionSequence::dump() const { raw_ostream &OS = llvm::errs(); bool PrintedSomething = false; if (First != ICK_Identity) { @@ -480,12 +489,12 @@ void StandardConversionSequence::DebugPrint() const { } } -/// DebugPrint - Print this user-defined conversion sequence to standard +/// dump - Print this user-defined conversion sequence to standard /// error. Useful for debugging overloading issues. -void UserDefinedConversionSequence::DebugPrint() const { +void UserDefinedConversionSequence::dump() const { raw_ostream &OS = llvm::errs(); if (Before.First || Before.Second || Before.Third) { - Before.DebugPrint(); + Before.dump(); OS << " -> "; } if (ConversionFunction) @@ -494,22 +503,24 @@ void UserDefinedConversionSequence::DebugPrint() const { OS << "aggregate initialization"; if (After.First || After.Second || After.Third) { OS << " -> "; - After.DebugPrint(); + After.dump(); } } -/// DebugPrint - Print this implicit conversion sequence to standard +/// dump - Print this implicit conversion sequence to standard /// error. Useful for debugging overloading issues. -void ImplicitConversionSequence::DebugPrint() const { +void ImplicitConversionSequence::dump() const { raw_ostream &OS = llvm::errs(); + if (isStdInitializerListElement()) + OS << "Worst std::initializer_list element conversion: "; switch (ConversionKind) { case StandardConversion: OS << "Standard conversion: "; - Standard.DebugPrint(); + Standard.dump(); break; case UserDefinedConversion: OS << "User-defined conversion: "; - UserDefined.DebugPrint(); + UserDefined.dump(); break; case EllipsisConversion: OS << "Ellipsis conversion"; @@ -541,13 +552,13 @@ AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) { } namespace { - // Structure used by OverloadCandidate::DeductionFailureInfo to store + // Structure used by DeductionFailureInfo to store // template argument information. struct DFIArguments { TemplateArgument FirstArg; TemplateArgument SecondArg; }; - // Structure used by OverloadCandidate::DeductionFailureInfo to store + // Structure used by DeductionFailureInfo to store // template parameter and template argument information. struct DFIParamWithArguments : DFIArguments { TemplateParameter Param; @@ -556,11 +567,10 @@ namespace { /// \brief Convert from Sema's representation of template deduction information /// to the form used in overload-candidate information. -OverloadCandidate::DeductionFailureInfo -static MakeDeductionFailureInfo(ASTContext &Context, - Sema::TemplateDeductionResult TDK, - TemplateDeductionInfo &Info) { - OverloadCandidate::DeductionFailureInfo Result; +DeductionFailureInfo MakeDeductionFailureInfo(ASTContext &Context, + Sema::TemplateDeductionResult TDK, + TemplateDeductionInfo &Info) { + DeductionFailureInfo Result; Result.Result = static_cast<unsigned>(TDK); Result.HasDiagnostic = false; Result.Data = 0; @@ -618,7 +628,7 @@ static MakeDeductionFailureInfo(ASTContext &Context, return Result; } -void OverloadCandidate::DeductionFailureInfo::Destroy() { +void DeductionFailureInfo::Destroy() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { case Sema::TDK_Success: case Sema::TDK_Invalid: @@ -652,15 +662,13 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() { } } -PartialDiagnosticAt * -OverloadCandidate::DeductionFailureInfo::getSFINAEDiagnostic() { +PartialDiagnosticAt *DeductionFailureInfo::getSFINAEDiagnostic() { if (HasDiagnostic) return static_cast<PartialDiagnosticAt*>(static_cast<void*>(Diagnostic)); return 0; } -TemplateParameter -OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { +TemplateParameter DeductionFailureInfo::getTemplateParameter() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { case Sema::TDK_Success: case Sema::TDK_Invalid: @@ -688,8 +696,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { return TemplateParameter(); } -TemplateArgumentList * -OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() { +TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { case Sema::TDK_Success: case Sema::TDK_Invalid: @@ -715,7 +722,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() { return 0; } -const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() { +const TemplateArgument *DeductionFailureInfo::getFirstArg() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { case Sema::TDK_Success: case Sema::TDK_Invalid: @@ -741,8 +748,7 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() { return 0; } -const TemplateArgument * -OverloadCandidate::DeductionFailureInfo::getSecondArg() { +const TemplateArgument *DeductionFailureInfo::getSecondArg() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { case Sema::TDK_Success: case Sema::TDK_Invalid: @@ -768,8 +774,7 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() { return 0; } -Expr * -OverloadCandidate::DeductionFailureInfo::getExpr() { +Expr *DeductionFailureInfo::getExpr() { if (static_cast<Sema::TemplateDeductionResult>(Result) == Sema::TDK_FailedOverloadResolution) return static_cast<Expr*>(Data); @@ -854,11 +859,11 @@ static bool checkPlaceholderForOverload(Sema &S, Expr *&E, /// checkArgPlaceholdersForOverload - Check a set of call operands for /// placeholders. -static bool checkArgPlaceholdersForOverload(Sema &S, Expr **args, - unsigned numArgs, +static bool checkArgPlaceholdersForOverload(Sema &S, + MultiExprArg Args, UnbridgedCastsSet &unbridged) { - for (unsigned i = 0; i != numArgs; ++i) - if (checkPlaceholderForOverload(S, args[i], &unbridged)) + for (unsigned i = 0, e = Args.size(); i != e; ++i) + if (checkPlaceholderForOverload(S, Args[i], &unbridged)) return true; return false; @@ -970,21 +975,16 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, return Ovl_Overload; } -static bool canBeOverloaded(const FunctionDecl &D) { - if (D.getAttr<OverloadableAttr>()) - return true; - if (D.isExternC()) +bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, + bool UseUsingDeclRules) { + // C++ [basic.start.main]p2: This function shall not be overloaded. + if (New->isMain()) return false; - // Main cannot be overloaded (basic.start.main). - if (D.isMain()) + // MSVCRT user defined entry points cannot be overloaded. + if (New->isMSVCRTEntryPoint()) return false; - return true; -} - -static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old, - bool UseUsingDeclRules) { FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate(); FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate(); @@ -995,8 +995,8 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old, return true; // Is the function New an overload of the function Old? - QualType OldQType = S.Context.getCanonicalType(Old->getType()); - QualType NewQType = S.Context.getCanonicalType(New->getType()); + QualType OldQType = Context.getCanonicalType(Old->getType()); + QualType NewQType = Context.getCanonicalType(New->getType()); // Compare the signatures (C++ 1.3.10) of the two functions to // determine whether they are overloads. If we find any mismatch @@ -1017,7 +1017,7 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old, if (OldQType != NewQType && (OldType->getNumArgs() != NewType->getNumArgs() || OldType->isVariadic() != NewType->isVariadic() || - !S.FunctionArgTypesAreEqual(OldType, NewType))) + !FunctionArgTypesAreEqual(OldType, NewType))) return true; // C++ [temp.over.link]p4: @@ -1033,9 +1033,9 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old, // However, we don't consider either of these when deciding whether // a member introduced by a shadow declaration is hidden. if (!UseUsingDeclRules && NewTemplate && - (!S.TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), - OldTemplate->getTemplateParameters(), - false, S.TPL_TemplateMatch) || + (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), + OldTemplate->getTemplateParameters(), + false, TPL_TemplateMatch) || OldType->getResultType() != NewType->getResultType())) return true; @@ -1061,9 +1061,9 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old, // declarations with the same name, the same parameter-type-list, and // the same template parameter lists cannot be overloaded if any of // them, but not all, have a ref-qualifier (8.3.5). - S.Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload) + Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload) << NewMethod->getRefQualifier() << OldMethod->getRefQualifier(); - S.Diag(OldMethod->getLocation(), diag::note_previous_declaration); + Diag(OldMethod->getLocation(), diag::note_previous_declaration); } return true; } @@ -1072,10 +1072,16 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old, // function yet (because we haven't yet resolved whether this is a static // or non-static member function). Add it now, on the assumption that this // is a redeclaration of OldMethod. + unsigned OldQuals = OldMethod->getTypeQualifiers(); unsigned NewQuals = NewMethod->getTypeQualifiers(); - if (NewMethod->isConstexpr() && !isa<CXXConstructorDecl>(NewMethod)) + if (!getLangOpts().CPlusPlus1y && NewMethod->isConstexpr() && + !isa<CXXConstructorDecl>(NewMethod)) NewQuals |= Qualifiers::Const; - if (OldMethod->getTypeQualifiers() != NewQuals) + + // We do not allow overloading based off of '__restrict'. + OldQuals &= ~Qualifiers::Restrict; + NewQuals &= ~Qualifiers::Restrict; + if (OldQuals != NewQuals) return true; } @@ -1083,19 +1089,6 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old, return false; } -bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, - bool UseUsingDeclRules) { - if (!shouldTryToOverload(*this, New, Old, UseUsingDeclRules)) - return false; - - // If both of the functions are extern "C", then they are not - // overloads. - if (!canBeOverloaded(*Old) && !canBeOverloaded(*New)) - return false; - - return true; -} - /// \brief Checks availability of the function depending on the current /// function context. Inside an unavailable function, unavailability is ignored. /// @@ -1115,7 +1108,8 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType, bool AllowExplicit, bool InOverloadResolution, bool CStyle, - bool AllowObjCWritebackConversion) { + bool AllowObjCWritebackConversion, + bool AllowObjCConversionOnExplicit) { ImplicitConversionSequence ICS; if (SuppressUserConversions) { @@ -1129,7 +1123,7 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType, OverloadCandidateSet Conversions(From->getExprLoc()); OverloadingResult UserDefResult = IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions, - AllowExplicit); + AllowExplicit, AllowObjCConversionOnExplicit); if (UserDefResult == OR_Success) { ICS.setUserDefined(); @@ -1218,7 +1212,8 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType, bool AllowExplicit, bool InOverloadResolution, bool CStyle, - bool AllowObjCWritebackConversion) { + bool AllowObjCWritebackConversion, + bool AllowObjCConversionOnExplicit) { ImplicitConversionSequence ICS; if (IsStandardConversion(S, From, ToType, InOverloadResolution, ICS.Standard, CStyle, AllowObjCWritebackConversion)){ @@ -1262,7 +1257,8 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType, return TryUserDefinedConversion(S, From, ToType, SuppressUserConversions, AllowExplicit, InOverloadResolution, CStyle, - AllowObjCWritebackConversion); + AllowObjCWritebackConversion, + AllowObjCConversionOnExplicit); } ImplicitConversionSequence @@ -1275,7 +1271,8 @@ Sema::TryImplicitConversion(Expr *From, QualType ToType, return clang::TryImplicitConversion(*this, From, ToType, SuppressUserConversions, AllowExplicit, InOverloadResolution, CStyle, - AllowObjCWritebackConversion); + AllowObjCWritebackConversion, + /*AllowObjCConversionOnExplicit=*/false); } /// PerformImplicitConversion - Perform an implicit conversion of the @@ -1307,7 +1304,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, AllowExplicit, /*InOverloadResolution=*/false, /*CStyle=*/false, - AllowObjCWritebackConversion); + AllowObjCWritebackConversion, + /*AllowObjCConversionOnExplicit=*/false); return PerformImplicitConversion(From, ToType, ICS, Action); } @@ -1591,7 +1589,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // Integral conversions (C++ 4.7). SCS.Second = ICK_Integral_Conversion; FromType = ToType.getUnqualifiedType(); - } else if (FromType->isAnyComplexType() && ToType->isComplexType()) { + } else if (FromType->isAnyComplexType() && ToType->isAnyComplexType()) { // Complex conversions (C99 6.3.1.6) SCS.Second = ICK_Complex_Conversion; FromType = ToType.getUnqualifiedType(); @@ -2596,48 +2594,16 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, /// FunctionArgTypesAreEqual - This routine checks two function proto types /// 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 parameter index -/// of the first different parameter. +/// they have same number of arguments. If the parameters are different, +/// ArgPos will have the parameter index of the first different parameter. bool Sema::FunctionArgTypesAreEqual(const FunctionProtoType *OldType, const FunctionProtoType *NewType, unsigned *ArgPos) { - 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 (!Context.hasSameType(ToType, FromType)) { - if (const PointerType *PTTo = ToType->getAs<PointerType>()) { - if (const PointerType *PTFr = FromType->getAs<PointerType>()) - if ((PTTo->getPointeeType()->isObjCQualifiedIdType() && - PTFr->getPointeeType()->isObjCQualifiedIdType()) || - (PTTo->getPointeeType()->isObjCQualifiedClassType() && - PTFr->getPointeeType()->isObjCQualifiedClassType())) - continue; - } - else if (const ObjCObjectPointerType *PTTo = - ToType->getAs<ObjCObjectPointerType>()) { - if (const ObjCObjectPointerType *PTFr = - FromType->getAs<ObjCObjectPointerType>()) - if (Context.hasSameUnqualifiedType( - PTTo->getObjectType()->getBaseType(), - PTFr->getObjectType()->getBaseType())) - continue; - } + if (!Context.hasSameType(O->getUnqualifiedType(), + N->getUnqualifiedType())) { if (ArgPos) *ArgPos = O - OldType->arg_type_begin(); return false; } @@ -2824,6 +2790,18 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, return false; } +/// Determine whether the lifetime conversion between the two given +/// qualifiers sets is nontrivial. +static bool isNonTrivialObjCLifetimeConversion(Qualifiers FromQuals, + Qualifiers ToQuals) { + // Converting anything to const __unsafe_unretained is trivial. + if (ToQuals.hasConst() && + ToQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone) + return false; + + return true; +} + /// IsQualificationConversion - Determines whether the conversion from /// an rvalue of type FromType to ToType is a qualification conversion /// (C++ 4.4). @@ -2865,7 +2843,8 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType, if (FromQuals.getObjCLifetime() != ToQuals.getObjCLifetime() && UnwrappedAnyPointer) { if (ToQuals.compatiblyIncludesObjCLifetime(FromQuals)) { - ObjCLifetimeConversion = true; + if (isNonTrivialObjCLifetimeConversion(FromQuals, ToQuals)) + ObjCLifetimeConversion = true; FromQuals.removeObjCLifetime(); ToQuals.removeObjCLifetime(); } else { @@ -3030,11 +3009,18 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, /// \param AllowExplicit true if the conversion should consider C++0x /// "explicit" conversion functions as well as non-explicit conversion /// functions (C++0x [class.conv.fct]p2). +/// +/// \param AllowObjCConversionOnExplicit true if the conversion should +/// allow an extra Objective-C pointer conversion on uses of explicit +/// constructors. Requires \c AllowExplicit to also be set. static OverloadingResult IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, UserDefinedConversionSequence &User, OverloadCandidateSet &CandidateSet, - bool AllowExplicit) { + bool AllowExplicit, + bool AllowObjCConversionOnExplicit) { + assert(AllowExplicit || !AllowObjCConversionOnExplicit); + // Whether we will only visit constructors. bool ConstructorsOnly = false; @@ -3067,7 +3053,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, 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. + // But first, see if there is an init-list-constructor that will work. OverloadingResult Result = IsInitializerListConstructorConversion( S, From, ToType, ToRecordDecl, User, CandidateSet, AllowExplicit); if (Result != OR_No_Viable_Function) @@ -3161,10 +3147,12 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, if (ConvTemplate) S.AddTemplateConversionCandidate(ConvTemplate, FoundDecl, ActingContext, From, ToType, - CandidateSet); + CandidateSet, + AllowObjCConversionOnExplicit); else S.AddConversionCandidate(Conv, FoundDecl, ActingContext, - From, ToType, CandidateSet); + From, ToType, CandidateSet, + AllowObjCConversionOnExplicit); } } } @@ -3251,15 +3239,19 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { OverloadCandidateSet CandidateSet(From->getExprLoc()); OverloadingResult OvResult = IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined, - CandidateSet, false); + CandidateSet, false, false); if (OvResult == OR_Ambiguous) Diag(From->getLocStart(), diag::err_typecheck_ambiguous_condition) << From->getType() << ToType << From->getSourceRange(); - else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty()) - Diag(From->getLocStart(), - diag::err_typecheck_nonviable_condition) - << From->getType() << ToType << From->getSourceRange(); + else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty()) { + if (!RequireCompleteType(From->getLocStart(), ToType, + diag::err_typecheck_nonviable_condition_incomplete, + From->getType(), From->getSourceRange())) + Diag(From->getLocStart(), + diag::err_typecheck_nonviable_condition) + << From->getType() << From->getSourceRange() << ToType; + } else return false; CandidateSet.NoteCandidates(*this, OCD_AllCandidates, From); @@ -3364,9 +3356,7 @@ CompareImplicitConversionSequences(Sema &S, // 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()) { + !ICS1.isBad()) { if (ICS1.isStdInitializerListElement() && !ICS2.isStdInitializerListElement()) return ImplicitConversionSequence::Better; @@ -4019,9 +4009,11 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, // space 2. if (T1Quals.getObjCLifetime() != T2Quals.getObjCLifetime() && T1Quals.compatiblyIncludesObjCLifetime(T2Quals)) { + if (isNonTrivialObjCLifetimeConversion(T2Quals, T1Quals)) + ObjCLifetimeConversion = true; + T1Quals.removeObjCLifetime(); T2Quals.removeObjCLifetime(); - ObjCLifetimeConversion = true; } if (T1Quals == T2Quals) @@ -4105,10 +4097,12 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, if (ConvTemplate) S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, - Init, DeclType, CandidateSet); + Init, DeclType, CandidateSet, + /*AllowObjCConversionOnExplicit=*/false); else S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init, - DeclType, CandidateSet); + DeclType, CandidateSet, + /*AllowObjCConversionOnExplicit=*/false); } bool HadMultipleCandidates = (CandidateSet.size() > 1); @@ -4390,7 +4384,8 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, /*AllowExplicit=*/false, /*InOverloadResolution=*/false, /*CStyle=*/false, - /*AllowObjCWritebackConversion=*/false); + /*AllowObjCWritebackConversion=*/false, + /*AllowObjCConversionOnExplicit=*/false); // Of course, that's still a reference binding. if (ICS.isStandard()) { @@ -4445,7 +4440,6 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, 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. @@ -4491,7 +4485,6 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, Result.Standard.setAllToTypes(ToType); } - Result.setListInitializationSequence(); Result.setStdInitializerListElement(toStdInitializerList); return Result; } @@ -4504,12 +4497,11 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, // 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; + return TryUserDefinedConversion(S, From, ToType, SuppressUserConversions, + /*AllowExplicit=*/false, + InOverloadResolution, /*CStyle=*/false, + AllowObjCWritebackConversion, + /*AllowObjCConversionOnExplicit=*/false); } // C++11 [over.ics.list]p4: @@ -4572,11 +4564,11 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, = S.CompareReferenceRelationship(From->getLocStart(), T1, T2, dummy1, dummy2, dummy3); - if (RefRelationship >= Sema::Ref_Related) - return TryReferenceInit(S, Init, ToType, - /*FIXME:*/From->getLocStart(), + 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 @@ -4626,7 +4618,6 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, Result.Standard.setFromType(ToType); Result.Standard.setAllToTypes(ToType); } - Result.setListInitializationSequence(); return Result; } @@ -4662,7 +4653,8 @@ TryCopyInitialization(Sema &S, Expr *From, QualType ToType, /*AllowExplicit=*/false, InOverloadResolution, /*CStyle=*/false, - AllowObjCWritebackConversion); + AllowObjCWritebackConversion, + /*AllowObjCConversionOnExplicit=*/false); } static bool TryCopyInitialization(const CanQualType FromQTy, @@ -4857,14 +4849,13 @@ Sema::PerformObjectArgumentInitialization(Expr *From, /// expression From to bool (C++0x [conv]p3). static ImplicitConversionSequence TryContextuallyConvertToBool(Sema &S, Expr *From) { - // FIXME: This is pretty broken. return TryImplicitConversion(S, From, S.Context.BoolTy, - // FIXME: Are these flags correct? /*SuppressUserConversions=*/false, /*AllowExplicit=*/true, /*InOverloadResolution=*/false, /*CStyle=*/false, - /*AllowObjCWritebackConversion=*/false); + /*AllowObjCWritebackConversion=*/false, + /*AllowObjCConversionOnExplicit=*/false); } /// PerformContextuallyConvertToBool - Perform a contextual conversion @@ -5009,17 +5000,13 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T, break; case NK_Constant_Narrowing: - Diag(From->getLocStart(), - isSFINAEContext() ? diag::err_cce_narrowing_sfinae : - diag::err_cce_narrowing) + Diag(From->getLocStart(), diag::ext_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) + Diag(From->getLocStart(), diag::ext_cce_narrowing) << CCE << /*Constant*/0 << From->getType() << T; break; } @@ -5079,7 +5066,8 @@ TryContextuallyConvertToObjCPointer(Sema &S, Expr *From) { /*AllowExplicit=*/true, /*InOverloadResolution=*/false, /*CStyle=*/false, - /*AllowObjCWritebackConversion=*/false); + /*AllowObjCWritebackConversion=*/false, + /*AllowObjCConversionOnExplicit=*/true); // Strip off any final conversions to 'id'. switch (ICS.getKind()) { @@ -5116,34 +5104,157 @@ ExprResult Sema::PerformContextuallyConvertToObjCPointer(Expr *From) { /// 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(); +bool Sema::ICEConvertDiagnoser::match(QualType T) { + return AllowScopedEnumerations ? T->isIntegralOrEnumerationType() + : T->isIntegralOrUnscopedEnumerationType(); +} + +static ExprResult +diagnoseAmbiguousConversion(Sema &SemaRef, SourceLocation Loc, Expr *From, + Sema::ContextualImplicitConverter &Converter, + QualType T, UnresolvedSetImpl &ViableConversions) { + + if (Converter.Suppress) + return ExprError(); + + Converter.diagnoseAmbiguous(SemaRef, Loc, T) << From->getSourceRange(); + for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) { + CXXConversionDecl *Conv = + cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl()); + QualType ConvTy = Conv->getConversionType().getNonReferenceType(); + Converter.noteAmbiguous(SemaRef, Conv, ConvTy); + } + return SemaRef.Owned(From); +} + +static bool +diagnoseNoViableConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From, + Sema::ContextualImplicitConverter &Converter, + QualType T, bool HadMultipleCandidates, + UnresolvedSetImpl &ExplicitConversions) { + if (ExplicitConversions.size() == 1 && !Converter.Suppress) { + DeclAccessPair Found = ExplicitConversions[0]; + CXXConversionDecl *Conversion = + cast<CXXConversionDecl>(Found->getUnderlyingDecl()); + + // The user probably meant to invoke the given explicit + // conversion; use it. + QualType ConvTy = Conversion->getConversionType().getNonReferenceType(); + std::string TypeStr; + ConvTy.getAsStringInternal(TypeStr, SemaRef.getPrintingPolicy()); + + Converter.diagnoseExplicitConv(SemaRef, Loc, T, ConvTy) + << FixItHint::CreateInsertion(From->getLocStart(), + "static_cast<" + TypeStr + ">(") + << FixItHint::CreateInsertion( + SemaRef.PP.getLocForEndOfToken(From->getLocEnd()), ")"); + Converter.noteExplicitConv(SemaRef, Conversion, ConvTy); + + // If we aren't in a SFINAE context, build a call to the + // explicit conversion function. + if (SemaRef.isSFINAEContext()) + return true; + + SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); + ExprResult Result = SemaRef.BuildCXXMemberCallExpr(From, Found, Conversion, + HadMultipleCandidates); + if (Result.isInvalid()) + return true; + // Record usage of conversion in an implicit cast. + From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(), + CK_UserDefinedConversion, Result.get(), 0, + Result.get()->getValueKind()); + } + return false; +} + +static bool recordConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From, + Sema::ContextualImplicitConverter &Converter, + QualType T, bool HadMultipleCandidates, + DeclAccessPair &Found) { + CXXConversionDecl *Conversion = + cast<CXXConversionDecl>(Found->getUnderlyingDecl()); + SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); + + QualType ToType = Conversion->getConversionType().getNonReferenceType(); + if (!Converter.SuppressConversion) { + if (SemaRef.isSFINAEContext()) + return true; + + Converter.diagnoseConversion(SemaRef, Loc, T, ToType) + << From->getSourceRange(); + } + + ExprResult Result = SemaRef.BuildCXXMemberCallExpr(From, Found, Conversion, + HadMultipleCandidates); + if (Result.isInvalid()) + return true; + // Record usage of conversion in an implicit cast. + From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(), + CK_UserDefinedConversion, Result.get(), 0, + Result.get()->getValueKind()); + return false; +} + +static ExprResult finishContextualImplicitConversion( + Sema &SemaRef, SourceLocation Loc, Expr *From, + Sema::ContextualImplicitConverter &Converter) { + if (!Converter.match(From->getType()) && !Converter.Suppress) + Converter.diagnoseNoMatch(SemaRef, Loc, From->getType()) + << From->getSourceRange(); + + return SemaRef.DefaultLvalueConversion(From); +} + +static void +collectViableConversionCandidates(Sema &SemaRef, Expr *From, QualType ToType, + UnresolvedSetImpl &ViableConversions, + OverloadCandidateSet &CandidateSet) { + for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) { + DeclAccessPair FoundDecl = ViableConversions[I]; + NamedDecl *D = FoundDecl.getDecl(); + CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext()); + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); + + CXXConversionDecl *Conv; + FunctionTemplateDecl *ConvTemplate; + if ((ConvTemplate = dyn_cast<FunctionTemplateDecl>(D))) + Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl()); + else + Conv = cast<CXXConversionDecl>(D); + + if (ConvTemplate) + SemaRef.AddTemplateConversionCandidate( + ConvTemplate, FoundDecl, ActingContext, From, ToType, CandidateSet, + /*AllowObjCConversionOnExplicit=*/false); + else + SemaRef.AddConversionCandidate(Conv, FoundDecl, ActingContext, From, + ToType, CandidateSet, + /*AllowObjCConversionOnExplicit=*/false); + } } -/// \brief Attempt to convert the given expression to an integral or -/// enumeration type. +/// \brief Attempt to convert the given expression to a type which is accepted +/// by the given converter. /// -/// This routine will attempt to convert an expression of class type to an -/// integral or enumeration type, if that class type only has a single -/// conversion to an integral or enumeration type. +/// This routine will attempt to convert an expression of class type to a +/// type accepted by the specified converter. In C++11 and before, the class +/// must have a single non-explicit conversion function converting to a matching +/// type. In C++1y, there can be multiple such conversion functions, but only +/// one target type. /// /// \param Loc The source location of the construct that requires the /// conversion. /// /// \param From The expression we're converting from. /// -/// \param Diagnoser Used to output any diagnostics. -/// -/// \param AllowScopedEnumerations Specifies whether conversions to scoped -/// enumerations should be considered. +/// \param Converter Used to control and diagnose the conversion process. /// /// \returns The expression, converted to an integral or enumeration type if /// successful. -ExprResult -Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, - ICEConvertDiagnoser &Diagnoser, - bool AllowScopedEnumerations) { +ExprResult Sema::PerformContextualImplicitConversion( + SourceLocation Loc, Expr *From, ContextualImplicitConverter &Converter) { // We can't perform any more checking for type-dependent expressions. if (From->isTypeDependent()) return Owned(From); @@ -5151,158 +5262,180 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, // Process placeholders immediately. if (From->hasPlaceholderType()) { ExprResult result = CheckPlaceholderExpr(From); - if (result.isInvalid()) return result; + if (result.isInvalid()) + return result; From = result.take(); } - // If the expression already has integral or enumeration type, we're golden. + // If the expression already has a matching type, we're golden. QualType T = From->getType(); - if (isIntegralOrEnumerationType(T, AllowScopedEnumerations)) + if (Converter.match(T)) 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. + // We can only perform contextual implicit conversions on objects of class + // type. const RecordType *RecordTy = T->getAs<RecordType>(); if (!RecordTy || !getLangOpts().CPlusPlus) { - if (!Diagnoser.Suppress) - Diagnoser.diagnoseNotInt(*this, Loc, T) << From->getSourceRange(); + if (!Converter.Suppress) + Converter.diagnoseNoMatch(*this, Loc, T) << From->getSourceRange(); return Owned(From); } // We must have a complete class type. struct TypeDiagnoserPartialDiag : TypeDiagnoser { - ICEConvertDiagnoser &Diagnoser; + ContextualImplicitConverter &Converter; Expr *From; - - TypeDiagnoserPartialDiag(ICEConvertDiagnoser &Diagnoser, Expr *From) - : TypeDiagnoser(Diagnoser.Suppress), Diagnoser(Diagnoser), From(From) {} - + + TypeDiagnoserPartialDiag(ContextualImplicitConverter &Converter, Expr *From) + : TypeDiagnoser(Converter.Suppress), Converter(Converter), From(From) {} + virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) { - Diagnoser.diagnoseIncomplete(S, Loc, T) << From->getSourceRange(); + Converter.diagnoseIncomplete(S, Loc, T) << From->getSourceRange(); } - } IncompleteDiagnoser(Diagnoser, From); + } IncompleteDiagnoser(Converter, From); if (RequireCompleteType(Loc, T, IncompleteDiagnoser)) return Owned(From); // Look for a conversion to an integral or enumeration type. - UnresolvedSet<4> ViableConversions; + UnresolvedSet<4> + ViableConversions; // These are *potentially* viable in C++1y. UnresolvedSet<4> ExplicitConversions; std::pair<CXXRecordDecl::conversion_iterator, - CXXRecordDecl::conversion_iterator> Conversions - = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions(); + CXXRecordDecl::conversion_iterator> Conversions = + cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions(); + + bool HadMultipleCandidates = + (std::distance(Conversions.first, Conversions.second) > 1); + + // To check that there is only one target type, in C++1y: + QualType ToType; + bool HasUniqueTargetType = true; + + // Collect explicit or viable (potentially in C++1y) conversions. + for (CXXRecordDecl::conversion_iterator I = Conversions.first, + E = Conversions.second; + I != E; ++I) { + NamedDecl *D = (*I)->getUnderlyingDecl(); + CXXConversionDecl *Conversion; + FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D); + if (ConvTemplate) { + if (getLangOpts().CPlusPlus1y) + Conversion = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl()); + else + continue; // C++11 does not consider conversion operator templates(?). + } else + Conversion = cast<CXXConversionDecl>(D); - bool HadMultipleCandidates - = (std::distance(Conversions.first, Conversions.second) > 1); + assert((!ConvTemplate || getLangOpts().CPlusPlus1y) && + "Conversion operator templates are considered potentially " + "viable in C++1y"); - for (CXXRecordDecl::conversion_iterator - I = Conversions.first, E = Conversions.second; I != E; ++I) { - if (CXXConversionDecl *Conversion - = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) { - if (isIntegralOrEnumerationType( - Conversion->getConversionType().getNonReferenceType(), - AllowScopedEnumerations)) { - if (Conversion->isExplicit()) + QualType CurToType = Conversion->getConversionType().getNonReferenceType(); + if (Converter.match(CurToType) || ConvTemplate) { + + if (Conversion->isExplicit()) { + // FIXME: For C++1y, do we need this restriction? + // cf. diagnoseNoViableConversion() + if (!ConvTemplate) ExplicitConversions.addDecl(I.getDecl(), I.getAccess()); - else - ViableConversions.addDecl(I.getDecl(), I.getAccess()); + } else { + if (!ConvTemplate && getLangOpts().CPlusPlus1y) { + if (ToType.isNull()) + ToType = CurToType.getUnqualifiedType(); + else if (HasUniqueTargetType && + (CurToType.getUnqualifiedType() != ToType)) + HasUniqueTargetType = false; + } + ViableConversions.addDecl(I.getDecl(), I.getAccess()); } } } - switch (ViableConversions.size()) { - case 0: - if (ExplicitConversions.size() == 1 && !Diagnoser.Suppress) { - DeclAccessPair Found = ExplicitConversions[0]; - CXXConversionDecl *Conversion - = cast<CXXConversionDecl>(Found->getUnderlyingDecl()); + if (getLangOpts().CPlusPlus1y) { + // C++1y [conv]p6: + // ... An expression e of class type E appearing in such a context + // is said to be contextually implicitly converted to a specified + // type T and is well-formed if and only if e can be implicitly + // converted to a type T that is determined as follows: E is searched + // for conversion functions whose return type is cv T or reference to + // cv T such that T is allowed by the context. There shall be + // exactly one such T. - // The user probably meant to invoke the given explicit - // conversion; use it. - QualType ConvTy - = Conversion->getConversionType().getNonReferenceType(); - std::string TypeStr; - ConvTy.getAsStringInternal(TypeStr, getPrintingPolicy()); + // If no unique T is found: + if (ToType.isNull()) { + if (diagnoseNoViableConversion(*this, Loc, From, Converter, T, + HadMultipleCandidates, + ExplicitConversions)) + return ExprError(); + return finishContextualImplicitConversion(*this, Loc, From, Converter); + } - Diagnoser.diagnoseExplicitConv(*this, Loc, T, ConvTy) - << FixItHint::CreateInsertion(From->getLocStart(), - "static_cast<" + TypeStr + ">(") - << FixItHint::CreateInsertion(PP.getLocForEndOfToken(From->getLocEnd()), - ")"); - Diagnoser.noteExplicitConv(*this, Conversion, ConvTy); + // If more than one unique Ts are found: + if (!HasUniqueTargetType) + return diagnoseAmbiguousConversion(*this, Loc, From, Converter, T, + ViableConversions); - // If we aren't in a SFINAE context, build a call to the - // explicit conversion function. - if (isSFINAEContext()) - return ExprError(); + // If one unique T is found: + // First, build a candidate set from the previously recorded + // potentially viable conversions. + OverloadCandidateSet CandidateSet(Loc); + collectViableConversionCandidates(*this, From, ToType, ViableConversions, + CandidateSet); - CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); - ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion, - HadMultipleCandidates); - if (Result.isInvalid()) + // Then, perform overload resolution over the candidate set. + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, Loc, Best)) { + case OR_Success: { + // Apply this conversion. + DeclAccessPair Found = + DeclAccessPair::make(Best->Function, Best->FoundDecl.getAccess()); + if (recordConversion(*this, Loc, From, Converter, T, + HadMultipleCandidates, Found)) return ExprError(); - // Record usage of conversion in an implicit cast. - From = ImplicitCastExpr::Create(Context, Result.get()->getType(), - CK_UserDefinedConversion, - Result.get(), 0, - Result.get()->getValueKind()); + break; } - - // We'll complain below about a non-integral condition type. - break; - - case 1: { - // Apply this conversion. - DeclAccessPair Found = ViableConversions[0]; - CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); - - CXXConversionDecl *Conversion - = cast<CXXConversionDecl>(Found->getUnderlyingDecl()); - QualType ConvTy - = Conversion->getConversionType().getNonReferenceType(); - if (!Diagnoser.SuppressConversion) { - if (isSFINAEContext()) + case OR_Ambiguous: + return diagnoseAmbiguousConversion(*this, Loc, From, Converter, T, + ViableConversions); + case OR_No_Viable_Function: + if (diagnoseNoViableConversion(*this, Loc, From, Converter, T, + HadMultipleCandidates, + ExplicitConversions)) return ExprError(); - - Diagnoser.diagnoseConversion(*this, Loc, T, ConvTy) - << From->getSourceRange(); + // fall through 'OR_Deleted' case. + case OR_Deleted: + // We'll complain below about a non-integral condition type. + break; } + } else { + switch (ViableConversions.size()) { + case 0: { + if (diagnoseNoViableConversion(*this, Loc, From, Converter, T, + HadMultipleCandidates, + ExplicitConversions)) + return ExprError(); - ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion, - HadMultipleCandidates); - if (Result.isInvalid()) - return ExprError(); - // 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 (Diagnoser.Suppress) - return ExprError(); - - Diagnoser.diagnoseAmbiguous(*this, Loc, T) << From->getSourceRange(); - for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) { - CXXConversionDecl *Conv - = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl()); - QualType ConvTy = Conv->getConversionType().getNonReferenceType(); - Diagnoser.noteAmbiguous(*this, Conv, ConvTy); + // We'll complain below about a non-integral condition type. + break; + } + case 1: { + // Apply this conversion. + DeclAccessPair Found = ViableConversions[0]; + if (recordConversion(*this, Loc, From, Converter, T, + HadMultipleCandidates, Found)) + return ExprError(); + break; + } + default: + return diagnoseAmbiguousConversion(*this, Loc, From, Converter, T, + ViableConversions); } - return Owned(From); - } - - if (!isIntegralOrEnumerationType(From->getType(), AllowScopedEnumerations) && - !Diagnoser.Suppress) { - Diagnoser.diagnoseNotInt(*this, Loc, From->getType()) - << From->getSourceRange(); } - return DefaultLvalueConversion(From); + return finishContextualImplicitConversion(*this, Loc, From, Converter); } /// AddOverloadCandidate - Adds the given function to the set of @@ -5348,10 +5481,18 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, if (!CandidateSet.isNewCandidate(Function)) return; + // C++11 [class.copy]p11: [DR1402] + // A defaulted move constructor that is defined as deleted is ignored by + // overload resolution. + CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function); + if (Constructor && Constructor->isDefaulted() && Constructor->isDeleted() && + Constructor->isMoveConstructor()) + return; + // Overload resolution is always an unevaluated context. EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); - if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function)){ + if (Constructor) { // C++ [class.copy]p3: // A member function template is never instantiated to perform the copy // of a class object to an object of its class type. @@ -5437,7 +5578,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, } /// \brief Add all of the function declarations in the given function set to -/// the overload canddiate set. +/// the overload candidate set. void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, @@ -5526,6 +5667,13 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, if (!CandidateSet.isNewCandidate(Method)) return; + // C++11 [class.copy]p23: [DR1402] + // A defaulted move assignment operator that is defined as deleted is + // ignored by overload resolution. + if (Method->isDefaulted() && Method->isDeleted() && + Method->isMoveAssignmentOperator()) + return; + // Overload resolution is always an unevaluated context. EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); @@ -5708,6 +5856,45 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, SuppressUserConversions); } +/// Determine whether this is an allowable conversion from the result +/// of an explicit conversion operator to the expected type, per C++ +/// [over.match.conv]p1 and [over.match.ref]p1. +/// +/// \param ConvType The return type of the conversion function. +/// +/// \param ToType The type we are converting to. +/// +/// \param AllowObjCPointerConversion Allow a conversion from one +/// Objective-C pointer to another. +/// +/// \returns true if the conversion is allowable, false otherwise. +static bool isAllowableExplicitConversion(Sema &S, + QualType ConvType, QualType ToType, + bool AllowObjCPointerConversion) { + QualType ToNonRefType = ToType.getNonReferenceType(); + + // Easy case: the types are the same. + if (S.Context.hasSameUnqualifiedType(ConvType, ToNonRefType)) + return true; + + // Allow qualification conversions. + bool ObjCLifetimeConversion; + if (S.IsQualificationConversion(ConvType, ToNonRefType, /*CStyle*/false, + ObjCLifetimeConversion)) + return true; + + // If we're not allowed to consider Objective-C pointer conversions, + // we're done. + if (!AllowObjCPointerConversion) + return false; + + // Is this an Objective-C pointer conversion? + bool IncompatibleObjC = false; + QualType ConvertedType; + return S.isObjCPointerConversion(ConvType, ToNonRefType, ConvertedType, + IncompatibleObjC); +} + /// AddConversionCandidate - Add a C++ conversion function as a /// candidate in the candidate set (C++ [over.match.conv], /// C++ [over.match.copy]). From is the expression we're converting from, @@ -5719,7 +5906,8 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, - OverloadCandidateSet& CandidateSet) { + OverloadCandidateSet& CandidateSet, + bool AllowObjCConversionOnExplicit) { assert(!Conversion->getDescribedFunctionTemplate() && "Conversion function templates use AddTemplateConversionCandidate"); QualType ConvType = Conversion->getConversionType().getNonReferenceType(); @@ -5734,6 +5922,14 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, ConvType = Conversion->getConversionType().getNonReferenceType(); } + // Per C++ [over.match.conv]p1, [over.match.ref]p1, an explicit conversion + // operator is only a candidate if its return type is the target type or + // can be converted to the target type with a qualification conversion. + if (Conversion->isExplicit() && + !isAllowableExplicitConversion(*this, ConvType, ToType, + AllowObjCConversionOnExplicit)) + return; + // Overload resolution is always an unevaluated context. EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); @@ -5868,7 +6064,8 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, CXXRecordDecl *ActingDC, Expr *From, QualType ToType, - OverloadCandidateSet &CandidateSet) { + OverloadCandidateSet &CandidateSet, + bool AllowObjCConversionOnExplicit) { assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) && "Only conversion function templates permitted here"); @@ -5897,7 +6094,7 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, // template argument deduction as a candidate. assert(Specialization && "Missing function template specialization?"); AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType, - CandidateSet); + CandidateSet, AllowObjCConversionOnExplicit); } /// AddSurrogateCandidate - Adds a "surrogate" candidate function that @@ -6119,6 +6316,8 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, } } +namespace { + /// BuiltinCandidateTypeSet - A set of types that will be used for the /// candidate operator functions for built-in operators (C++ /// [over.built]). The types are separated into pointer types and @@ -6208,6 +6407,8 @@ public: bool hasNullPtrType() const { return HasNullPtrType; } }; +} // end anonymous namespace + /// AddPointerWithMoreQualifiedTypeVariants - Add the pointer type @p Ty to /// the set of pointer types along with any more-qualified variants of /// that type. For example, if @p Ty is "int const *", this routine @@ -7560,11 +7761,10 @@ public: /// on the operator @p Op and the arguments given. For example, if the /// operator is a binary '+', this routine might add "int /// operator+(int, int)" to cover integer addition. -void -Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, - SourceLocation OpLoc, - llvm::ArrayRef<Expr *> Args, - OverloadCandidateSet& CandidateSet) { +void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, + SourceLocation OpLoc, + ArrayRef<Expr *> Args, + OverloadCandidateSet &CandidateSet) { // Find all of the types that the arguments can convert to, but only // if the operator we're looking at has built-in operator candidates // that make use of these types. Also record whether we encounter non-record @@ -7869,7 +8069,8 @@ isBetterOverloadCandidate(Sema &S, Loc, isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion : TPOC_Call, - Cand1.ExplicitCallArguments)) + Cand1.ExplicitCallArguments, + Cand2.ExplicitCallArguments)) return BetterTemplate == Cand1.Function->getPrimaryTemplate(); } @@ -8024,7 +8225,7 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S, return isTemplate ? oc_function_template : oc_function; } -void MaybeEmitInheritedConstructorNote(Sema &S, FunctionDecl *Fn) { +void MaybeEmitInheritedConstructorNote(Sema &S, Decl *Fn) { const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn); if (!Ctor) return; @@ -8047,7 +8248,7 @@ void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType) { MaybeEmitInheritedConstructorNote(*this, Fn); } -//Notes the location of all overload candidates designated through +// Notes the location of all overload candidates designated through // OverloadedExpr void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr, QualType DestType) { assert(OverloadedExpr->getType() == Context.OverloadTy); @@ -8310,30 +8511,52 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { MaybeEmitInheritedConstructorNote(S, Fn); } -void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand, - unsigned NumFormalArgs) { - // TODO: treat calls to a missing default constructor as a special case - +/// Additional arity mismatch diagnosis specific to a function overload +/// candidates. This is not covered by the more general DiagnoseArityMismatch() +/// over a candidate in any candidate set. +bool CheckArityMismatch(Sema &S, OverloadCandidate *Cand, + unsigned NumArgs) { FunctionDecl *Fn = Cand->Function; - const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>(); - unsigned MinParams = Fn->getMinRequiredArguments(); // With invalid overloaded operators, it's possible that we think we - // have an arity mismatch when it fact it looks like we have the + // have an arity mismatch when in fact it looks like we have the // right number of arguments, because only overloaded operators have // the weird behavior of overloading member and non-member functions. // Just don't report anything. if (Fn->isInvalidDecl() && Fn->getDeclName().getNameKind() == DeclarationName::CXXOperatorName) - return; + return true; - // at least / at most / exactly - unsigned mode, modeCount; - if (NumFormalArgs < MinParams) { + if (NumArgs < MinParams) { assert((Cand->FailureKind == ovl_fail_too_few_arguments) || (Cand->FailureKind == ovl_fail_bad_deduction && Cand->DeductionFailure.Result == Sema::TDK_TooFewArguments)); + } else { + assert((Cand->FailureKind == ovl_fail_too_many_arguments) || + (Cand->FailureKind == ovl_fail_bad_deduction && + Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments)); + } + + return false; +} + +/// General arity mismatch diagnosis over a candidate in a candidate set. +void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) { + assert(isa<FunctionDecl>(D) && + "The templated declaration should at least be a function" + " when diagnosing bad template argument deduction due to too many" + " or too few arguments"); + + FunctionDecl *Fn = cast<FunctionDecl>(D); + + // TODO: treat calls to a missing default constructor as a special case + const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>(); + unsigned MinParams = Fn->getMinRequiredArguments(); + + // at least / at most / exactly + unsigned mode, modeCount; + if (NumFormalArgs < MinParams) { if (MinParams != FnTy->getNumArgs() || FnTy->isVariadic() || FnTy->isTemplateVariadic()) mode = 0; // "at least" @@ -8341,9 +8564,6 @@ void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand, mode = 2; // "exactly" modeCount = MinParams; } else { - assert((Cand->FailureKind == ovl_fail_too_many_arguments) || - (Cand->FailureKind == ovl_fail_bad_deduction && - Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments)); if (MinParams != FnTy->getNumArgs()) mode = 1; // "at most" else @@ -8365,25 +8585,42 @@ void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand, MaybeEmitInheritedConstructorNote(S, Fn); } +/// Arity mismatch diagnosis specific to a function overload candidate. +void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand, + unsigned NumFormalArgs) { + if (!CheckArityMismatch(S, Cand, NumFormalArgs)) + DiagnoseArityMismatch(S, Cand->Function, NumFormalArgs); +} + +TemplateDecl *getDescribedTemplate(Decl *Templated) { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Templated)) + return FD->getDescribedFunctionTemplate(); + else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Templated)) + return RD->getDescribedClassTemplate(); + + llvm_unreachable("Unsupported: Getting the described template declaration" + " for bad deduction diagnosis"); +} + /// Diagnose a failed template-argument deduction. -void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, +void DiagnoseBadDeduction(Sema &S, Decl *Templated, + DeductionFailureInfo &DeductionFailure, unsigned NumArgs) { - FunctionDecl *Fn = Cand->Function; // pattern - - TemplateParameter Param = Cand->DeductionFailure.getTemplateParameter(); + TemplateParameter Param = DeductionFailure.getTemplateParameter(); NamedDecl *ParamD; (ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) || (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) || (ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>()); - switch (Cand->DeductionFailure.Result) { + switch (DeductionFailure.Result) { case Sema::TDK_Success: llvm_unreachable("TDK_success while diagnosing bad deduction"); case Sema::TDK_Incomplete: { assert(ParamD && "no parameter found for incomplete deduction result"); - S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction) - << ParamD->getDeclName(); - MaybeEmitInheritedConstructorNote(S, Fn); + S.Diag(Templated->getLocation(), + diag::note_ovl_candidate_incomplete_deduction) + << ParamD->getDeclName(); + MaybeEmitInheritedConstructorNote(S, Templated); return; } @@ -8391,7 +8628,7 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, assert(ParamD && "no parameter found for bad qualifiers deduction result"); TemplateTypeParmDecl *TParam = cast<TemplateTypeParmDecl>(ParamD); - QualType Param = Cand->DeductionFailure.getFirstArg()->getAsType(); + QualType Param = DeductionFailure.getFirstArg()->getAsType(); // Param will have been canonicalized, but it should just be a // qualified version of ParamD, so move the qualifiers to that. @@ -8404,11 +8641,11 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, // about that. It also doesn't matter as much, because it won't // have any template parameters in it (because deduction isn't // done on dependent types). - QualType Arg = Cand->DeductionFailure.getSecondArg()->getAsType(); + QualType Arg = DeductionFailure.getSecondArg()->getAsType(); - S.Diag(Fn->getLocation(), diag::note_ovl_candidate_underqualified) - << ParamD->getDeclName() << Arg << NonCanonParam; - MaybeEmitInheritedConstructorNote(S, Fn); + S.Diag(Templated->getLocation(), diag::note_ovl_candidate_underqualified) + << ParamD->getDeclName() << Arg << NonCanonParam; + MaybeEmitInheritedConstructorNote(S, Templated); return; } @@ -8423,20 +8660,20 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, which = 2; } - S.Diag(Fn->getLocation(), diag::note_ovl_candidate_inconsistent_deduction) - << which << ParamD->getDeclName() - << *Cand->DeductionFailure.getFirstArg() - << *Cand->DeductionFailure.getSecondArg(); - MaybeEmitInheritedConstructorNote(S, Fn); + S.Diag(Templated->getLocation(), + diag::note_ovl_candidate_inconsistent_deduction) + << which << ParamD->getDeclName() << *DeductionFailure.getFirstArg() + << *DeductionFailure.getSecondArg(); + MaybeEmitInheritedConstructorNote(S, Templated); return; } case Sema::TDK_InvalidExplicitArguments: assert(ParamD && "no parameter found for invalid explicit arguments"); if (ParamD->getDeclName()) - S.Diag(Fn->getLocation(), + S.Diag(Templated->getLocation(), diag::note_ovl_candidate_explicit_arg_mismatch_named) - << ParamD->getDeclName(); + << ParamD->getDeclName(); else { int index = 0; if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD)) @@ -8446,35 +8683,36 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, index = NTTP->getIndex(); else index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex(); - S.Diag(Fn->getLocation(), + S.Diag(Templated->getLocation(), diag::note_ovl_candidate_explicit_arg_mismatch_unnamed) - << (index + 1); + << (index + 1); } - MaybeEmitInheritedConstructorNote(S, Fn); + MaybeEmitInheritedConstructorNote(S, Templated); return; case Sema::TDK_TooManyArguments: case Sema::TDK_TooFewArguments: - DiagnoseArityMismatch(S, Cand, NumArgs); + DiagnoseArityMismatch(S, Templated, NumArgs); return; case Sema::TDK_InstantiationDepth: - S.Diag(Fn->getLocation(), diag::note_ovl_candidate_instantiation_depth); - MaybeEmitInheritedConstructorNote(S, Fn); + S.Diag(Templated->getLocation(), + diag::note_ovl_candidate_instantiation_depth); + MaybeEmitInheritedConstructorNote(S, Templated); return; case Sema::TDK_SubstitutionFailure: { // Format the template argument list into the argument string. SmallString<128> TemplateArgString; if (TemplateArgumentList *Args = - Cand->DeductionFailure.getTemplateArgumentList()) { + DeductionFailure.getTemplateArgumentList()) { TemplateArgString = " "; TemplateArgString += S.getTemplateArgumentBindingsText( - Fn->getDescribedFunctionTemplate()->getTemplateParameters(), *Args); + getDescribedTemplate(Templated)->getTemplateParameters(), *Args); } // If this candidate was disabled by enable_if, say so. - PartialDiagnosticAt *PDiag = Cand->DeductionFailure.getSFINAEDiagnostic(); + PartialDiagnosticAt *PDiag = DeductionFailure.getSFINAEDiagnostic(); if (PDiag && PDiag->second.getDiagID() == diag::err_typename_nested_not_found_enable_if) { // FIXME: Use the source range of the condition, and the fully-qualified @@ -8495,25 +8733,25 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, PDiag->second.EmitToString(S.getDiagnostics(), SFINAEArgString); } - S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure) - << TemplateArgString << SFINAEArgString << R; - MaybeEmitInheritedConstructorNote(S, Fn); + S.Diag(Templated->getLocation(), + diag::note_ovl_candidate_substitution_failure) + << TemplateArgString << SFINAEArgString << R; + MaybeEmitInheritedConstructorNote(S, Templated); return; } case Sema::TDK_FailedOverloadResolution: { - OverloadExpr::FindResult R = - OverloadExpr::find(Cand->DeductionFailure.getExpr()); - S.Diag(Fn->getLocation(), + OverloadExpr::FindResult R = OverloadExpr::find(DeductionFailure.getExpr()); + S.Diag(Templated->getLocation(), diag::note_ovl_candidate_failed_overload_resolution) - << R.Expression->getName(); + << R.Expression->getName(); return; } case Sema::TDK_NonDeducedMismatch: { // FIXME: Provide a source location to indicate what we couldn't match. - TemplateArgument FirstTA = *Cand->DeductionFailure.getFirstArg(); - TemplateArgument SecondTA = *Cand->DeductionFailure.getSecondArg(); + TemplateArgument FirstTA = *DeductionFailure.getFirstArg(); + TemplateArgument SecondTA = *DeductionFailure.getSecondArg(); if (FirstTA.getKind() == TemplateArgument::Template && SecondTA.getKind() == TemplateArgument::Template) { TemplateName FirstTN = FirstTA.getAsTemplate(); @@ -8528,26 +8766,42 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, // 2) The diagnostic printer only attempts to find a better // name for types, not decls. // Ideally, this should folded into the diagnostic printer. - S.Diag(Fn->getLocation(), + S.Diag(Templated->getLocation(), diag::note_ovl_candidate_non_deduced_mismatch_qualified) << FirstTN.getAsTemplateDecl() << SecondTN.getAsTemplateDecl(); return; } } } - S.Diag(Fn->getLocation(), diag::note_ovl_candidate_non_deduced_mismatch) - << FirstTA << SecondTA; + // FIXME: For generic lambda parameters, check if the function is a lambda + // call operator, and if so, emit a prettier and more informative + // diagnostic that mentions 'auto' and lambda in addition to + // (or instead of?) the canonical template type parameters. + S.Diag(Templated->getLocation(), + diag::note_ovl_candidate_non_deduced_mismatch) + << FirstTA << SecondTA; return; } // TODO: diagnose these individually, then kill off // note_ovl_candidate_bad_deduction, which is uselessly vague. case Sema::TDK_MiscellaneousDeductionFailure: - S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction); - MaybeEmitInheritedConstructorNote(S, Fn); + S.Diag(Templated->getLocation(), diag::note_ovl_candidate_bad_deduction); + MaybeEmitInheritedConstructorNote(S, Templated); return; } } +/// Diagnose a failed template-argument deduction, for function calls. +void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, unsigned NumArgs) { + unsigned TDK = Cand->DeductionFailure.Result; + if (TDK == Sema::TDK_TooFewArguments || TDK == Sema::TDK_TooManyArguments) { + if (CheckArityMismatch(S, Cand, NumArgs)) + return; + } + DiagnoseBadDeduction(S, Cand->Function, // pattern + Cand->DeductionFailure, NumArgs); +} + /// CUDA: diagnose an invalid call across targets. void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) { FunctionDecl *Caller = cast<FunctionDecl>(S.CurContext); @@ -8695,7 +8949,7 @@ void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc, } } -SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) { +static SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) { if (Cand->Function) return Cand->Function->getLocation(); if (Cand->IsSurrogate) @@ -8703,8 +8957,7 @@ SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) { return SourceLocation(); } -static unsigned -RankDeductionFailure(const OverloadCandidate::DeductionFailureInfo &DFI) { +static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) { switch ((Sema::TemplateDeductionResult)DFI.Result) { case Sema::TDK_Success: llvm_unreachable("TDK_success while diagnosing bad deduction"); @@ -8997,6 +9250,108 @@ void OverloadCandidateSet::NoteCandidates(Sema &S, S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I); } +static SourceLocation +GetLocationForCandidate(const TemplateSpecCandidate *Cand) { + return Cand->Specialization ? Cand->Specialization->getLocation() + : SourceLocation(); +} + +struct CompareTemplateSpecCandidatesForDisplay { + Sema &S; + CompareTemplateSpecCandidatesForDisplay(Sema &S) : S(S) {} + + bool operator()(const TemplateSpecCandidate *L, + const TemplateSpecCandidate *R) { + // Fast-path this check. + if (L == R) + return false; + + // Assuming that both candidates are not matches... + + // Sort by the ranking of deduction failures. + if (L->DeductionFailure.Result != R->DeductionFailure.Result) + return RankDeductionFailure(L->DeductionFailure) < + RankDeductionFailure(R->DeductionFailure); + + // Sort everything else by location. + SourceLocation LLoc = GetLocationForCandidate(L); + SourceLocation RLoc = GetLocationForCandidate(R); + + // Put candidates without locations (e.g. builtins) at the end. + if (LLoc.isInvalid()) + return false; + if (RLoc.isInvalid()) + return true; + + return S.SourceMgr.isBeforeInTranslationUnit(LLoc, RLoc); + } +}; + +/// Diagnose a template argument deduction failure. +/// We are treating these failures as overload failures due to bad +/// deductions. +void TemplateSpecCandidate::NoteDeductionFailure(Sema &S) { + DiagnoseBadDeduction(S, Specialization, // pattern + DeductionFailure, /*NumArgs=*/0); +} + +void TemplateSpecCandidateSet::destroyCandidates() { + for (iterator i = begin(), e = end(); i != e; ++i) { + i->DeductionFailure.Destroy(); + } +} + +void TemplateSpecCandidateSet::clear() { + destroyCandidates(); + Candidates.clear(); +} + +/// NoteCandidates - When no template specialization match is found, prints +/// diagnostic messages containing the non-matching specializations that form +/// the candidate set. +/// This is analoguous to OverloadCandidateSet::NoteCandidates() with +/// OCD == OCD_AllCandidates and Cand->Viable == false. +void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) { + // Sort the candidates by position (assuming no candidate is a match). + // Sorting directly would be prohibitive, so we make a set of pointers + // and sort those. + SmallVector<TemplateSpecCandidate *, 32> Cands; + Cands.reserve(size()); + for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) { + if (Cand->Specialization) + Cands.push_back(Cand); + // Otherwise, this is a non matching builtin candidate. We do not, + // in general, want to list every possible builtin candidate. + } + + std::sort(Cands.begin(), Cands.end(), + CompareTemplateSpecCandidatesForDisplay(S)); + + // FIXME: Perhaps rename OverloadsShown and getShowOverloads() + // for generalization purposes (?). + const OverloadsShown ShowOverloads = S.Diags.getShowOverloads(); + + SmallVectorImpl<TemplateSpecCandidate *>::iterator I, E; + unsigned CandsShown = 0; + for (I = Cands.begin(), E = Cands.end(); I != E; ++I) { + TemplateSpecCandidate *Cand = *I; + + // Set an arbitrary limit on the number of candidates we'll spam + // the user with. FIXME: This limit should depend on details of the + // candidate list. + if (CandsShown >= 4 && ShowOverloads == Ovl_Best) + break; + ++CandsShown; + + assert(Cand->Specialization && + "Non-matching built-in candidates are not added to Cands."); + Cand->NoteDeductionFailure(S); + } + + if (I != E) + S.Diag(Loc, diag::note_ovl_too_many_candidates) << int(E - I); +} + // [PossiblyAFunctionType] --> [Return] // NonFunctionType --> NonFunctionType // R (A) --> R(A) @@ -9034,47 +9389,51 @@ class AddressOfFunctionResolver bool TargetTypeIsNonStaticMemberFunction; bool FoundNonTemplateFunction; + bool StaticMemberFunctionFromBoundPointer; OverloadExpr::FindResult OvlExprInfo; OverloadExpr *OvlExpr; TemplateArgumentListInfo OvlExplicitTemplateArgs; SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches; + TemplateSpecCandidateSet FailedCandidates; public: - AddressOfFunctionResolver(Sema &S, Expr* SourceExpr, - const QualType& TargetType, bool Complain) - : S(S), SourceExpr(SourceExpr), TargetType(TargetType), - Complain(Complain), Context(S.getASTContext()), - TargetTypeIsNonStaticMemberFunction( - !!TargetType->getAs<MemberPointerType>()), - FoundNonTemplateFunction(false), - OvlExprInfo(OverloadExpr::find(SourceExpr)), - OvlExpr(OvlExprInfo.Expression) - { + AddressOfFunctionResolver(Sema &S, Expr *SourceExpr, + const QualType &TargetType, bool Complain) + : S(S), SourceExpr(SourceExpr), TargetType(TargetType), + Complain(Complain), Context(S.getASTContext()), + TargetTypeIsNonStaticMemberFunction( + !!TargetType->getAs<MemberPointerType>()), + FoundNonTemplateFunction(false), + StaticMemberFunctionFromBoundPointer(false), + OvlExprInfo(OverloadExpr::find(SourceExpr)), + OvlExpr(OvlExprInfo.Expression), + FailedCandidates(OvlExpr->getNameLoc()) { ExtractUnqualifiedFunctionTypeFromTargetType(); - - if (!TargetFunctionType->isFunctionType()) { - if (OvlExpr->hasExplicitTemplateArgs()) { - DeclAccessPair dap; - if (FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization( - OvlExpr, false, &dap) ) { - - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) { - if (!Method->isStatic()) { - // If the target type is a non-function type and the function - // found is a non-static member function, pretend as if that was - // the target, it's the only possible type to end up with. - TargetTypeIsNonStaticMemberFunction = true; - - // And skip adding the function if its not in the proper form. - // We'll diagnose this due to an empty set of functions. - if (!OvlExprInfo.HasFormOfMemberPointer) - return; - } + + if (TargetFunctionType->isFunctionType()) { + if (UnresolvedMemberExpr *UME = dyn_cast<UnresolvedMemberExpr>(OvlExpr)) + if (!UME->isImplicitAccess() && + !S.ResolveSingleFunctionTemplateSpecialization(UME)) + StaticMemberFunctionFromBoundPointer = true; + } else if (OvlExpr->hasExplicitTemplateArgs()) { + DeclAccessPair dap; + if (FunctionDecl *Fn = S.ResolveSingleFunctionTemplateSpecialization( + OvlExpr, false, &dap)) { + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) + if (!Method->isStatic()) { + // If the target type is a non-function type and the function found + // is a non-static member function, pretend as if that was the + // target, it's the only possible type to end up with. + TargetTypeIsNonStaticMemberFunction = true; + + // And skip adding the function if its not in the proper form. + // We'll diagnose this due to an empty set of functions. + if (!OvlExprInfo.HasFormOfMemberPointer) + return; } - Matches.push_back(std::make_pair(dap,Fn)); - } + Matches.push_back(std::make_pair(dap, Fn)); } return; } @@ -9128,14 +9487,16 @@ private: // function template specialization, which is added to the set of // overloaded functions considered. FunctionDecl *Specialization = 0; - TemplateDeductionInfo Info(OvlExpr->getNameLoc()); + TemplateDeductionInfo Info(FailedCandidates.getLocation()); if (Sema::TemplateDeductionResult Result = S.DeduceTemplateArguments(FunctionTemplate, &OvlExplicitTemplateArgs, TargetFunctionType, Specialization, Info, /*InOverloadResolution=*/true)) { - // FIXME: make a note of the failed deduction for diagnostics. - (void)Result; + // Make a note of the failed deduction for diagnostics. + FailedCandidates.addCandidate() + .set(FunctionTemplate->getTemplatedDecl(), + MakeDeductionFailureInfo(Context, Result, Info)); return false; } @@ -9239,15 +9600,15 @@ private: for (unsigned I = 0, E = Matches.size(); I != E; ++I) MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess()); - UnresolvedSetIterator Result = - S.getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(), - TPOC_Other, 0, SourceExpr->getLocStart(), - S.PDiag(), - S.PDiag(diag::err_addr_ovl_ambiguous) - << Matches[0].second->getDeclName(), - S.PDiag(diag::note_ovl_candidate) - << (unsigned) oc_function_template, - Complain, TargetFunctionType); + // TODO: It looks like FailedCandidates does not serve much purpose + // here, since the no_viable diagnostic has index 0. + UnresolvedSetIterator Result = S.getMostSpecialized( + MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates, + SourceExpr->getLocStart(), S.PDiag(), + S.PDiag(diag::err_addr_ovl_ambiguous) << Matches[0] + .second->getDeclName(), + S.PDiag(diag::note_ovl_candidate) << (unsigned)oc_function_template, + Complain, TargetFunctionType); if (Result != MatchesCopy.end()) { // Make it the first and only element @@ -9276,14 +9637,27 @@ public: S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_no_viable) << OvlExpr->getName() << TargetFunctionType << OvlExpr->getSourceRange(); - S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType); - } - + if (FailedCandidates.empty()) + S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType); + else { + // We have some deduction failure messages. Use them to diagnose + // the function templates, and diagnose the non-template candidates + // normally. + for (UnresolvedSetIterator I = OvlExpr->decls_begin(), + IEnd = OvlExpr->decls_end(); + I != IEnd; ++I) + if (FunctionDecl *Fun = + dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl())) + S.NoteOverloadCandidate(Fun, TargetFunctionType); + FailedCandidates.NoteCandidates(S, OvlExpr->getLocStart()); + } + } + bool IsInvalidFormOfPointerToMemberFunction() const { return TargetTypeIsNonStaticMemberFunction && !OvlExprInfo.HasFormOfMemberPointer; } - + void ComplainIsInvalidFormOfPointerToMemberFunction() const { // TODO: Should we condition this on whether any functions might // have matched, or is it more appropriate to do that in callers? @@ -9291,7 +9665,17 @@ public: S.Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier) << TargetType << OvlExpr->getSourceRange(); } - + + bool IsStaticMemberFunctionFromBoundPointer() const { + return StaticMemberFunctionFromBoundPointer; + } + + void ComplainIsStaticMemberFunctionFromBoundPointer() const { + S.Diag(OvlExpr->getLocStart(), + diag::err_invalid_form_pointer_member_function) + << OvlExpr->getSourceRange(); + } + void ComplainOfInvalidConversion() const { S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_not_func_ptrref) << OvlExpr->getName() << TargetType; @@ -9359,8 +9743,12 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, Fn = Resolver.getMatchingFunctionDecl(); assert(Fn); FoundResult = *Resolver.getMatchingFunctionAccessPair(); - if (Complain) - CheckAddressOfMemberAccess(AddressOfExpr, FoundResult); + if (Complain) { + if (Resolver.IsStaticMemberFunctionFromBoundPointer()) + Resolver.ComplainIsStaticMemberFunctionFromBoundPointer(); + else + CheckAddressOfMemberAccess(AddressOfExpr, FoundResult); + } } if (pHadMultipleCandidates) @@ -9375,6 +9763,9 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, /// template, where that template-id refers to a single template whose template /// arguments are either provided by the template-id or have defaults, /// as described in C++0x [temp.arg.explicit]p3. +/// +/// If no template-ids are found, no diagnostics are emitted and NULL is +/// returned. FunctionDecl * Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, bool Complain, @@ -9392,6 +9783,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, TemplateArgumentListInfo ExplicitTemplateArgs; ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs); + TemplateSpecCandidateSet FailedCandidates(ovl->getNameLoc()); // Look through all of the overloaded functions, searching for one // whose type matches exactly. @@ -9414,13 +9806,16 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, // function template specialization, which is added to the set of // overloaded functions considered. FunctionDecl *Specialization = 0; - TemplateDeductionInfo Info(ovl->getNameLoc()); + TemplateDeductionInfo Info(FailedCandidates.getLocation()); if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs, Specialization, Info, /*InOverloadResolution=*/true)) { - // FIXME: make a note of the failed deduction for diagnostics. - (void)Result; + // Make a note of the failed deduction for diagnostics. + // TODO: Actually use the failed-deduction info? + FailedCandidates.addCandidate() + .set(FunctionTemplate->getTemplatedDecl(), + MakeDeductionFailureInfo(Context, Result, Info)); continue; } @@ -9623,6 +10018,19 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, CandidateSet, PartialOverloading); } +/// Determine whether a declaration with the specified name could be moved into +/// a different namespace. +static bool canBeDeclaredInNamespace(const DeclarationName &Name) { + switch (Name.getCXXOverloadedOperator()) { + case OO_New: case OO_Array_New: + case OO_Delete: case OO_Array_Delete: + return false; + + default: + return true; + } +} + /// Attempt to recover from an ill-formed use of a non-dependent name in a /// template, where the non-dependent name was declared after the template /// was defined. This is common in code written for a compilers which do not @@ -9675,22 +10083,24 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, AssociatedNamespaces, AssociatedClasses); Sema::AssociatedNamespaceSet SuggestedNamespaces; - DeclContext *Std = SemaRef.getStdNamespace(); - for (Sema::AssociatedNamespaceSet::iterator - it = AssociatedNamespaces.begin(), - end = AssociatedNamespaces.end(); it != end; ++it) { - // Never suggest declaring a function within namespace 'std'. - if (Std && Std->Encloses(*it)) - continue; - - // Never suggest declaring a function within a namespace with a reserved - // name, like __gnu_cxx. - NamespaceDecl *NS = dyn_cast<NamespaceDecl>(*it); - if (NS && - NS->getQualifiedNameAsString().find("__") != std::string::npos) - continue; + if (canBeDeclaredInNamespace(R.getLookupName())) { + DeclContext *Std = SemaRef.getStdNamespace(); + for (Sema::AssociatedNamespaceSet::iterator + it = AssociatedNamespaces.begin(), + end = AssociatedNamespaces.end(); it != end; ++it) { + // Never suggest declaring a function within namespace 'std'. + if (Std && Std->Encloses(*it)) + continue; - SuggestedNamespaces.insert(*it); + // Never suggest declaring a function within a namespace with a + // reserved name, like __gnu_cxx. + NamespaceDecl *NS = dyn_cast<NamespaceDecl>(*it); + if (NS && + NS->getQualifiedNameAsString().find("__") != std::string::npos) + continue; + + SuggestedNamespaces.insert(*it); + } } SemaRef.Diag(R.getNameLoc(), diag::err_not_found_by_two_phase_lookup) @@ -9739,67 +10149,6 @@ DiagnoseTwoPhaseOperatorLookup(Sema &SemaRef, OverloadedOperatorKind Op, } 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; - } -}; - class BuildRecoveryCallExprRAII { Sema &SemaRef; public: @@ -9848,7 +10197,8 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(), Sema::LookupOrdinaryName); - RecoveryCallCCC Validator(SemaRef, Args.size(), ExplicitTemplateArgs != 0); + FunctionCallFilterCCC Validator(SemaRef, Args.size(), + ExplicitTemplateArgs != 0); NoTypoCorrectionCCC RejectAll; CorrectionCandidateCallback *CCC = AllowTypoCorrection ? (CorrectionCandidateCallback*)&Validator : @@ -9890,7 +10240,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, /// \returns true when an the ExprResult output parameter has been set. bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, - Expr **Args, unsigned NumArgs, + MultiExprArg Args, SourceLocation RParenLoc, OverloadCandidateSet *CandidateSet, ExprResult *Result) { @@ -9913,15 +10263,14 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn, #endif UnbridgedCastsSet UnbridgedCasts; - if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts)) { + if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts)) { *Result = ExprError(); return true; } // Add the functions denoted by the callee to the set of candidate // functions, including those from argument-dependent lookup. - AddOverloadedCallCandidates(ULE, llvm::makeArrayRef(Args, NumArgs), - *CandidateSet); + AddOverloadedCallCandidates(ULE, Args, *CandidateSet); // If we found nothing, try to recover. // BuildRecoveryCallExpr diagnoses the error itself, so we just bail @@ -9933,8 +10282,7 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn, // classes. if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() && (isa<FunctionDecl>(CurContext) || isa<CXXRecordDecl>(CurContext))) { - CallExpr *CE = new (Context) CallExpr(Context, Fn, - llvm::makeArrayRef(Args, NumArgs), + CallExpr *CE = new (Context) CallExpr(Context, Fn, Args, Context.DependentTy, VK_RValue, RParenLoc); CE->setTypeDependent(true); @@ -9954,7 +10302,7 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn, static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc, - Expr **Args, unsigned NumArgs, + MultiExprArg Args, SourceLocation RParenLoc, Expr *ExecConfig, OverloadCandidateSet *CandidateSet, @@ -9962,8 +10310,7 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, OverloadingResult OverloadResult, bool AllowTypoCorrection) { if (CandidateSet->empty()) - return BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc, - llvm::MutableArrayRef<Expr *>(Args, NumArgs), + return BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc, Args, RParenLoc, /*EmptyLookup=*/true, AllowTypoCorrection); @@ -9974,16 +10321,15 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, if (SemaRef.DiagnoseUseOfDecl(FDecl, ULE->getNameLoc())) return ExprError(); Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); - return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, - RParenLoc, ExecConfig); + return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc, + ExecConfig); } case OR_No_Viable_Function: { // Try to recover by looking for viable functions which the user might // have meant to call. ExprResult Recovery = BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc, - llvm::MutableArrayRef<Expr *>(Args, NumArgs), - RParenLoc, + Args, RParenLoc, /*EmptyLookup=*/false, AllowTypoCorrection); if (!Recovery.isInvalid()) @@ -9992,16 +10338,14 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_no_viable_function_in_call) << ULE->getName() << Fn->getSourceRange(); - CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, - llvm::makeArrayRef(Args, NumArgs)); + CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args); break; } case OR_Ambiguous: SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_ambiguous_call) << ULE->getName() << Fn->getSourceRange(); - CandidateSet->NoteCandidates(SemaRef, OCD_ViableCandidates, - llvm::makeArrayRef(Args, NumArgs)); + CandidateSet->NoteCandidates(SemaRef, OCD_ViableCandidates, Args); break; case OR_Deleted: { @@ -10010,15 +10354,14 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, << ULE->getName() << SemaRef.getDeletedOrUnavailableSuffix((*Best)->Function) << Fn->getSourceRange(); - CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, - llvm::makeArrayRef(Args, NumArgs)); + CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args); // We emitted an error for the unvailable/deleted function call but keep // the call in the AST. FunctionDecl *FDecl = (*Best)->Function; Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); - return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, - RParenLoc, ExecConfig); + return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc, + ExecConfig); } } @@ -10035,22 +10378,22 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc, - Expr **Args, unsigned NumArgs, + MultiExprArg Args, SourceLocation RParenLoc, Expr *ExecConfig, bool AllowTypoCorrection) { OverloadCandidateSet CandidateSet(Fn->getExprLoc()); ExprResult result; - if (buildOverloadedCallSet(S, Fn, ULE, Args, NumArgs, LParenLoc, - &CandidateSet, &result)) + if (buildOverloadedCallSet(S, Fn, ULE, Args, LParenLoc, &CandidateSet, + &result)) return result; OverloadCandidateSet::iterator Best; OverloadingResult OverloadResult = CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best); - return FinishOverloadedCallExpr(*this, S, Fn, ULE, LParenLoc, Args, NumArgs, + return FinishOverloadedCallExpr(*this, S, Fn, ULE, LParenLoc, Args, RParenLoc, ExecConfig, &CandidateSet, &Best, OverloadResult, AllowTypoCorrection); @@ -10180,17 +10523,17 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, Input = InputInit.take(); } - // Determine the result type. - QualType ResultTy = FnDecl->getResultType(); - ExprValueKind VK = Expr::getValueKindForType(ResultTy); - ResultTy = ResultTy.getNonLValueExprType(Context); - // Build the actual expression node. ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, Best->FoundDecl, HadMultipleCandidates, OpLoc); if (FnExpr.isInvalid()) return ExprError(); + // Determine the result type. + QualType ResultTy = FnDecl->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + Args[0] = Input; CallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), ArgsArray, @@ -10414,11 +10757,6 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, Args[1] = RHS = Arg1.takeAs<Expr>(); } - // Determine the result type. - QualType ResultTy = FnDecl->getResultType(); - ExprValueKind VK = Expr::getValueKindForType(ResultTy); - ResultTy = ResultTy.getNonLValueExprType(Context); - // Build the actual expression node. ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, Best->FoundDecl, @@ -10426,6 +10764,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (FnExpr.isInvalid()) return ExprError(); + // Determine the result type. + QualType ResultTy = FnDecl->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + CXXOperatorCallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), Args, ResultTy, VK, OpLoc, @@ -10481,6 +10824,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, Diag(OpLoc, diag::err_ovl_no_viable_oper) << BinaryOperator::getOpcodeStr(Opc) << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + if (Args[0]->getType()->isIncompleteType()) { + Diag(OpLoc, diag::note_assign_lhs_incomplete) + << Args[0]->getType() + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + } } else { // This is an erroneous use of an operator which can be overloaded by // a non-member function. Check for non-member operators which were @@ -10621,11 +10969,6 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, Args[1] = InputInit.takeAs<Expr>(); - // Determine the result type - QualType ResultTy = FnDecl->getResultType(); - ExprValueKind VK = Expr::getValueKindForType(ResultTy); - ResultTy = ResultTy.getNonLValueExprType(Context); - // Build the actual expression node. DeclarationNameInfo OpLocInfo(OpName, LLoc); OpLocInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc)); @@ -10637,6 +10980,11 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, if (FnExpr.isInvalid()) return ExprError(); + // Determine the result type + QualType ResultTy = FnDecl->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + CXXOperatorCallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, OO_Subscript, FnExpr.take(), Args, @@ -10716,8 +11064,9 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, /// member function. ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, - SourceLocation LParenLoc, Expr **Args, - unsigned NumArgs, SourceLocation RParenLoc) { + SourceLocation LParenLoc, + MultiExprArg Args, + SourceLocation RParenLoc) { assert(MemExprE->getType() == Context.BoundMemberTy || MemExprE->getType() == Context.OverloadTy); @@ -10758,8 +11107,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, } CXXMemberCallExpr *call - = new (Context) CXXMemberCallExpr(Context, MemExprE, - llvm::makeArrayRef(Args, NumArgs), + = new (Context) CXXMemberCallExpr(Context, MemExprE, Args, resultType, valueKind, RParenLoc); if (CheckCallReturnType(proto->getResultType(), @@ -10767,14 +11115,17 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, call, 0)) return ExprError(); - if (ConvertArgumentsForCall(call, op, 0, proto, Args, NumArgs, RParenLoc)) + if (ConvertArgumentsForCall(call, op, 0, proto, Args, RParenLoc)) + return ExprError(); + + if (CheckOtherCall(call, proto)) return ExprError(); return MaybeBindToTemporary(call); } UnbridgedCastsSet UnbridgedCasts; - if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts)) + if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts)) return ExprError(); MemberExpr *MemExpr; @@ -10818,7 +11169,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // Microsoft supports direct constructor calls. if (getLangOpts().MicrosoftExt && isa<CXXConstructorDecl>(Func)) { AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), - llvm::makeArrayRef(Args, NumArgs), CandidateSet); + Args, CandidateSet); } else if ((Method = dyn_cast<CXXMethodDecl>(Func))) { // If explicit template arguments were provided, we can't call a // non-template member function. @@ -10826,15 +11177,13 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, continue; AddMethodCandidate(Method, I.getPair(), ActingDC, ObjectType, - ObjectClassification, - llvm::makeArrayRef(Args, NumArgs), CandidateSet, + ObjectClassification, Args, CandidateSet, /*SuppressUserConversions=*/false); } else { AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func), I.getPair(), ActingDC, TemplateArgs, ObjectType, ObjectClassification, - llvm::makeArrayRef(Args, NumArgs), - CandidateSet, + Args, CandidateSet, /*SuppressUsedConversions=*/false); } } @@ -10852,22 +11201,29 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl); if (DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc())) return ExprError(); + // If FoundDecl is different from Method (such as if one is a template + // and the other a specialization), make sure DiagnoseUseOfDecl is + // called on both. + // FIXME: This would be more comprehensively addressed by modifying + // DiagnoseUseOfDecl to accept both the FoundDecl and the decl + // being used. + if (Method != FoundDecl.getDecl() && + DiagnoseUseOfDecl(Method, UnresExpr->getNameLoc())) + return ExprError(); break; case OR_No_Viable_Function: Diag(UnresExpr->getMemberLoc(), diag::err_ovl_no_viable_member_function_in_call) << DeclName << MemExprE->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, - llvm::makeArrayRef(Args, NumArgs)); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); // 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, - llvm::makeArrayRef(Args, NumArgs)); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); // FIXME: Leaking incoming expressions! return ExprError(); @@ -10877,8 +11233,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, << DeclName << getDeletedOrUnavailableSuffix(Best->Function) << MemExprE->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, - llvm::makeArrayRef(Args, NumArgs)); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); // FIXME: Leaking incoming expressions! return ExprError(); } @@ -10888,8 +11243,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // If overload resolution picked a static member, build a // non-member call based on that function. if (Method->isStatic()) { - return BuildResolvedCallExpr(MemExprE, Method, LParenLoc, - Args, NumArgs, RParenLoc); + return BuildResolvedCallExpr(MemExprE, Method, LParenLoc, Args, + RParenLoc); } MemExpr = cast<MemberExpr>(MemExprE->IgnoreParens()); @@ -10901,8 +11256,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, assert(Method && "Member call to something that isn't a method?"); CXXMemberCallExpr *TheCall = - new (Context) CXXMemberCallExpr(Context, MemExprE, - llvm::makeArrayRef(Args, NumArgs), + new (Context) CXXMemberCallExpr(Context, MemExprE, Args, ResultType, VK, RParenLoc); // Check for a valid return type. @@ -10925,11 +11279,11 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // Convert the rest of the arguments const FunctionProtoType *Proto = Method->getType()->getAs<FunctionProtoType>(); - if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args, NumArgs, + if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args, RParenLoc)) return ExprError(); - DiagnoseSentinelCalls(Method, LParenLoc, Args, NumArgs); + DiagnoseSentinelCalls(Method, LParenLoc, Args); if (CheckFunctionCall(Method, TheCall, Proto)) return ExprError(); @@ -10958,14 +11312,14 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, ExprResult Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, SourceLocation LParenLoc, - Expr **Args, unsigned NumArgs, + MultiExprArg Args, SourceLocation RParenLoc) { if (checkPlaceholderForOverload(*this, Obj)) return ExprError(); ExprResult Object = Owned(Obj); UnbridgedCastsSet UnbridgedCasts; - if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts)) + if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts)) return ExprError(); assert(Object.get()->getType()->isRecordType() && "Requires object type argument"); @@ -10992,8 +11346,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); Oper != OperEnd; ++Oper) { AddMethodCandidate(Oper.getPair(), Object.get()->getType(), - Object.get()->Classify(Context), - llvm::makeArrayRef(Args, NumArgs), CandidateSet, + Object.get()->Classify(Context), + Args, CandidateSet, /*SuppressUserConversions=*/ false); } @@ -11040,8 +11394,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>()) { AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto, - Object.get(), llvm::makeArrayRef(Args, NumArgs), - CandidateSet); + Object.get(), Args, CandidateSet); } } } @@ -11066,16 +11419,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, Diag(Object.get()->getLocStart(), diag::err_ovl_no_viable_object_call) << Object.get()->getType() << Object.get()->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, - llvm::makeArrayRef(Args, NumArgs)); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); break; case OR_Ambiguous: Diag(Object.get()->getLocStart(), diag::err_ovl_ambiguous_object_call) << Object.get()->getType() << Object.get()->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, - llvm::makeArrayRef(Args, NumArgs)); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args); break; case OR_Deleted: @@ -11085,8 +11436,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, << Object.get()->getType() << getDeletedOrUnavailableSuffix(Best->Function) << Object.get()->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, - llvm::makeArrayRef(Args, NumArgs)); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); break; } @@ -11105,7 +11455,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl); if (DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc)) return ExprError(); - + assert(Conv == Best->FoundDecl.getDecl() && + "Found Decl & conversion-to-functionptr should be same, right?!"); // We selected one of the surrogate functions that converts the // object parameter to a function pointer. Perform the conversion // on the object argument, then let ActOnCallExpr finish the job. @@ -11121,8 +11472,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, CK_UserDefinedConversion, Call.get(), 0, VK_RValue)); - return ActOnCallExpr(S, Call.get(), LParenLoc, MultiExprArg(Args, NumArgs), - RParenLoc); + return ActOnCallExpr(S, Call.get(), LParenLoc, Args, RParenLoc); } CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl); @@ -11140,21 +11490,6 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, Method->getType()->getAs<FunctionProtoType>(); unsigned NumArgsInProto = Proto->getNumArgs(); - unsigned NumArgsToCheck = NumArgs; - - // Build the full argument list for the method call (the - // implicit object parameter is placed at the beginning of the - // list). - Expr **MethodArgs; - if (NumArgs < NumArgsInProto) { - NumArgsToCheck = NumArgsInProto; - MethodArgs = new Expr*[NumArgsInProto + 1]; - } else { - MethodArgs = new Expr*[NumArgs + 1]; - } - MethodArgs[0] = Object.get(); - for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) - MethodArgs[ArgIdx + 1] = Args[ArgIdx]; DeclarationNameInfo OpLocInfo( Context.DeclarationNames.getCXXOperatorName(OO_Call), LParenLoc); @@ -11166,17 +11501,23 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, if (NewFn.isInvalid()) return true; + // Build the full argument list for the method call (the implicit object + // parameter is placed at the beginning of the list). + llvm::OwningArrayPtr<Expr *> MethodArgs(new Expr*[Args.size() + 1]); + MethodArgs[0] = Object.get(); + std::copy(Args.begin(), Args.end(), &MethodArgs[1]); + // Once we've built TheCall, all of the expressions are properly // owned. QualType ResultTy = Method->getResultType(); ExprValueKind VK = Expr::getValueKindForType(ResultTy); ResultTy = ResultTy.getNonLValueExprType(Context); - CXXOperatorCallExpr *TheCall = - new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn.take(), - llvm::makeArrayRef(MethodArgs, NumArgs+1), - ResultTy, VK, RParenLoc, false); - delete [] MethodArgs; + CXXOperatorCallExpr *TheCall = new (Context) + CXXOperatorCallExpr(Context, OO_Call, NewFn.take(), + llvm::makeArrayRef(MethodArgs.get(), Args.size() + 1), + ResultTy, VK, RParenLoc, false); + MethodArgs.reset(); if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall, Method)) @@ -11184,10 +11525,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, // We may have default arguments. If so, we need to allocate more // slots in the call for them. - if (NumArgs < NumArgsInProto) + if (Args.size() < NumArgsInProto) TheCall->setNumArgs(Context, NumArgsInProto + 1); - else if (NumArgs > NumArgsInProto) - NumArgsToCheck = NumArgsInProto; bool IsError = false; @@ -11202,9 +11541,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, TheCall->setArg(0, Object.take()); // Check the argument types. - for (unsigned i = 0; i != NumArgsToCheck; i++) { + for (unsigned i = 0; i != NumArgsInProto; i++) { Expr *Arg; - if (i < NumArgs) { + if (i < Args.size()) { Arg = Args[i]; // Pass the argument. @@ -11234,7 +11573,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, // If this is a variadic call, handle args passed through "...". if (Proto->isVariadic()) { // Promote the arguments (C99 6.5.2.2p7). - for (unsigned i = NumArgsInProto; i < NumArgs; i++) { + for (unsigned i = NumArgsInProto, e = Args.size(); i < e; i++) { ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0); IsError |= Arg.isInvalid(); TheCall->setArg(i + 1, Arg.take()); @@ -11243,7 +11582,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, if (IsError) return true; - DiagnoseSentinelCalls(Method, LParenLoc, Args, NumArgs); + DiagnoseSentinelCalls(Method, LParenLoc, Args); if (CheckFunctionCall(Method, TheCall, Proto)) return true; @@ -11255,7 +11594,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, /// (if one exists), where @c Base is an expression of class type and /// @c Member is the name of the member we're trying to find. ExprResult -Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { +Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, + bool *NoArrowOperatorFound) { assert(Base->getType()->isRecordType() && "left-hand side must have class type"); @@ -11299,10 +11639,21 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { break; case OR_No_Viable_Function: - if (CandidateSet.empty()) + if (CandidateSet.empty()) { + QualType BaseType = Base->getType(); + if (NoArrowOperatorFound) { + // Report this specific error to the caller instead of emitting a + // diagnostic, as requested. + *NoArrowOperatorFound = true; + return ExprError(); + } Diag(OpLoc, diag::err_typecheck_member_reference_arrow) - << Base->getType() << Base->getSourceRange(); - else + << BaseType << Base->getSourceRange(); + if (BaseType->isRecordType() && !BaseType->isPointerType()) { + Diag(OpLoc, diag::note_typecheck_member_reference_suggestion) + << FixItHint::CreateReplacement(OpLoc, "."); + } + } else Diag(OpLoc, diag::err_ovl_no_viable_oper) << "operator->" << Base->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Base); @@ -11473,7 +11824,7 @@ Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc, /*NeedsADL=*/true, /*Overloaded=*/false, FoundNames.begin(), FoundNames.end()); - bool CandidateSetError = buildOverloadedCallSet(S, Fn, Fn, &Range, 1, Loc, + bool CandidateSetError = buildOverloadedCallSet(S, Fn, Fn, Range, Loc, CandidateSet, CallExpr); if (CandidateSet->empty() || CandidateSetError) { *CallExpr = ExprError(); @@ -11487,7 +11838,7 @@ Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc, *CallExpr = ExprError(); return FRS_NoViableFunction; } - *CallExpr = FinishOverloadedCallExpr(*this, S, Fn, Fn, Loc, &Range, 1, + *CallExpr = FinishOverloadedCallExpr(*this, S, Fn, Fn, Loc, Range, Loc, 0, CandidateSet, &Best, OverloadResult, /*AllowTypoCorrection=*/false); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp index 054d557e92d0..af74f0d4a3e8 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp @@ -101,6 +101,25 @@ namespace { resultIndex); } + if (ChooseExpr *ce = dyn_cast<ChooseExpr>(e)) { + assert(!ce->isConditionDependent()); + + Expr *LHS = ce->getLHS(), *RHS = ce->getRHS(); + Expr *&rebuiltExpr = ce->isConditionTrue() ? LHS : RHS; + rebuiltExpr = rebuild(rebuiltExpr); + + return new (S.Context) ChooseExpr(ce->getBuiltinLoc(), + ce->getCond(), + LHS, RHS, + rebuiltExpr->getType(), + rebuiltExpr->getValueKind(), + rebuiltExpr->getObjectKind(), + ce->getRParenLoc(), + ce->isConditionTrue(), + rebuiltExpr->isTypeDependent(), + rebuiltExpr->isValueDependent()); + } + llvm_unreachable("bad expression to rebuild!"); } }; @@ -575,9 +594,9 @@ bool ObjCPropertyOpBuilder::findSetter(bool warn) { RefExpr->getImplicitPropertyGetter()->getSelector() .getIdentifierInfoForSlot(0); SetterSelector = - SelectorTable::constructSetterName(S.PP.getIdentifierTable(), - S.PP.getSelectorTable(), - getterName); + SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(), + S.PP.getSelectorTable(), + getterName); return false; } } @@ -711,6 +730,16 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, op = opResult.take(); assert(op && "successful assignment left argument invalid?"); } + else if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(op)) { + Expr *Initializer = OVE->getSourceExpr(); + // passing C++11 style initialized temporaries to objc++ properties + // requires special treatment by removing OpaqueValueExpr so type + // conversion takes place and adding the OpaqueValueExpr later on. + if (isa<InitListExpr>(Initializer) && + Initializer->getType()->isVoidType()) { + op = Initializer; + } + } } // Arguments. @@ -882,8 +911,8 @@ ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) { S.Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, SyntacticForm->getLocStart()); if (Level != DiagnosticsEngine::Ignored) - S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr, - SyntacticRefExpr->isMessagingGetter()); + S.recordUseOfEvaluatedWeak(SyntacticRefExpr, + SyntacticRefExpr->isMessagingGetter()); } return PseudoOpBuilder::complete(SyntacticForm); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp index 248665ac86cb..9bd8678c876a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp @@ -65,7 +65,7 @@ StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc, StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc, SourceLocation EndLoc) { - DeclGroupRef DG = dg.getAsVal<DeclGroupRef>(); + DeclGroupRef DG = dg.get(); // If we have an invalid decl, just return an error. if (DG.isNull()) return StmtError(); @@ -74,7 +74,7 @@ StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc, } void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) { - DeclGroupRef DG = dg.getAsVal<DeclGroupRef>(); + DeclGroupRef DG = dg.get(); // If we don't have a declaration, or we have an invalid declaration, // just return. @@ -93,9 +93,6 @@ void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) { return; } - // suppress any potential 'unused variable' warning. - var->setUsed(); - // foreach variables are never actually initialized in the way that // the parser came up with. var->setInit(0); @@ -294,11 +291,10 @@ sema::CompoundScopeInfo &Sema::getCurCompoundScope() const { return getCurFunction()->CompoundScopes.back(); } -StmtResult -Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, - MultiStmtArg elts, bool isStmtExpr) { - unsigned NumElts = elts.size(); - Stmt **Elts = elts.data(); +StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, + ArrayRef<Stmt *> Elts, bool isStmtExpr) { + const unsigned NumElts = Elts.size(); + // If we're in C89 mode, check that we don't have any decls after stmts. If // so, emit an extension diagnostic. if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) { @@ -335,9 +331,7 @@ Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, DiagnoseEmptyLoopBody(Elts[i], Elts[i + 1]); } - return Owned(new (Context) CompoundStmt(Context, - llvm::makeArrayRef(Elts, NumElts), - L, R)); + return Owned(new (Context) CompoundStmt(Context, Elts, L, R)); } StmtResult @@ -592,52 +586,50 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond, public: SwitchConvertDiagnoser(Expr *Cond) - : ICEConvertDiagnoser(false, true), Cond(Cond) { } + : ICEConvertDiagnoser(/*AllowScopedEnumerations*/true, false, true), + Cond(Cond) {} - virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, - QualType T) { + virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, + QualType T) { return S.Diag(Loc, diag::err_typecheck_statement_requires_integer) << T; } - virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc, - QualType T) { + virtual SemaDiagnosticBuilder diagnoseIncomplete( + Sema &S, SourceLocation Loc, QualType T) { return S.Diag(Loc, diag::err_switch_incomplete_class_type) << T << Cond->getSourceRange(); } - virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc, - QualType T, - QualType ConvTy) { + virtual SemaDiagnosticBuilder diagnoseExplicitConv( + Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) { return S.Diag(Loc, diag::err_switch_explicit_conversion) << T << ConvTy; } - virtual DiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv, - QualType ConvTy) { + virtual SemaDiagnosticBuilder noteExplicitConv( + Sema &S, CXXConversionDecl *Conv, QualType ConvTy) { return S.Diag(Conv->getLocation(), diag::note_switch_conversion) << ConvTy->isEnumeralType() << ConvTy; } - virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, - QualType T) { + virtual SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, + QualType T) { return S.Diag(Loc, diag::err_switch_multiple_conversions) << T; } - virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv, - QualType ConvTy) { + virtual SemaDiagnosticBuilder noteAmbiguous( + Sema &S, CXXConversionDecl *Conv, QualType ConvTy) { return S.Diag(Conv->getLocation(), diag::note_switch_conversion) << ConvTy->isEnumeralType() << ConvTy; } - virtual DiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc, - QualType T, - QualType ConvTy) { - return DiagnosticBuilder::getEmpty(); + virtual SemaDiagnosticBuilder diagnoseConversion( + Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) { + llvm_unreachable("conversion functions are permitted"); } } SwitchDiagnoser(Cond); - CondResult - = ConvertToIntegralOrEnumerationType(SwitchLoc, Cond, SwitchDiagnoser, - /*AllowScopedEnumerations*/ true); + CondResult = + PerformContextualImplicitConversion(SwitchLoc, Cond, SwitchDiagnoser); if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.take(); @@ -1122,9 +1114,9 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, void Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, Expr *SrcExpr) { - unsigned DIAG = diag::warn_not_in_enum_assignement; - if (Diags.getDiagnosticLevel(DIAG, SrcExpr->getExprLoc()) - == DiagnosticsEngine::Ignored) + if (Diags.getDiagnosticLevel(diag::warn_not_in_enum_assignment, + SrcExpr->getExprLoc()) == + DiagnosticsEngine::Ignored) return; if (const EnumType *ET = DstType->getAs<EnumType>()) @@ -1133,13 +1125,14 @@ Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, if (!SrcExpr->isTypeDependent() && !SrcExpr->isValueDependent() && SrcExpr->isIntegerConstantExpr(Context)) { // Get the bitwidth of the enum value before promotions. - unsigned DstWith = Context.getIntWidth(DstType); + unsigned DstWidth = Context.getIntWidth(DstType); bool DstIsSigned = DstType->isSignedIntegerOrEnumerationType(); llvm::APSInt RhsVal = SrcExpr->EvaluateKnownConstInt(Context); + AdjustAPSInt(RhsVal, DstWidth, DstIsSigned); const EnumDecl *ED = ET->getDecl(); - typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> - EnumValsTy; + typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64> + EnumValsTy; EnumValsTy EnumVals; // Gather all enum values, set their type and sort them, @@ -1147,21 +1140,21 @@ Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, for (EnumDecl::enumerator_iterator EDI = ED->enumerator_begin(); EDI != ED->enumerator_end(); ++EDI) { llvm::APSInt Val = EDI->getInitVal(); - AdjustAPSInt(Val, DstWith, DstIsSigned); + AdjustAPSInt(Val, DstWidth, DstIsSigned); EnumVals.push_back(std::make_pair(Val, *EDI)); } if (EnumVals.empty()) return; std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); EnumValsTy::iterator EIend = - std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); + std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); - // See which case values aren't in enum. + // See which values aren't in the enum. EnumValsTy::const_iterator EI = EnumVals.begin(); while (EI != EIend && EI->first < RhsVal) EI++; if (EI == EIend || EI->first != RhsVal) { - Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignement) + Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment) << DstType; } } @@ -1220,77 +1213,77 @@ namespace { // of the excluded constructs are used. class DeclExtractor : public EvaluatedExprVisitor<DeclExtractor> { llvm::SmallPtrSet<VarDecl*, 8> &Decls; - SmallVector<SourceRange, 10> &Ranges; + SmallVectorImpl<SourceRange> &Ranges; bool Simple; -public: - typedef EvaluatedExprVisitor<DeclExtractor> Inherited; - - DeclExtractor(Sema &S, llvm::SmallPtrSet<VarDecl*, 8> &Decls, - SmallVector<SourceRange, 10> &Ranges) : - Inherited(S.Context), - Decls(Decls), - Ranges(Ranges), - Simple(true) {} + public: + typedef EvaluatedExprVisitor<DeclExtractor> Inherited; - bool isSimple() { return Simple; } + DeclExtractor(Sema &S, llvm::SmallPtrSet<VarDecl*, 8> &Decls, + SmallVectorImpl<SourceRange> &Ranges) : + Inherited(S.Context), + Decls(Decls), + Ranges(Ranges), + Simple(true) {} - // Replaces the method in EvaluatedExprVisitor. - void VisitMemberExpr(MemberExpr* E) { - Simple = false; - } + bool isSimple() { return Simple; } - // Any Stmt not whitelisted will cause the condition to be marked complex. - void VisitStmt(Stmt *S) { - Simple = false; - } + // Replaces the method in EvaluatedExprVisitor. + void VisitMemberExpr(MemberExpr* E) { + Simple = false; + } - void VisitBinaryOperator(BinaryOperator *E) { - Visit(E->getLHS()); - Visit(E->getRHS()); - } + // Any Stmt not whitelisted will cause the condition to be marked complex. + void VisitStmt(Stmt *S) { + Simple = false; + } - void VisitCastExpr(CastExpr *E) { - Visit(E->getSubExpr()); - } + void VisitBinaryOperator(BinaryOperator *E) { + Visit(E->getLHS()); + Visit(E->getRHS()); + } - void VisitUnaryOperator(UnaryOperator *E) { - // Skip checking conditionals with derefernces. - if (E->getOpcode() == UO_Deref) - Simple = false; - else + void VisitCastExpr(CastExpr *E) { Visit(E->getSubExpr()); - } + } - void VisitConditionalOperator(ConditionalOperator *E) { - Visit(E->getCond()); - Visit(E->getTrueExpr()); - Visit(E->getFalseExpr()); - } + void VisitUnaryOperator(UnaryOperator *E) { + // Skip checking conditionals with derefernces. + if (E->getOpcode() == UO_Deref) + Simple = false; + else + Visit(E->getSubExpr()); + } - void VisitParenExpr(ParenExpr *E) { - Visit(E->getSubExpr()); - } + void VisitConditionalOperator(ConditionalOperator *E) { + Visit(E->getCond()); + Visit(E->getTrueExpr()); + Visit(E->getFalseExpr()); + } - void VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { - Visit(E->getOpaqueValue()->getSourceExpr()); - Visit(E->getFalseExpr()); - } + void VisitParenExpr(ParenExpr *E) { + Visit(E->getSubExpr()); + } + + void VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { + Visit(E->getOpaqueValue()->getSourceExpr()); + Visit(E->getFalseExpr()); + } - void VisitIntegerLiteral(IntegerLiteral *E) { } - void VisitFloatingLiteral(FloatingLiteral *E) { } - void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { } - void VisitCharacterLiteral(CharacterLiteral *E) { } - void VisitGNUNullExpr(GNUNullExpr *E) { } - void VisitImaginaryLiteral(ImaginaryLiteral *E) { } + void VisitIntegerLiteral(IntegerLiteral *E) { } + void VisitFloatingLiteral(FloatingLiteral *E) { } + void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { } + void VisitCharacterLiteral(CharacterLiteral *E) { } + void VisitGNUNullExpr(GNUNullExpr *E) { } + void VisitImaginaryLiteral(ImaginaryLiteral *E) { } - void VisitDeclRefExpr(DeclRefExpr *E) { - VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()); - if (!VD) return; + void VisitDeclRefExpr(DeclRefExpr *E) { + VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()); + if (!VD) return; - Ranges.push_back(E->getSourceRange()); + Ranges.push_back(E->getSourceRange()); - Decls.insert(VD); - } + Decls.insert(VD); + } }; // end class DeclExtractor @@ -1300,66 +1293,67 @@ public: llvm::SmallPtrSet<VarDecl*, 8> &Decls; bool FoundDecl; -public: - typedef EvaluatedExprVisitor<DeclMatcher> Inherited; + public: + typedef EvaluatedExprVisitor<DeclMatcher> Inherited; - DeclMatcher(Sema &S, llvm::SmallPtrSet<VarDecl*, 8> &Decls, Stmt *Statement) : - Inherited(S.Context), Decls(Decls), FoundDecl(false) { - if (!Statement) return; + DeclMatcher(Sema &S, llvm::SmallPtrSet<VarDecl*, 8> &Decls, + Stmt *Statement) : + Inherited(S.Context), Decls(Decls), FoundDecl(false) { + if (!Statement) return; - Visit(Statement); - } + Visit(Statement); + } - void VisitReturnStmt(ReturnStmt *S) { - FoundDecl = true; - } + void VisitReturnStmt(ReturnStmt *S) { + FoundDecl = true; + } - void VisitBreakStmt(BreakStmt *S) { - FoundDecl = true; - } + void VisitBreakStmt(BreakStmt *S) { + FoundDecl = true; + } - void VisitGotoStmt(GotoStmt *S) { - FoundDecl = true; - } + void VisitGotoStmt(GotoStmt *S) { + FoundDecl = true; + } - void VisitCastExpr(CastExpr *E) { - if (E->getCastKind() == CK_LValueToRValue) - CheckLValueToRValueCast(E->getSubExpr()); - else - Visit(E->getSubExpr()); - } + void VisitCastExpr(CastExpr *E) { + if (E->getCastKind() == CK_LValueToRValue) + CheckLValueToRValueCast(E->getSubExpr()); + else + Visit(E->getSubExpr()); + } - void CheckLValueToRValueCast(Expr *E) { - E = E->IgnoreParenImpCasts(); + void CheckLValueToRValueCast(Expr *E) { + E = E->IgnoreParenImpCasts(); - if (isa<DeclRefExpr>(E)) { - return; - } + if (isa<DeclRefExpr>(E)) { + return; + } - if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { - Visit(CO->getCond()); - CheckLValueToRValueCast(CO->getTrueExpr()); - CheckLValueToRValueCast(CO->getFalseExpr()); - return; - } + if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { + Visit(CO->getCond()); + CheckLValueToRValueCast(CO->getTrueExpr()); + CheckLValueToRValueCast(CO->getFalseExpr()); + return; + } - if (BinaryConditionalOperator *BCO = - dyn_cast<BinaryConditionalOperator>(E)) { - CheckLValueToRValueCast(BCO->getOpaqueValue()->getSourceExpr()); - CheckLValueToRValueCast(BCO->getFalseExpr()); - return; - } + if (BinaryConditionalOperator *BCO = + dyn_cast<BinaryConditionalOperator>(E)) { + CheckLValueToRValueCast(BCO->getOpaqueValue()->getSourceExpr()); + CheckLValueToRValueCast(BCO->getFalseExpr()); + return; + } - Visit(E); - } + Visit(E); + } - void VisitDeclRefExpr(DeclRefExpr *E) { - if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) - if (Decls.count(VD)) - FoundDecl = true; - } + void VisitDeclRefExpr(DeclRefExpr *E) { + if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) + if (Decls.count(VD)) + FoundDecl = true; + } - bool FoundDeclInUse() { return FoundDecl; } + bool FoundDeclInUse() { return FoundDecl; } }; // end class DeclMatcher @@ -1411,7 +1405,7 @@ public: // Load SourceRanges into diagnostic if there is room. // Otherwise, load the SourceRange of the conditional expression. if (Ranges.size() <= PartialDiagnostic::MaxArguments) - for (SmallVector<SourceRange, 10>::iterator I = Ranges.begin(), + for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) PDiag << *I; @@ -1421,6 +1415,104 @@ public: S.Diag(Ranges.begin()->getBegin(), PDiag); } + // If Statement is an incemement or decrement, return true and sets the + // variables Increment and DRE. + bool ProcessIterationStmt(Sema &S, Stmt* Statement, bool &Increment, + DeclRefExpr *&DRE) { + if (UnaryOperator *UO = dyn_cast<UnaryOperator>(Statement)) { + switch (UO->getOpcode()) { + default: return false; + case UO_PostInc: + case UO_PreInc: + Increment = true; + break; + case UO_PostDec: + case UO_PreDec: + Increment = false; + break; + } + DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr()); + return DRE; + } + + if (CXXOperatorCallExpr *Call = dyn_cast<CXXOperatorCallExpr>(Statement)) { + FunctionDecl *FD = Call->getDirectCallee(); + if (!FD || !FD->isOverloadedOperator()) return false; + switch (FD->getOverloadedOperator()) { + default: return false; + case OO_PlusPlus: + Increment = true; + break; + case OO_MinusMinus: + Increment = false; + break; + } + DRE = dyn_cast<DeclRefExpr>(Call->getArg(0)); + return DRE; + } + + return false; + } + + // A visitor to determine if a continue statement is a subexpression. + class ContinueFinder : public EvaluatedExprVisitor<ContinueFinder> { + bool Found; + public: + ContinueFinder(Sema &S, Stmt* Body) : + Inherited(S.Context), + Found(false) { + Visit(Body); + } + + typedef EvaluatedExprVisitor<ContinueFinder> Inherited; + + void VisitContinueStmt(ContinueStmt* E) { + Found = true; + } + + bool ContinueFound() { return Found; } + + }; // end class ContinueFinder + + // Emit a warning when a loop increment/decrement appears twice per loop + // iteration. The conditions which trigger this warning are: + // 1) The last statement in the loop body and the third expression in the + // for loop are both increment or both decrement of the same variable + // 2) No continue statements in the loop body. + void CheckForRedundantIteration(Sema &S, Expr *Third, Stmt *Body) { + // Return when there is nothing to check. + if (!Body || !Third) return; + + if (S.Diags.getDiagnosticLevel(diag::warn_redundant_loop_iteration, + Third->getLocStart()) + == DiagnosticsEngine::Ignored) + return; + + // Get the last statement from the loop body. + CompoundStmt *CS = dyn_cast<CompoundStmt>(Body); + if (!CS || CS->body_empty()) return; + Stmt *LastStmt = CS->body_back(); + if (!LastStmt) return; + + bool LoopIncrement, LastIncrement; + DeclRefExpr *LoopDRE, *LastDRE; + + if (!ProcessIterationStmt(S, Third, LoopIncrement, LoopDRE)) return; + if (!ProcessIterationStmt(S, LastStmt, LastIncrement, LastDRE)) return; + + // Check that the two statements are both increments or both decrements + // on the same varaible. + if (LoopIncrement != LastIncrement || + LoopDRE->getDecl() != LastDRE->getDecl()) return; + + if (ContinueFinder(S, Body).ContinueFound()) return; + + S.Diag(LastDRE->getLocation(), diag::warn_redundant_loop_iteration) + << LastDRE->getDecl() << LastIncrement; + S.Diag(LoopDRE->getLocation(), diag::note_loop_iteration_here) + << LoopIncrement; + } + } // end namespace StmtResult @@ -1447,6 +1539,7 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, } CheckForLoopConditionalStatement(*this, second.get(), third.get(), Body); + CheckForRedundantIteration(*this, third.get(), Body); ExprResult SecondResult(second.release()); VarDecl *ConditionVar = 0; @@ -1618,6 +1711,9 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, << First->getSourceRange()); FirstType = static_cast<Expr*>(First)->getType(); + if (FirstType.isConstQualified()) + Diag(ForLoc, diag::err_selector_element_const_type) + << FirstType << First->getSourceRange(); } if (!FirstType->isDependentType() && !FirstType->isObjCObjectPointerType() && @@ -1738,10 +1834,10 @@ StmtResult Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, Stmt *First, SourceLocation ColonLoc, Expr *Range, SourceLocation RParenLoc, BuildForRangeKind Kind) { - if (!First || !Range) + if (!First) return StmtError(); - if (ObjCEnumerationCollection(Range)) + if (Range && ObjCEnumerationCollection(Range)) return ActOnObjCForCollectionStmt(ForLoc, First, Range, RParenLoc); DeclStmt *DS = dyn_cast<DeclStmt>(First); @@ -1751,11 +1847,13 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, Diag(DS->getStartLoc(), diag::err_type_defined_in_for_range); return StmtError(); } - if (DS->getSingleDecl()->isInvalidDecl()) - return StmtError(); - if (DiagnoseUnexpandedParameterPack(Range, UPPC_Expression)) + Decl *LoopVar = DS->getSingleDecl(); + if (LoopVar->isInvalidDecl() || !Range || + DiagnoseUnexpandedParameterPack(Range, UPPC_Expression)) { + LoopVar->setInvalidDecl(); return StmtError(); + } // Build auto && __range = range-init SourceLocation RangeLoc = Range->getLocStart(); @@ -1763,15 +1861,20 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, Context.getAutoRRefDeductType(), "__range"); if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc, - diag::err_for_range_deduction_failure)) + diag::err_for_range_deduction_failure)) { + LoopVar->setInvalidDecl(); return StmtError(); + } // Claim the type doesn't contain auto: we've already done the checking. DeclGroupPtrTy RangeGroup = - BuildDeclaratorGroup((Decl**)&RangeVar, 1, /*TypeMayContainAuto=*/false); + BuildDeclaratorGroup(llvm::MutableArrayRef<Decl *>((Decl **)&RangeVar, 1), + /*TypeMayContainAuto=*/ false); StmtResult RangeDecl = ActOnDeclStmt(RangeGroup, RangeLoc, RangeLoc); - if (RangeDecl.isInvalid()) + if (RangeDecl.isInvalid()) { + LoopVar->setInvalidDecl(); return StmtError(); + } return BuildCXXForRangeStmt(ForLoc, ColonLoc, RangeDecl.get(), /*BeginEndDecl=*/0, /*Cond=*/0, /*Inc=*/0, DS, @@ -1900,6 +2003,22 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S, Sema::BFRK_Rebuild); } +namespace { +/// RAII object to automatically invalidate a declaration if an error occurs. +struct InvalidateOnErrorScope { + InvalidateOnErrorScope(Sema &SemaRef, Decl *D, bool Enabled) + : Trap(SemaRef.Diags), D(D), Enabled(Enabled) {} + ~InvalidateOnErrorScope() { + if (Enabled && Trap.hasErrorOccurred()) + D->setInvalidDecl(); + } + + DiagnosticErrorTrap Trap; + Decl *D; + bool Enabled; +}; +} + /// BuildCXXForRangeStmt - Build or instantiate a C++11 for-range statement. StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, @@ -1915,12 +2034,17 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, DeclStmt *LoopVarDS = cast<DeclStmt>(LoopVarDecl); VarDecl *LoopVar = cast<VarDecl>(LoopVarDS->getSingleDecl()); + // If we hit any errors, mark the loop variable as invalid if its type + // contains 'auto'. + InvalidateOnErrorScope Invalidate(*this, LoopVar, + LoopVar->getType()->isUndeducedType()); + StmtResult BeginEndDecl = BeginEnd; ExprResult NotEqExpr = Cond, IncrExpr = Inc; if (RangeVarType->isDependentType()) { // The range is implicitly used as a placeholder when it is dependent. - RangeVar->setUsed(); + RangeVar->markUsed(Context); // Deduce any 'auto's in the loop variable as 'DependentTy'. We'll fill // them in properly when we instantiate the loop. @@ -1981,8 +2105,6 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, RangeLoc)); else if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(UnqAT)) - // FIXME: Need to build an OpaqueValueExpr for this rather than - // recomputing it! BoundExpr = VAT->getSizeExpr(); else { // Can't be a DependentSizedArrayType or an IncompleteArrayType since @@ -2009,10 +2131,25 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, BeginVar, EndVar, ColonLoc, &CandidateSet, &BeginExpr, &EndExpr, &BEFFailure); - // If building the range failed, try dereferencing the range expression - // unless a diagnostic was issued or the end function is problematic. if (Kind == BFRK_Build && RangeStatus == FRS_NoViableFunction && BEFFailure == BEF_begin) { + // If the range is being built from an array parameter, emit a + // a diagnostic that it is being treated as a pointer. + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Range)) { + if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) { + QualType ArrayTy = PVD->getOriginalType(); + QualType PointerTy = PVD->getType(); + if (PointerTy->isPointerType() && ArrayTy->isArrayType()) { + Diag(Range->getLocStart(), diag::err_range_on_array_parameter) + << RangeLoc << PVD << ArrayTy << PointerTy; + Diag(PVD->getLocation(), diag::note_declared_at); + return StmtError(); + } + } + } + + // If building the range failed, try dereferencing the range expression + // unless a diagnostic was issued or the end function is problematic. StmtResult SR = RebuildForRangeWithDereference(*this, S, ForLoc, LoopVarDecl, ColonLoc, Range, RangeLoc, @@ -2048,7 +2185,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, Decl *BeginEndDecls[] = { BeginVar, EndVar }; // Claim the type doesn't contain auto: we've already done the checking. DeclGroupPtrTy BeginEndGroup = - BuildDeclaratorGroup(BeginEndDecls, 2, /*TypeMayContainAuto=*/false); + BuildDeclaratorGroup(llvm::MutableArrayRef<Decl *>(BeginEndDecls, 2), + /*TypeMayContainAuto=*/ false); BeginEndDecl = ActOnDeclStmt(BeginEndGroup, ColonLoc, ColonLoc); const QualType BeginRefNonRefType = BeginType.getNonReferenceType(); @@ -2162,7 +2300,7 @@ StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, LabelDecl *TheDecl) { getCurFunction()->setHasBranchIntoScope(); - TheDecl->setUsed(); + TheDecl->markUsed(Context); return Owned(new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc)); } @@ -2356,28 +2494,51 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, return Res; } +/// \brief Determine whether the declared return type of the specified function +/// contains 'auto'. +static bool hasDeducedReturnType(FunctionDecl *FD) { + const FunctionProtoType *FPT = + FD->getTypeSourceInfo()->getType()->castAs<FunctionProtoType>(); + return FPT->getResultType()->isUndeducedType(); +} + /// ActOnCapScopeReturnStmt - Utility routine to type-check return statements /// for capturing scopes. /// StmtResult 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. + // [expr.prim.lambda]p4 in C++11; block literals follow the same rules. CapturingScopeInfo *CurCap = cast<CapturingScopeInfo>(getCurFunction()); QualType FnRetType = CurCap->ReturnType; + LambdaScopeInfo *CurLambda = dyn_cast<LambdaScopeInfo>(CurCap); - // For blocks/lambdas with implicit return types, we check each return - // statement individually, and deduce the common return type when the block - // or lambda is completed. - if (CurCap->HasImplicitReturnType) { + if (CurLambda && hasDeducedReturnType(CurLambda->CallOperator)) { + // In C++1y, the return type may involve 'auto'. + // FIXME: Blocks might have a return type of 'auto' explicitly specified. + FunctionDecl *FD = CurLambda->CallOperator; + if (CurCap->ReturnType.isNull()) + CurCap->ReturnType = FD->getResultType(); + + AutoType *AT = CurCap->ReturnType->getContainedAutoType(); + assert(AT && "lost auto type from lambda return type"); + if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) { + FD->setInvalidDecl(); + return StmtError(); + } + CurCap->ReturnType = FnRetType = FD->getResultType(); + } else if (CurCap->HasImplicitReturnType) { + // For blocks/lambdas with implicit return types, we check each return + // statement individually, and deduce the common return type when the block + // or lambda is completed. + // FIXME: Fold this into the 'auto' codepath above. if (RetValExp && !isa<InitListExpr>(RetValExp)) { ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp); if (Result.isInvalid()) return StmtError(); RetValExp = Result.take(); - if (!RetValExp->isTypeDependent()) + if (!CurContext->isDependentContext()) FnRetType = RetValExp->getType(); else FnRetType = CurCap->ReturnType = Context.DependentTy; @@ -2410,8 +2571,9 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { Diag(ReturnLoc, diag::err_return_in_captured_stmt) << CurRegion->getRegionName(); return StmtError(); } else { - LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CurCap); - if (LSI->CallOperator->getType()->getAs<FunctionType>()->getNoReturnAttr()){ + assert(CurLambda && "unknown kind of captured scope"); + if (CurLambda->CallOperator->getType()->getAs<FunctionType>() + ->getNoReturnAttr()) { Diag(ReturnLoc, diag::err_noreturn_lambda_has_return_expr); return StmtError(); } @@ -2492,7 +2654,24 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, IgnoreParens().castAs<FunctionProtoTypeLoc>().getResultLoc(); QualType Deduced; - if (RetExpr) { + if (RetExpr && isa<InitListExpr>(RetExpr)) { + // If the deduction is for a return statement and the initializer is + // a braced-init-list, the program is ill-formed. + Diag(RetExpr->getExprLoc(), + getCurLambda() ? diag::err_lambda_return_init_list + : diag::err_auto_fn_return_init_list) + << RetExpr->getSourceRange(); + return true; + } + + if (FD->isDependentContext()) { + // C++1y [dcl.spec.auto]p12: + // Return type deduction [...] occurs when the definition is + // instantiated even if the function body contains a return + // statement with a non-type-dependent operand. + assert(AT->isDeduced() && "should have deduced to dependent type"); + return false; + } else if (RetExpr) { // If the deduction is for a return statement and the initializer is // a braced-init-list, the program is ill-formed. if (isa<InitListExpr>(RetExpr)) { @@ -2533,10 +2712,18 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, // the program is ill-formed. if (AT->isDeduced() && !FD->isInvalidDecl()) { AutoType *NewAT = Deduced->getContainedAutoType(); - if (!Context.hasSameType(AT->getDeducedType(), NewAT->getDeducedType())) { - Diag(ReturnLoc, diag::err_auto_fn_different_deductions) - << (AT->isDecltypeAuto() ? 1 : 0) - << NewAT->getDeducedType() << AT->getDeducedType(); + if (!FD->isDependentContext() && + !Context.hasSameType(AT->getDeducedType(), NewAT->getDeducedType())) { + const LambdaScopeInfo *LambdaSI = getCurLambda(); + if (LambdaSI && LambdaSI->HasImplicitReturnType) { + Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible) + << NewAT->getDeducedType() << AT->getDeducedType() + << true /*IsLambda*/; + } else { + Diag(ReturnLoc, diag::err_auto_fn_different_deductions) + << (AT->isDecltypeAuto() ? 1 : 0) + << NewAT->getDeducedType() << AT->getDeducedType(); + } return true; } } else if (!FD->isInvalidDecl()) { @@ -2553,9 +2740,6 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp)) return StmtError(); - // FIXME: Unify this and C++1y auto function handling. In particular, we - // should allow 'return { 1, 2, 3 };' in a lambda to deduce - // 'std::initializer_list<int>'. if (isa<CapturingScopeInfo>(getCurFunction())) return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp); @@ -2580,13 +2764,10 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // FIXME: Add a flag to the ScopeInfo to indicate whether we're performing // deduction. - bool HasDependentReturnType = FnRetType->isDependentType(); if (getLangOpts().CPlusPlus1y) { if (AutoType *AT = FnRetType->getContainedAutoType()) { FunctionDecl *FD = cast<FunctionDecl>(CurContext); - if (CurContext->isDependentContext()) - HasDependentReturnType = true; - else if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) { + if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) { FD->setInvalidDecl(); return StmtError(); } else { @@ -2595,6 +2776,8 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } } + bool HasDependentReturnType = FnRetType->isDependentType(); + ReturnStmt *Result = 0; if (FnRetType->isVoidType()) { if (RetValExp) { @@ -2699,11 +2882,10 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // If we have a related result type, we need to implicitly // convert back to the formal result type. We can't pretend to // initialize the result again --- we might end double-retaining - // --- so instead we initialize a notional temporary; this can - // lead to less-than-great diagnostics, but this stage is much - // less likely to fail than the previous stage. + // --- so instead we initialize a notional temporary. if (!RelatedRetType.isNull()) { - Entity = InitializedEntity::InitializeTemporary(FnRetType); + Entity = InitializedEntity::InitializeRelatedResult(getCurMethodDecl(), + FnRetType); Res = PerformCopyInitialization(Entity, ReturnLoc, RetValExp); if (Res.isInvalid()) { // FIXME: Clean up temporaries here anyway? @@ -2886,18 +3068,16 @@ public: /// ActOnCXXTryBlock - Takes a try compound-statement and a number of /// handlers and creates a try statement from them. -StmtResult -Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, - MultiStmtArg RawHandlers) { +StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, + ArrayRef<Stmt *> Handlers) { // Don't report an error if 'try' is used in system headers. if (!getLangOpts().CXXExceptions && !getSourceManager().isInSystemHeader(TryLoc)) Diag(TryLoc, diag::err_exceptions_disabled) << "try"; - unsigned NumHandlers = RawHandlers.size(); + const unsigned NumHandlers = Handlers.size(); assert(NumHandlers > 0 && "The parser shouldn't call this if there are no handlers."); - Stmt **Handlers = RawHandlers.data(); SmallVector<TypeWithHandler, 8> TypesWithHandlers; @@ -2945,8 +3125,7 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, // Neither of these are explicitly forbidden, but every compiler detects them // and warns. - return Owned(CXXTryStmt::Create(Context, TryLoc, TryBlock, - llvm::makeArrayRef(Handlers, NumHandlers))); + return Owned(CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers)); } StmtResult @@ -3051,7 +3230,7 @@ static void buildCapturedStmtCaptureList( if (Cap->isThisCapture()) { Captures.push_back(CapturedStmt::Capture(Cap->getLocation(), CapturedStmt::VCK_This)); - CaptureInits.push_back(Cap->getCopyExpr()); + CaptureInits.push_back(Cap->getInitExpr()); continue; } @@ -3061,7 +3240,7 @@ static void buildCapturedStmtCaptureList( Captures.push_back(CapturedStmt::Capture(Cap->getLocation(), CapturedStmt::VCK_ByRef, Cap->getVariable())); - CaptureInits.push_back(Cap->getCopyExpr()); + CaptureInits.push_back(Cap->getInitExpr()); } } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp index fce95bebd1a9..9169032178fe 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp @@ -77,13 +77,12 @@ static bool isOperandMentioned(unsigned OpNo, StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, bool IsVolatile, unsigned NumOutputs, unsigned NumInputs, IdentifierInfo **Names, - MultiExprArg constraints, MultiExprArg exprs, + MultiExprArg constraints, MultiExprArg Exprs, Expr *asmString, MultiExprArg clobbers, SourceLocation RParenLoc) { unsigned NumClobbers = clobbers.size(); StringLiteral **Constraints = reinterpret_cast<StringLiteral**>(constraints.data()); - Expr **Exprs = exprs.data(); StringLiteral *AsmString = cast<StringLiteral>(asmString); StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data()); @@ -204,8 +203,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, GCCAsmStmt *NS = new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, - NumInputs, Names, Constraints, Exprs, AsmString, - NumClobbers, Clobbers, RParenLoc); + NumInputs, Names, Constraints, Exprs.data(), + AsmString, NumClobbers, Clobbers, RParenLoc); // Validate the asm string, ensuring it makes sense given the operands we // have. SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces; @@ -382,7 +381,9 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS, ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id, /*trailing lparen*/ false, - /*is & operand*/ false); + /*is & operand*/ false, + /*CorrectionCandidateCallback=*/0, + /*IsInlineAsmIdentifier=*/ true); if (IsUnevaluatedContext) PopExpressionEvaluationContext(); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp index b9695cc1e166..28603daa267c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp @@ -11,6 +11,7 @@ #include "TreeTransform.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTConsumer.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" @@ -207,8 +208,9 @@ TemplateNameKind Sema::isTemplateName(Scope *S, R.suppressDiagnostics(); } else { assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) || - isa<TypeAliasTemplateDecl>(TD)); - TemplateKind = TNK_Type_template; + isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD)); + TemplateKind = + isa<VarTemplateDecl>(TD) ? TNK_Var_template : TNK_Type_template; } } @@ -256,7 +258,8 @@ void Sema::LookupTemplateName(LookupResult &Found, assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); LookupCtx = computeDeclContext(ObjectType); isDependent = ObjectType->isDependentType(); - assert((isDependent || !ObjectType->isIncompleteType()) && + assert((isDependent || !ObjectType->isIncompleteType() || + ObjectType->castAs<TagType>()->isBeingDefined()) && "Caller should have completed object type"); // Template names cannot appear inside an Objective-C class or object type. @@ -328,20 +331,16 @@ void Sema::LookupTemplateName(LookupResult &Found, Found.addDecl(Corrected.getCorrectionDecl()); FilterAcceptableTemplateNames(Found); if (!Found.empty()) { - 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() - << FixItHint::CreateReplacement(Corrected.getCorrectionRange(), - CorrectedStr); - else - Diag(Found.getNameLoc(), diag::err_no_template_suggest) - << Name << CorrectedQuotedStr - << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr); - if (TemplateDecl *Template = Found.getAsSingle<TemplateDecl>()) - Diag(Template->getLocation(), diag::note_previous_decl) - << CorrectedQuotedStr; + if (LookupCtx) { + std::string CorrectedStr(Corrected.getAsString(getLangOpts())); + bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && + Name.getAsString() == CorrectedStr; + diagnoseTypo(Corrected, PDiag(diag::err_no_member_template_suggest) + << Name << LookupCtx << DroppedSpecifier + << SS.getRange()); + } else { + diagnoseTypo(Corrected, PDiag(diag::err_no_template_suggest) << Name); + } } } else { Found.setLookupName(Name); @@ -356,7 +355,7 @@ void Sema::LookupTemplateName(LookupResult &Found, } if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope && - !(getLangOpts().CPlusPlus11 && !Found.empty())) { + !getLangOpts().CPlusPlus11) { // C++03 [basic.lookup.classref]p1: // [...] If the lookup in the class of the object expression finds a // template, the name is also looked up in the context of the entire @@ -533,6 +532,15 @@ void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn, TemplateArgsIn[I])); } +static void maybeDiagnoseTemplateParameterShadow(Sema &SemaRef, Scope *S, + SourceLocation Loc, + IdentifierInfo *Name) { + NamedDecl *PrevDecl = SemaRef.LookupSingleName( + S, Name, Loc, Sema::LookupOrdinaryName, Sema::ForRedeclaration); + if (PrevDecl && PrevDecl->isTemplateParameter()) + SemaRef.DiagnoseTemplateParameterShadow(Loc, PrevDecl); +} + /// ActOnTypeParameter - Called when a C++ template type parameter /// (e.g., "typename T") has been parsed. Typename specifies whether /// the keyword "typename" was used to declare the type parameter @@ -554,16 +562,6 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, "Template type parameter not in template parameter scope!"); bool Invalid = false; - if (ParamName) { - NamedDecl *PrevDecl = LookupSingleName(S, ParamName, ParamNameLoc, - LookupOrdinaryName, - ForRedeclaration); - if (PrevDecl && PrevDecl->isTemplateParameter()) { - DiagnoseTemplateParameterShadow(ParamNameLoc, PrevDecl); - PrevDecl = 0; - } - } - SourceLocation Loc = ParamNameLoc; if (!ParamName) Loc = KeyLoc; @@ -577,6 +575,8 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, Param->setInvalidDecl(); if (ParamName) { + maybeDiagnoseTemplateParameterShadow(*this, S, ParamNameLoc, ParamName); + // Add the template parameter into the current scope. S->AddDecl(Param); IdResolver.AddDecl(Param); @@ -682,23 +682,13 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, "Non-type template parameter not in template parameter scope!"); bool Invalid = false; - IdentifierInfo *ParamName = D.getIdentifier(); - if (ParamName) { - NamedDecl *PrevDecl = LookupSingleName(S, ParamName, D.getIdentifierLoc(), - LookupOrdinaryName, - ForRedeclaration); - if (PrevDecl && PrevDecl->isTemplateParameter()) { - DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); - PrevDecl = 0; - } - } - T = CheckNonTypeTemplateParameterType(T, D.getIdentifierLoc()); if (T.isNull()) { T = Context.IntTy; // Recover with an 'int' type. Invalid = true; } + IdentifierInfo *ParamName = D.getIdentifier(); bool IsParameterPack = D.hasEllipsis(); NonTypeTemplateParmDecl *Param = NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(), @@ -707,11 +697,14 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, Depth, Position, ParamName, T, IsParameterPack, TInfo); Param->setAccess(AS_public); - + if (Invalid) Param->setInvalidDecl(); - if (D.getIdentifier()) { + if (ParamName) { + maybeDiagnoseTemplateParameterShadow(*this, S, D.getIdentifierLoc(), + ParamName); + // Add the template parameter into the current scope. S->AddDecl(Param); IdResolver.AddDecl(Param); @@ -773,6 +766,8 @@ Decl *Sema::ActOnTemplateTemplateParameter(Scope* S, // If the template template parameter has a name, then link the identifier // into the scope and lookup mechanisms. if (Name) { + maybeDiagnoseTemplateParameterShadow(*this, S, NameLoc, Name); + S->AddDecl(Param); IdResolver.AddDecl(Param); } @@ -882,10 +877,11 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // 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) + Diag(NameLoc, TUK == TUK_Friend + ? diag::warn_template_qualified_friend_ignored + : diag::err_template_qualified_declarator_no_match) << SS.getScopeRep() << SS.getRange(); - return true; + return TUK != TUK_Friend; } if (RequireCompleteDeclContext(SS, SemanticContext)) @@ -1032,13 +1028,14 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // template declaration. Skip this check for a friend in a dependent // context, because the template parameter list might be dependent. if (!(TUK == TUK_Friend && CurContext->isDependentContext()) && - CheckTemplateParameterList(TemplateParams, - PrevClassTemplate? PrevClassTemplate->getTemplateParameters() : 0, - (SS.isSet() && SemanticContext && - SemanticContext->isRecord() && - SemanticContext->isDependentContext()) - ? TPC_ClassTemplateMember - : TPC_ClassTemplate)) + CheckTemplateParameterList( + TemplateParams, + PrevClassTemplate ? PrevClassTemplate->getTemplateParameters() : 0, + (SS.isSet() && SemanticContext && SemanticContext->isRecord() && + SemanticContext->isDependentContext()) + ? TPC_ClassTemplateMember + : TUK == TUK_Friend ? TPC_FriendClassTemplate + : TPC_ClassTemplate)) Invalid = true; if (SS.isSet()) { @@ -1046,8 +1043,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // template out-of-line. if (!SS.isInvalid() && !Invalid && !PrevClassTemplate) { Diag(NameLoc, TUK == TUK_Friend ? diag::err_friend_decl_does_not_match - : diag::err_member_def_does_not_match) - << Name << SemanticContext << SS.getRange(); + : diag::err_member_decl_does_not_match) + << Name << SemanticContext << /*IsDefinition*/true << SS.getRange(); Invalid = true; } } @@ -1118,8 +1115,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, NewClass->setAccess(PrevClassTemplate->getAccess()); } - NewTemplate->setObjectOfFriendDecl(/* PreviouslyDeclared = */ - PrevClassTemplate != NULL); + NewTemplate->setObjectOfFriendDecl(); // Friend templates are visible in fairly strange ways. if (!CurContext->isDependentContext()) { @@ -1158,6 +1154,7 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S, SourceRange DefArgRange) { switch (TPC) { case Sema::TPC_ClassTemplate: + case Sema::TPC_VarTemplate: case Sema::TPC_TypeAliasTemplate: return false; @@ -1186,6 +1183,7 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S, << DefArgRange; return true; + case Sema::TPC_FriendClassTemplate: case Sema::TPC_FriendFunctionTemplate: // C++ [temp.param]p9: // A default template-argument shall not be specified in a @@ -1317,7 +1315,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, } else if (OldTypeParm && OldTypeParm->hasDefaultArgument()) { // Merge the default argument from the old declaration to the // new declaration. - SawDefaultArgument = true; NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgumentInfo(), true); PreviousDefaultArgLoc = OldTypeParm->getDefaultArgumentLoc(); @@ -1354,7 +1351,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, if (!NewNonTypeParm->isPackExpansion()) SawParameterPack = true; } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() && - NewNonTypeParm->hasDefaultArgument()) { + NewNonTypeParm->hasDefaultArgument()) { OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc(); NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc(); SawDefaultArgument = true; @@ -1363,7 +1360,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument()) { // Merge the default argument from the old declaration to the // new declaration. - SawDefaultArgument = true; // FIXME: We need to create a new kind of "default argument" // expression that points to a previous non-type template // parameter. @@ -1411,7 +1407,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument()) { // Merge the default argument from the old declaration to the // new declaration. - SawDefaultArgument = true; // FIXME: We need to create a new kind of "default argument" expression // that points to a previous template template parameter. NewTemplateParm->setDefaultArgument( @@ -1431,7 +1426,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // 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)) { + (TPC == TPC_ClassTemplate || TPC == TPC_VarTemplate || + TPC == TPC_TypeAliasTemplate)) { Diag((*NewParam)->getLocation(), diag::err_template_param_pack_must_be_last_template_parameter); Invalid = true; @@ -1584,8 +1580,6 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context, /// \param ParamLists the template parameter lists, from the outermost to the /// innermost template parameter lists. /// -/// \param NumParamLists the number of template parameter lists in ParamLists. -/// /// \param IsFriend Whether to apply the slightly different rules for /// matching template parameters to scope specifiers in friend /// declarations. @@ -1599,15 +1593,10 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context, /// template) or may have no template parameters (if we're declaring a /// template specialization), or may be NULL (if what we're declaring isn't /// itself a template). -TemplateParameterList * -Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, - SourceLocation DeclLoc, - const CXXScopeSpec &SS, - TemplateParameterList **ParamLists, - unsigned NumParamLists, - bool IsFriend, - bool &IsExplicitSpecialization, - bool &Invalid) { +TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( + SourceLocation DeclStartLoc, SourceLocation DeclLoc, const CXXScopeSpec &SS, + ArrayRef<TemplateParameterList *> ParamLists, bool IsFriend, + bool &IsExplicitSpecialization, bool &Invalid) { IsExplicitSpecialization = false; Invalid = false; @@ -1780,7 +1769,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // unspecialized, except that the declaration shall not explicitly // specialize a class member template if its en- closing class templates // are not explicitly specialized as well. - if (ParamIdx < NumParamLists) { + if (ParamIdx < ParamLists.size()) { if (ParamLists[ParamIdx]->size() == 0) { if (SawNonEmptyTemplateParameterList) { Diag(DeclLoc, diag::err_specialize_member_of_template) @@ -1798,8 +1787,8 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // here, then it's an explicit specialization. if (TypeIdx == NumTypes - 1) IsExplicitSpecialization = true; - - if (ParamIdx < NumParamLists) { + + if (ParamIdx < ParamLists.size()) { if (ParamLists[ParamIdx]->size() > 0) { // The header has template parameters when it shouldn't. Complain. Diag(ParamLists[ParamIdx]->getTemplateLoc(), @@ -1820,7 +1809,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, if (!IsFriend) { // We don't have a template header, but we should. SourceLocation ExpectedTemplateLoc; - if (NumParamLists > 0) + if (!ParamLists.empty()) ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc(); else ExpectedTemplateLoc = DeclStartLoc; @@ -1839,15 +1828,15 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // assume that empty parameter lists are supposed to match this // template-id. if (IsFriend && T->isDependentType()) { - if (ParamIdx < NumParamLists && + if (ParamIdx < ParamLists.size() && DependsOnTemplateParameters(T, ParamLists[ParamIdx])) ExpectedTemplateParams = 0; else continue; } - if (ParamIdx < NumParamLists) { - // Check the template parameter list, if we can. + if (ParamIdx < ParamLists.size()) { + // Check the template parameter list, if we can. if (ExpectedTemplateParams && !TemplateParameterListsAreEqual(ParamLists[ParamIdx], ExpectedTemplateParams, @@ -1874,25 +1863,25 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // If there were at least as many template-ids as there were template // parameter lists, then there are no template parameter lists remaining for // the declaration itself. - if (ParamIdx >= NumParamLists) + if (ParamIdx >= ParamLists.size()) return 0; // If there were too many template parameter lists, complain about that now. - if (ParamIdx < NumParamLists - 1) { + if (ParamIdx < ParamLists.size() - 1) { bool HasAnyExplicitSpecHeader = false; bool AllExplicitSpecHeaders = true; - for (unsigned I = ParamIdx; I != NumParamLists - 1; ++I) { + for (unsigned I = ParamIdx, E = ParamLists.size() - 1; I != E; ++I) { if (ParamLists[I]->size() == 0) HasAnyExplicitSpecHeader = true; else AllExplicitSpecHeaders = false; } - + Diag(ParamLists[ParamIdx]->getTemplateLoc(), - AllExplicitSpecHeaders? diag::warn_template_spec_extra_headers - : diag::err_template_spec_extra_headers) - << SourceRange(ParamLists[ParamIdx]->getTemplateLoc(), - ParamLists[NumParamLists - 2]->getRAngleLoc()); + AllExplicitSpecHeaders ? diag::warn_template_spec_extra_headers + : diag::err_template_spec_extra_headers) + << SourceRange(ParamLists[ParamIdx]->getTemplateLoc(), + ParamLists[ParamLists.size() - 2]->getRAngleLoc()); // If there was a specialization somewhere, such that 'template<>' is // not required, and there were any 'template<>' headers, note where the @@ -1916,8 +1905,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // unspecialized, except that the declaration shall not explicitly // specialize a class member template if its en- closing class templates // are not explicitly specialized as well. - if (ParamLists[NumParamLists - 1]->size() == 0 && - SawNonEmptyTemplateParameterList) { + if (ParamLists.back()->size() == 0 && SawNonEmptyTemplateParameterList) { Diag(DeclLoc, diag::err_specialize_member_of_template) << ParamLists[ParamIdx]->getSourceRange(); Invalid = true; @@ -1927,17 +1915,20 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // Return the last template parameter list, which corresponds to the // entity being declared. - return ParamLists[NumParamLists - 1]; + return ParamLists.back(); } void Sema::NoteAllFoundTemplates(TemplateName Name) { if (TemplateDecl *Template = Name.getAsTemplateDecl()) { Diag(Template->getLocation(), diag::note_template_declared_here) - << (isa<FunctionTemplateDecl>(Template)? 0 - : isa<ClassTemplateDecl>(Template)? 1 - : isa<TypeAliasTemplateDecl>(Template)? 2 - : 3) - << Template->getDeclName(); + << (isa<FunctionTemplateDecl>(Template) + ? 0 + : isa<ClassTemplateDecl>(Template) + ? 1 + : isa<VarTemplateDecl>(Template) + ? 2 + : isa<TypeAliasTemplateDecl>(Template) ? 3 : 4) + << Template->getDeclName(); return; } @@ -2007,11 +1998,11 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); unsigned Depth = AliasTemplate->getTemplateParameters()->getDepth(); for (unsigned I = 0; I < Depth; ++I) - TemplateArgLists.addOuterTemplateArguments(0, 0); + TemplateArgLists.addOuterTemplateArguments(None); LocalInstantiationScope Scope(*this); InstantiatingTemplate Inst(*this, TemplateLoc, Template); - if (Inst) + if (Inst.isInvalid()) return QualType(); CanonType = SubstType(Pattern->getUnderlyingType(), @@ -2102,6 +2093,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext()); } + // Diagnose uses of this specialization. + (void)DiagnoseUseOfDecl(Decl, TemplateLoc); + CanonType = Context.getTypeDeclType(Decl); assert(isa<RecordType>(CanonType) && "type of non-dependent specialization is not a RecordType"); @@ -2123,7 +2117,7 @@ Sema::ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, if (SS.isInvalid()) return true; - TemplateName Template = TemplateD.getAsVal<TemplateName>(); + TemplateName Template = TemplateD.get(); // Translate the parser's template argument list in our AST format. TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); @@ -2190,7 +2184,7 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, SourceLocation RAngleLoc) { - TemplateName Template = TemplateD.getAsVal<TemplateName>(); + TemplateName Template = TemplateD.get(); // Translate the parser's template argument list in our AST format. TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); @@ -2272,6 +2266,499 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); } +static bool CheckTemplatePartialSpecializationArgs( + Sema &S, TemplateParameterList *TemplateParams, + SmallVectorImpl<TemplateArgument> &TemplateArgs); + +static bool CheckTemplateSpecializationScope(Sema &S, NamedDecl *Specialized, + NamedDecl *PrevDecl, + SourceLocation Loc, + bool IsPartialSpecialization); + +static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D); + +static bool isTemplateArgumentTemplateParameter( + const TemplateArgument &Arg, unsigned Depth, unsigned Index) { + switch (Arg.getKind()) { + case TemplateArgument::Null: + case TemplateArgument::NullPtr: + case TemplateArgument::Integral: + case TemplateArgument::Declaration: + case TemplateArgument::Pack: + case TemplateArgument::TemplateExpansion: + return false; + + case TemplateArgument::Type: { + QualType Type = Arg.getAsType(); + const TemplateTypeParmType *TPT = + Arg.getAsType()->getAs<TemplateTypeParmType>(); + return TPT && !Type.hasQualifiers() && + TPT->getDepth() == Depth && TPT->getIndex() == Index; + } + + case TemplateArgument::Expression: { + DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg.getAsExpr()); + if (!DRE || !DRE->getDecl()) + return false; + const NonTypeTemplateParmDecl *NTTP = + dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl()); + return NTTP && NTTP->getDepth() == Depth && NTTP->getIndex() == Index; + } + + case TemplateArgument::Template: + const TemplateTemplateParmDecl *TTP = + dyn_cast_or_null<TemplateTemplateParmDecl>( + Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()); + return TTP && TTP->getDepth() == Depth && TTP->getIndex() == Index; + } + llvm_unreachable("unexpected kind of template argument"); +} + +static bool isSameAsPrimaryTemplate(TemplateParameterList *Params, + ArrayRef<TemplateArgument> Args) { + if (Params->size() != Args.size()) + return false; + + unsigned Depth = Params->getDepth(); + + for (unsigned I = 0, N = Args.size(); I != N; ++I) { + TemplateArgument Arg = Args[I]; + + // If the parameter is a pack expansion, the argument must be a pack + // whose only element is a pack expansion. + if (Params->getParam(I)->isParameterPack()) { + if (Arg.getKind() != TemplateArgument::Pack || Arg.pack_size() != 1 || + !Arg.pack_begin()->isPackExpansion()) + return false; + Arg = Arg.pack_begin()->getPackExpansionPattern(); + } + + if (!isTemplateArgumentTemplateParameter(Arg, Depth, I)) + return false; + } + + return true; +} + +DeclResult Sema::ActOnVarTemplateSpecialization( + Scope *S, VarTemplateDecl *VarTemplate, Declarator &D, TypeSourceInfo *DI, + SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams, + VarDecl::StorageClass SC, bool IsPartialSpecialization) { + assert(VarTemplate && "A variable template id without template?"); + + // D must be variable template id. + assert(D.getName().getKind() == UnqualifiedId::IK_TemplateId && + "Variable template specialization is declared with a template it."); + + TemplateIdAnnotation *TemplateId = D.getName().TemplateId; + SourceLocation TemplateNameLoc = D.getIdentifierLoc(); + SourceLocation LAngleLoc = TemplateId->LAngleLoc; + SourceLocation RAngleLoc = TemplateId->RAngleLoc; + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); + translateTemplateArguments(TemplateArgsPtr, TemplateArgs); + TemplateName Name(VarTemplate); + + // Check for unexpanded parameter packs in any of the template arguments. + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + if (DiagnoseUnexpandedParameterPack(TemplateArgs[I], + UPPC_PartialSpecialization)) + return true; + + // Check that the template argument list is well-formed for this + // template. + SmallVector<TemplateArgument, 4> Converted; + if (CheckTemplateArgumentList(VarTemplate, TemplateNameLoc, TemplateArgs, + false, Converted)) + return true; + + // Check that the type of this variable template specialization + // matches the expected type. + TypeSourceInfo *ExpectedDI; + { + // Do substitution on the type of the declaration + TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack, + Converted.data(), Converted.size()); + InstantiatingTemplate Inst(*this, TemplateKWLoc, VarTemplate); + if (Inst.isInvalid()) + return true; + VarDecl *Templated = VarTemplate->getTemplatedDecl(); + ExpectedDI = + SubstType(Templated->getTypeSourceInfo(), + MultiLevelTemplateArgumentList(TemplateArgList), + Templated->getTypeSpecStartLoc(), Templated->getDeclName()); + } + if (!ExpectedDI) + return true; + + // Find the variable template (partial) specialization declaration that + // corresponds to these arguments. + if (IsPartialSpecialization) { + if (CheckTemplatePartialSpecializationArgs( + *this, VarTemplate->getTemplateParameters(), Converted)) + return true; + + bool InstantiationDependent; + if (!Name.isDependent() && + !TemplateSpecializationType::anyDependentTemplateArguments( + TemplateArgs.getArgumentArray(), TemplateArgs.size(), + InstantiationDependent)) { + Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized) + << VarTemplate->getDeclName(); + IsPartialSpecialization = false; + } + + if (isSameAsPrimaryTemplate(VarTemplate->getTemplateParameters(), + Converted)) { + // C++ [temp.class.spec]p9b3: + // + // -- The argument list of the specialization shall not be identical + // to the implicit argument list of the primary template. + Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template) + << /*variable template*/ 1 + << /*is definition*/(SC != SC_Extern && !CurContext->isRecord()) + << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc)); + // FIXME: Recover from this by treating the declaration as a redeclaration + // of the primary template. + return true; + } + } + + void *InsertPos = 0; + VarTemplateSpecializationDecl *PrevDecl = 0; + + if (IsPartialSpecialization) + // FIXME: Template parameter list matters too + PrevDecl = VarTemplate->findPartialSpecialization( + Converted.data(), Converted.size(), InsertPos); + else + PrevDecl = VarTemplate->findSpecialization(Converted.data(), + Converted.size(), InsertPos); + + VarTemplateSpecializationDecl *Specialization = 0; + + // Check whether we can declare a variable template specialization in + // the current scope. + if (CheckTemplateSpecializationScope(*this, VarTemplate, PrevDecl, + TemplateNameLoc, + IsPartialSpecialization)) + return true; + + if (PrevDecl && PrevDecl->getSpecializationKind() == TSK_Undeclared) { + // Since the only prior variable template specialization with these + // arguments was referenced but not declared, reuse that + // declaration node as our own, updating its source location and + // the list of outer template parameters to reflect our new declaration. + Specialization = PrevDecl; + Specialization->setLocation(TemplateNameLoc); + PrevDecl = 0; + } else if (IsPartialSpecialization) { + // Create a new class template partial specialization declaration node. + VarTemplatePartialSpecializationDecl *PrevPartial = + cast_or_null<VarTemplatePartialSpecializationDecl>(PrevDecl); + VarTemplatePartialSpecializationDecl *Partial = + VarTemplatePartialSpecializationDecl::Create( + Context, VarTemplate->getDeclContext(), TemplateKWLoc, + TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC, + Converted.data(), Converted.size(), TemplateArgs); + + if (!PrevPartial) + VarTemplate->AddPartialSpecialization(Partial, InsertPos); + Specialization = Partial; + + // If we are providing an explicit specialization of a member variable + // template specialization, make a note of that. + if (PrevPartial && PrevPartial->getInstantiatedFromMember()) + PrevPartial->setMemberSpecialization(); + + // Check that all of the template parameters of the variable template + // partial specialization are deducible from the template + // arguments. If not, this variable template partial specialization + // will never be used. + llvm::SmallBitVector DeducibleParams(TemplateParams->size()); + MarkUsedTemplateParameters(Partial->getTemplateArgs(), true, + TemplateParams->getDepth(), DeducibleParams); + + if (!DeducibleParams.all()) { + unsigned NumNonDeducible = + DeducibleParams.size() - DeducibleParams.count(); + Diag(TemplateNameLoc, diag::warn_partial_specs_not_deducible) + << /*variable template*/ 1 << (NumNonDeducible > 1) + << SourceRange(TemplateNameLoc, RAngleLoc); + for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) { + if (!DeducibleParams[I]) { + NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I)); + if (Param->getDeclName()) + Diag(Param->getLocation(), diag::note_partial_spec_unused_parameter) + << Param->getDeclName(); + else + Diag(Param->getLocation(), diag::note_partial_spec_unused_parameter) + << "<anonymous>"; + } + } + } + } else { + // Create a new class template specialization declaration node for + // this explicit specialization or friend declaration. + Specialization = VarTemplateSpecializationDecl::Create( + Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc, + VarTemplate, DI->getType(), DI, SC, Converted.data(), Converted.size()); + Specialization->setTemplateArgsInfo(TemplateArgs); + + if (!PrevDecl) + VarTemplate->AddSpecialization(Specialization, InsertPos); + } + + // C++ [temp.expl.spec]p6: + // If a template, a member template or the member of a class template is + // 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. + if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) { + bool Okay = false; + for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) { + // Is there any previous explicit specialization declaration? + if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) { + Okay = true; + break; + } + } + + if (!Okay) { + SourceRange Range(TemplateNameLoc, RAngleLoc); + Diag(TemplateNameLoc, diag::err_specialization_after_instantiation) + << Name << Range; + + Diag(PrevDecl->getPointOfInstantiation(), + diag::note_instantiation_required_here) + << (PrevDecl->getTemplateSpecializationKind() != + TSK_ImplicitInstantiation); + return true; + } + } + + Specialization->setTemplateKeywordLoc(TemplateKWLoc); + Specialization->setLexicalDeclContext(CurContext); + + // Add the specialization into its lexical context, so that it can + // be seen when iterating through the list of declarations in that + // context. However, specializations are not found by name lookup. + CurContext->addDecl(Specialization); + + // Note that this is an explicit specialization. + Specialization->setSpecializationKind(TSK_ExplicitSpecialization); + + if (PrevDecl) { + // Check that this isn't a redefinition of this specialization, + // merging with previous declarations. + LookupResult PrevSpec(*this, GetNameForDeclarator(D), LookupOrdinaryName, + ForRedeclaration); + PrevSpec.addDecl(PrevDecl); + D.setRedeclaration(CheckVariableDeclaration(Specialization, PrevSpec)); + } else if (Specialization->isStaticDataMember() && + Specialization->isOutOfLine()) { + Specialization->setAccess(VarTemplate->getAccess()); + } + + // Link instantiations of static data members back to the template from + // which they were instantiated. + if (Specialization->isStaticDataMember()) + Specialization->setInstantiationOfStaticDataMember( + VarTemplate->getTemplatedDecl(), + Specialization->getSpecializationKind()); + + return Specialization; +} + +namespace { +/// \brief A partial specialization whose template arguments have matched +/// a given template-id. +struct PartialSpecMatchResult { + VarTemplatePartialSpecializationDecl *Partial; + TemplateArgumentList *Args; +}; +} + +DeclResult +Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, + SourceLocation TemplateNameLoc, + const TemplateArgumentListInfo &TemplateArgs) { + assert(Template && "A variable template id without template?"); + + // Check that the template argument list is well-formed for this template. + SmallVector<TemplateArgument, 4> Converted; + bool ExpansionIntoFixedList = false; + if (CheckTemplateArgumentList( + Template, TemplateNameLoc, + const_cast<TemplateArgumentListInfo &>(TemplateArgs), false, + Converted, &ExpansionIntoFixedList)) + return true; + + // Find the variable template specialization declaration that + // corresponds to these arguments. + void *InsertPos = 0; + if (VarTemplateSpecializationDecl *Spec = Template->findSpecialization( + Converted.data(), Converted.size(), InsertPos)) + // If we already have a variable template specialization, return it. + return Spec; + + // This is the first time we have referenced this variable template + // specialization. Create the canonical declaration and add it to + // the set of specializations, based on the closest partial specialization + // that it represents. That is, + VarDecl *InstantiationPattern = Template->getTemplatedDecl(); + TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack, + Converted.data(), Converted.size()); + TemplateArgumentList *InstantiationArgs = &TemplateArgList; + bool AmbiguousPartialSpec = false; + typedef PartialSpecMatchResult MatchResult; + SmallVector<MatchResult, 4> Matched; + SourceLocation PointOfInstantiation = TemplateNameLoc; + TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation); + + // 1. Attempt to find the closest partial specialization that this + // specializes, if any. + // If any of the template arguments is dependent, then this is probably + // a placeholder for an incomplete declarative context; which must be + // complete by instantiation time. Thus, do not search through the partial + // specializations yet. + // TODO: Unify with InstantiateClassTemplateSpecialization()? + // Perhaps better after unification of DeduceTemplateArguments() and + // getMoreSpecializedPartialSpecialization(). + bool InstantiationDependent = false; + if (!TemplateSpecializationType::anyDependentTemplateArguments( + TemplateArgs, InstantiationDependent)) { + + SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs; + Template->getPartialSpecializations(PartialSpecs); + + for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) { + VarTemplatePartialSpecializationDecl *Partial = PartialSpecs[I]; + TemplateDeductionInfo Info(FailedCandidates.getLocation()); + + if (TemplateDeductionResult Result = + DeduceTemplateArguments(Partial, TemplateArgList, Info)) { + // Store the failed-deduction information for use in diagnostics, later. + // TODO: Actually use the failed-deduction info? + FailedCandidates.addCandidate() + .set(Partial, MakeDeductionFailureInfo(Context, Result, Info)); + (void)Result; + } else { + Matched.push_back(PartialSpecMatchResult()); + Matched.back().Partial = Partial; + Matched.back().Args = Info.take(); + } + } + + // If we're dealing with a member template where the template parameters + // have been instantiated, this provides the original template parameters + // from which the member template's parameters were instantiated. + SmallVector<const NamedDecl *, 4> InstantiatedTemplateParameters; + + if (Matched.size() >= 1) { + SmallVector<MatchResult, 4>::iterator Best = Matched.begin(); + if (Matched.size() == 1) { + // -- If exactly one matching specialization is found, the + // instantiation is generated from that specialization. + // We don't need to do anything for this. + } else { + // -- If more than one matching specialization is found, the + // partial order rules (14.5.4.2) are used to determine + // whether one of the specializations is more specialized + // than the others. If none of the specializations is more + // specialized than all of the other matching + // specializations, then the use of the variable template is + // ambiguous and the program is ill-formed. + for (SmallVector<MatchResult, 4>::iterator P = Best + 1, + PEnd = Matched.end(); + P != PEnd; ++P) { + if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial, + PointOfInstantiation) == + P->Partial) + Best = P; + } + + // Determine if the best partial specialization is more specialized than + // the others. + for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(), + PEnd = Matched.end(); + P != PEnd; ++P) { + if (P != Best && getMoreSpecializedPartialSpecialization( + P->Partial, Best->Partial, + PointOfInstantiation) != Best->Partial) { + AmbiguousPartialSpec = true; + break; + } + } + } + + // Instantiate using the best variable template partial specialization. + InstantiationPattern = Best->Partial; + InstantiationArgs = Best->Args; + } else { + // -- If no match is found, the instantiation is generated + // from the primary template. + // InstantiationPattern = Template->getTemplatedDecl(); + } + } + + // 2. Create the canonical declaration. + // Note that we do not instantiate the variable just yet, since + // instantiation is handled in DoMarkVarDeclReferenced(). + // FIXME: LateAttrs et al.? + VarTemplateSpecializationDecl *Decl = BuildVarTemplateInstantiation( + Template, InstantiationPattern, *InstantiationArgs, TemplateArgs, + Converted, TemplateNameLoc, InsertPos /*, LateAttrs, StartingScope*/); + if (!Decl) + return true; + + if (AmbiguousPartialSpec) { + // Partial ordering did not produce a clear winner. Complain. + Decl->setInvalidDecl(); + Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous) + << Decl; + + // Print the matching partial specializations. + for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(), + PEnd = Matched.end(); + P != PEnd; ++P) + Diag(P->Partial->getLocation(), diag::note_partial_spec_match) + << getTemplateArgumentBindingsText( + P->Partial->getTemplateParameters(), *P->Args); + return true; + } + + if (VarTemplatePartialSpecializationDecl *D = + dyn_cast<VarTemplatePartialSpecializationDecl>(InstantiationPattern)) + Decl->setInstantiationOf(D, InstantiationArgs); + + assert(Decl && "No variable template specialization?"); + return Decl; +} + +ExprResult +Sema::CheckVarTemplateId(const CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo, + VarTemplateDecl *Template, SourceLocation TemplateLoc, + const TemplateArgumentListInfo *TemplateArgs) { + + DeclResult Decl = CheckVarTemplateId(Template, TemplateLoc, NameInfo.getLoc(), + *TemplateArgs); + if (Decl.isInvalid()) + return ExprError(); + + VarDecl *Var = cast<VarDecl>(Decl.get()); + if (!Var->getTemplateSpecializationKind()) + Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation, + NameInfo.getLoc()); + + // Build an ordinary singleton decl ref. + return BuildDeclarationNameExpr(SS, NameInfo, Var, + /*FoundD=*/0, TemplateArgs); +} + ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, @@ -2291,6 +2778,13 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, assert(!R.empty() && "empty lookup results when building templateid"); assert(!R.isAmbiguous() && "ambiguous lookup when building templateid"); + // In C++1y, check variable template ids. + if (R.getAsSingle<VarTemplateDecl>()) { + return Owned(CheckVarTemplateId(SS, R.getLookupNameInfo(), + R.getAsSingle<VarTemplateDecl>(), + TemplateKWLoc, TemplateArgs)); + } + // We don't want lookup warnings at this point. R.suppressDiagnostics(); @@ -2311,6 +2805,7 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs) { + assert(TemplateArgs || TemplateKWLoc.isValid()); DeclContext *DC; if (!(DC = computeDeclContext(SS, false)) || @@ -2564,22 +3059,25 @@ SubstDefaultTemplateArgument(Sema &SemaRef, // If the argument type is dependent, instantiate it now based // on the previously-computed template arguments. if (ArgType->getType()->isDependentType()) { - TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, - Converted.data(), Converted.size()); - - MultiLevelTemplateArgumentList AllTemplateArgs - = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs); - Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, Template, Converted, SourceRange(TemplateLoc, RAngleLoc)); - if (Inst) + if (Inst.isInvalid()) return 0; + TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, + Converted.data(), Converted.size()); + + // Only substitute for the innermost template argument list. + MultiLevelTemplateArgumentList TemplateArgLists; + TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); + for (unsigned i = 0, e = Param->getDepth(); i != e; ++i) + TemplateArgLists.addOuterTemplateArguments(None); + Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext()); - ArgType = SemaRef.SubstType(ArgType, AllTemplateArgs, - Param->getDefaultArgumentLoc(), - Param->getDeclName()); + ArgType = + SemaRef.SubstType(ArgType, TemplateArgLists, + Param->getDefaultArgumentLoc(), Param->getDeclName()); } return ArgType; @@ -2614,21 +3112,24 @@ SubstDefaultTemplateArgument(Sema &SemaRef, SourceLocation RAngleLoc, NonTypeTemplateParmDecl *Param, SmallVectorImpl<TemplateArgument> &Converted) { - TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, - Converted.data(), Converted.size()); - - MultiLevelTemplateArgumentList AllTemplateArgs - = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs); - Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, Template, Converted, SourceRange(TemplateLoc, RAngleLoc)); - if (Inst) + if (Inst.isInvalid()) return ExprError(); + TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, + Converted.data(), Converted.size()); + + // Only substitute for the innermost template argument list. + MultiLevelTemplateArgumentList TemplateArgLists; + TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); + for (unsigned i = 0, e = Param->getDepth(); i != e; ++i) + TemplateArgLists.addOuterTemplateArguments(None); + Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext()); EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); - return SemaRef.SubstExpr(Param->getDefaultArgument(), AllTemplateArgs); + return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists); } /// \brief Substitute template arguments into the default template argument for @@ -2664,32 +3165,35 @@ SubstDefaultTemplateArgument(Sema &SemaRef, TemplateTemplateParmDecl *Param, SmallVectorImpl<TemplateArgument> &Converted, NestedNameSpecifierLoc &QualifierLoc) { + Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, Template, Converted, + SourceRange(TemplateLoc, RAngleLoc)); + if (Inst.isInvalid()) + return TemplateName(); + TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted.data(), Converted.size()); - MultiLevelTemplateArgumentList AllTemplateArgs - = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs); - - Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, - Template, Converted, - SourceRange(TemplateLoc, RAngleLoc)); - if (Inst) - return TemplateName(); + // Only substitute for the innermost template argument list. + MultiLevelTemplateArgumentList TemplateArgLists; + TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); + for (unsigned i = 0, e = Param->getDepth(); i != e; ++i) + TemplateArgLists.addOuterTemplateArguments(None); Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext()); - // Substitute into the nested-name-specifier first, + // Substitute into the nested-name-specifier first, QualifierLoc = Param->getDefaultArgument().getTemplateQualifierLoc(); if (QualifierLoc) { - QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, - AllTemplateArgs); + QualifierLoc = + SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgLists); if (!QualifierLoc) return TemplateName(); } - - return SemaRef.SubstTemplateName(QualifierLoc, - Param->getDefaultArgument().getArgument().getAsTemplate(), - Param->getDefaultArgument().getTemplateNameLoc(), - AllTemplateArgs); + + return SemaRef.SubstTemplateName( + QualifierLoc, + Param->getDefaultArgument().getArgument().getAsTemplate(), + Param->getDefaultArgument().getTemplateNameLoc(), + TemplateArgLists); } /// \brief If the given template parameter has a default template @@ -2700,11 +3204,16 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation RAngleLoc, Decl *Param, - SmallVectorImpl<TemplateArgument> &Converted) { - if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) { + SmallVectorImpl<TemplateArgument> + &Converted, + bool &HasDefaultArg) { + HasDefaultArg = false; + + if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) { if (!TypeParm->hasDefaultArgument()) return TemplateArgumentLoc(); + HasDefaultArg = true; TypeSourceInfo *DI = SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, @@ -2721,6 +3230,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, if (!NonTypeParm->hasDefaultArgument()) return TemplateArgumentLoc(); + HasDefaultArg = true; ExprResult Arg = SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, @@ -2738,7 +3248,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, if (!TempTempParm->hasDefaultArgument()) return TemplateArgumentLoc(); - + HasDefaultArg = true; NestedNameSpecifierLoc QualifierLoc; TemplateName TName = SubstDefaultTemplateArgument(*this, Template, TemplateLoc, @@ -2808,7 +3318,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, InstantiatingTemplate Inst(*this, TemplateLoc, Template, NTTP, Converted, SourceRange(TemplateLoc, RAngleLoc)); - if (Inst) + if (Inst.isInvalid()) return true; TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, @@ -2943,7 +3453,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, InstantiatingTemplate Inst(*this, TemplateLoc, Template, TempParm, Converted, SourceRange(TemplateLoc, RAngleLoc)); - if (Inst) + if (Inst.isInvalid()) return true; TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, @@ -3110,8 +3620,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // deduced argument and place it on the argument pack. Note that we // stay on the same template parameter so that we can deduce more // arguments. - ArgumentPack.push_back(Converted.back()); - Converted.pop_back(); + ArgumentPack.push_back(Converted.pop_back_val()); } else { // Move to the next template parameter. ++Param; @@ -3255,10 +3764,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // Introduce an instantiation record that describes where we are using // the default template argument. - InstantiatingTemplate Instantiating(*this, RAngleLoc, Template, - *Param, Converted, - SourceRange(TemplateLoc, RAngleLoc)); - if (Instantiating) + InstantiatingTemplate Inst(*this, RAngleLoc, Template, *Param, Converted, + SourceRange(TemplateLoc, RAngleLoc)); + if (Inst.isInvalid()) return true; // Check the default template argument. @@ -3655,6 +4163,63 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, return NPV_NotNullPointer; } +/// \brief Checks whether the given template argument is compatible with its +/// template parameter. +static bool CheckTemplateArgumentIsCompatibleWithParameter( + Sema &S, NonTypeTemplateParmDecl *Param, QualType ParamType, Expr *ArgIn, + Expr *Arg, QualType ArgType) { + bool ObjCLifetimeConversion; + if (ParamType->isPointerType() && + !ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType() && + S.IsQualificationConversion(ArgType, ParamType, false, + ObjCLifetimeConversion)) { + // For pointer-to-object types, qualification conversions are + // permitted. + } else { + if (const ReferenceType *ParamRef = ParamType->getAs<ReferenceType>()) { + if (!ParamRef->getPointeeType()->isFunctionType()) { + // C++ [temp.arg.nontype]p5b3: + // For a non-type template-parameter of type reference to + // object, no conversions apply. The type referred to by the + // reference may be more cv-qualified than the (otherwise + // identical) type of the template- argument. The + // template-parameter is bound directly to the + // template-argument, which shall be an lvalue. + + // FIXME: Other qualifiers? + unsigned ParamQuals = ParamRef->getPointeeType().getCVRQualifiers(); + unsigned ArgQuals = ArgType.getCVRQualifiers(); + + if ((ParamQuals | ArgQuals) != ParamQuals) { + S.Diag(Arg->getLocStart(), + diag::err_template_arg_ref_bind_ignores_quals) + << ParamType << Arg->getType() << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + } + } + + // At this point, the template argument refers to an object or + // function with external linkage. We now need to check whether the + // argument and parameter types are compatible. + if (!S.Context.hasSameUnqualifiedType(ArgType, + ParamType.getNonReferenceType())) { + // We can't perform this conversion or binding. + if (ParamType->isReferenceType()) + S.Diag(Arg->getLocStart(), diag::err_template_arg_no_ref_bind) + << ParamType << ArgIn->getType() << Arg->getSourceRange(); + else + S.Diag(Arg->getLocStart(), diag::err_template_arg_not_convertible) + << ArgIn->getType() << ParamType << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + } + + return false; +} + /// \brief Checks whether the given template argument is the address /// of an object or function according to C++ [temp.arg.nontype]p1. static bool @@ -3682,68 +4247,110 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, break; } } - - // See through any implicit casts we added to fix the type. - Arg = Arg->IgnoreImpCasts(); - // C++ [temp.arg.nontype]p1: - // - // A template-argument for a non-type, non-template - // template-parameter shall be one of: [...] - // - // -- the address of an object or function with external - // linkage, including function templates and function - // template-ids but excluding non-static class members, - // expressed as & id-expression where the & is optional if - // the name refers to a function or array, or if the - // corresponding template-parameter is a reference; or - - // In C++98/03 mode, give an extension warning on any extra parentheses. - // See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773 - bool ExtraParens = false; - while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { - if (!Invalid && !ExtraParens) { - S.Diag(Arg->getLocStart(), - S.getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_template_arg_extra_parens : - diag::ext_template_arg_extra_parens) - << Arg->getSourceRange(); - ExtraParens = true; + bool AddressTaken = false; + SourceLocation AddrOpLoc; + if (S.getLangOpts().MicrosoftExt) { + // Microsoft Visual C++ strips all casts, allows an arbitrary number of + // dereference and address-of operators. + Arg = Arg->IgnoreParenCasts(); + + bool ExtWarnMSTemplateArg = false; + UnaryOperatorKind FirstOpKind; + SourceLocation FirstOpLoc; + while (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) { + UnaryOperatorKind UnOpKind = UnOp->getOpcode(); + if (UnOpKind == UO_Deref) + ExtWarnMSTemplateArg = true; + if (UnOpKind == UO_AddrOf || UnOpKind == UO_Deref) { + Arg = UnOp->getSubExpr()->IgnoreParenCasts(); + if (!AddrOpLoc.isValid()) { + FirstOpKind = UnOpKind; + FirstOpLoc = UnOp->getOperatorLoc(); + } + } else + break; + } + if (FirstOpLoc.isValid()) { + if (ExtWarnMSTemplateArg) + S.Diag(ArgIn->getLocStart(), diag::ext_ms_deref_template_argument) + << ArgIn->getSourceRange(); + + if (FirstOpKind == UO_AddrOf) + AddressTaken = true; + else if (Arg->getType()->isPointerType()) { + // We cannot let pointers get dereferenced here, that is obviously not a + // constant expression. + assert(FirstOpKind == UO_Deref); + S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref) + << Arg->getSourceRange(); + } } + } else { + // See through any implicit casts we added to fix the type. + Arg = Arg->IgnoreImpCasts(); - Arg = Parens->getSubExpr(); - } + // C++ [temp.arg.nontype]p1: + // + // A template-argument for a non-type, non-template + // template-parameter shall be one of: [...] + // + // -- the address of an object or function with external + // linkage, including function templates and function + // template-ids but excluding non-static class members, + // expressed as & id-expression where the & is optional if + // the name refers to a function or array, or if the + // corresponding template-parameter is a reference; or + + // In C++98/03 mode, give an extension warning on any extra parentheses. + // See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773 + bool ExtraParens = false; + while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { + if (!Invalid && !ExtraParens) { + S.Diag(Arg->getLocStart(), + S.getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_template_arg_extra_parens + : diag::ext_template_arg_extra_parens) + << Arg->getSourceRange(); + ExtraParens = true; + } - while (SubstNonTypeTemplateParmExpr *subst = - dyn_cast<SubstNonTypeTemplateParmExpr>(Arg)) - Arg = subst->getReplacement()->IgnoreImpCasts(); + Arg = Parens->getSubExpr(); + } - bool AddressTaken = false; - SourceLocation AddrOpLoc; - if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) { - if (UnOp->getOpcode() == UO_AddrOf) { - Arg = UnOp->getSubExpr(); - AddressTaken = true; - AddrOpLoc = UnOp->getOperatorLoc(); + while (SubstNonTypeTemplateParmExpr *subst = + dyn_cast<SubstNonTypeTemplateParmExpr>(Arg)) + Arg = subst->getReplacement()->IgnoreImpCasts(); + + if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) { + if (UnOp->getOpcode() == UO_AddrOf) { + Arg = UnOp->getSubExpr(); + AddressTaken = true; + AddrOpLoc = UnOp->getOperatorLoc(); + } } + + while (SubstNonTypeTemplateParmExpr *subst = + dyn_cast<SubstNonTypeTemplateParmExpr>(Arg)) + Arg = subst->getReplacement()->IgnoreImpCasts(); } - if (S.getLangOpts().MicrosoftExt && isa<CXXUuidofExpr>(Arg)) { + // 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; } - while (SubstNonTypeTemplateParmExpr *subst = - dyn_cast<SubstNonTypeTemplateParmExpr>(Arg)) - Arg = subst->getReplacement()->IgnoreImpCasts(); + if (isa<CXXUuidofExpr>(Arg)) { + if (CheckTemplateArgumentIsCompatibleWithParameter(S, Param, ParamType, + ArgIn, Arg, ArgType)) + 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) @@ -3752,20 +4359,12 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, return true; } - if (!isa<ValueDecl>(DRE->getDecl())) { - 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; - } - ValueDecl *Entity = DRE->getDecl(); // Cannot refer to non-static data members - if (FieldDecl *Field = dyn_cast<FieldDecl>(Entity)) { + if (isa<FieldDecl>(Entity) || isa<IndirectFieldDecl>(Entity)) { S.Diag(Arg->getLocStart(), diag::err_template_arg_field) - << Field << Arg->getSourceRange(); + << Entity << Arg->getSourceRange(); S.Diag(Param->getLocation(), diag::note_template_param_here); return true; } @@ -3793,14 +4392,14 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, } // Address / reference template args must have external linkage in C++98. - if (Entity->getLinkage() == InternalLinkage) { + if (Entity->getFormalLinkage() == InternalLinkage) { S.Diag(Arg->getLocStart(), S.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_template_arg_object_internal : diag::ext_template_arg_object_internal) << !Func << Entity << Arg->getSourceRange(); S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object) << !Func; - } else if (Entity->getLinkage() == NoLinkage) { + } else if (!Entity->hasLinkage()) { 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) @@ -3896,55 +4495,9 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, } } - bool ObjCLifetimeConversion; - if (ParamType->isPointerType() && - !ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType() && - S.IsQualificationConversion(ArgType, ParamType, false, - ObjCLifetimeConversion)) { - // For pointer-to-object types, qualification conversions are - // permitted. - } else { - if (const ReferenceType *ParamRef = ParamType->getAs<ReferenceType>()) { - if (!ParamRef->getPointeeType()->isFunctionType()) { - // C++ [temp.arg.nontype]p5b3: - // For a non-type template-parameter of type reference to - // object, no conversions apply. The type referred to by the - // reference may be more cv-qualified than the (otherwise - // identical) type of the template- argument. The - // template-parameter is bound directly to the - // template-argument, which shall be an lvalue. - - // FIXME: Other qualifiers? - unsigned ParamQuals = ParamRef->getPointeeType().getCVRQualifiers(); - unsigned ArgQuals = ArgType.getCVRQualifiers(); - - if ((ParamQuals | ArgQuals) != ParamQuals) { - S.Diag(Arg->getLocStart(), - diag::err_template_arg_ref_bind_ignores_quals) - << ParamType << Arg->getType() - << Arg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); - return true; - } - } - } - - // At this point, the template argument refers to an object or - // function with external linkage. We now need to check whether the - // argument and parameter types are compatible. - if (!S.Context.hasSameUnqualifiedType(ArgType, - ParamType.getNonReferenceType())) { - // We can't perform this conversion or binding. - if (ParamType->isReferenceType()) - S.Diag(Arg->getLocStart(), diag::err_template_arg_no_ref_bind) - << ParamType << ArgIn->getType() << Arg->getSourceRange(); - else - S.Diag(Arg->getLocStart(), diag::err_template_arg_not_convertible) - << ArgIn->getType() << ParamType << Arg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); - return true; - } - } + if (CheckTemplateArgumentIsCompatibleWithParameter(S, Param, ParamType, ArgIn, + Arg, ArgType)) + return true; // Create the template argument. Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()), @@ -4035,9 +4588,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, else if ((DRE = dyn_cast<DeclRefExpr>(Arg))) { if (ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) { if (VD->getType()->isMemberPointerType()) { - if (isa<NonTypeTemplateParmDecl>(VD) || - (isa<VarDecl>(VD) && - S.Context.getCanonicalType(VD->getType()).isConstQualified())) { + if (isa<NonTypeTemplateParmDecl>(VD)) { if (Arg->isTypeDependent() || Arg->isValueDependent()) { Converted = TemplateArgument(Arg); } else { @@ -4057,8 +4608,11 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, diag::err_template_arg_not_pointer_to_member_form) << Arg->getSourceRange(); - if (isa<FieldDecl>(DRE->getDecl()) || isa<CXXMethodDecl>(DRE->getDecl())) { + if (isa<FieldDecl>(DRE->getDecl()) || + isa<IndirectFieldDecl>(DRE->getDecl()) || + isa<CXXMethodDecl>(DRE->getDecl())) { assert((isa<FieldDecl>(DRE->getDecl()) || + isa<IndirectFieldDecl>(DRE->getDecl()) || !cast<CXXMethodDecl>(DRE->getDecl())->isStatic()) && "Only non-static member pointers can make it here"); @@ -4520,7 +5074,8 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl()); if (VD->getDeclContext()->isRecord() && - (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD))) { + (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD) || + isa<IndirectFieldDecl>(VD))) { // If the value is a class member, we might have a pointer-to-member. // Determine whether the non-type template template parameter is of // pointer-to-member type. If so, we need to build an appropriate @@ -4898,7 +5453,7 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { // C++ [temp]p2: // A template-declaration can appear only as a namespace scope or // class scope declaration. - DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity()); + DeclContext *Ctx = S->getEntity(); if (Ctx && isa<LinkageSpecDecl>(Ctx) && cast<LinkageSpecDecl>(Ctx)->getLanguage() != LinkageSpecDecl::lang_cxx) return Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage) @@ -4907,8 +5462,20 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { while (Ctx && isa<LinkageSpecDecl>(Ctx)) Ctx = Ctx->getParent(); - if (Ctx && (Ctx->isFileContext() || Ctx->isRecord())) - return false; + if (Ctx) { + if (Ctx->isFileContext()) + return false; + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Ctx)) { + // C++ [temp.mem]p2: + // A local class shall not have member templates. + if (RD->isLocalClass()) + return Diag(TemplateParams->getTemplateLoc(), + diag::err_template_inside_local_class) + << TemplateParams->getSourceRange(); + else + return false; + } + } return Diag(TemplateParams->getTemplateLoc(), diag::err_template_outside_namespace_or_class_scope) @@ -4965,16 +5532,18 @@ static bool CheckTemplateSpecializationScope(Sema &S, int EntityKind = 0; if (isa<ClassTemplateDecl>(Specialized)) EntityKind = IsPartialSpecialization? 1 : 0; + else if (isa<VarTemplateDecl>(Specialized)) + EntityKind = IsPartialSpecialization ? 3 : 2; else if (isa<FunctionTemplateDecl>(Specialized)) - EntityKind = 2; + EntityKind = 4; else if (isa<CXXMethodDecl>(Specialized)) - EntityKind = 3; + EntityKind = 5; else if (isa<VarDecl>(Specialized)) - EntityKind = 4; + EntityKind = 6; else if (isa<RecordDecl>(Specialized)) - EntityKind = 5; + EntityKind = 7; else if (isa<EnumDecl>(Specialized) && S.getLangOpts().CPlusPlus11) - EntityKind = 6; + EntityKind = 8; else { S.Diag(Loc, diag::err_template_spec_unknown_kind) << S.getLangOpts().CPlusPlus11; @@ -5098,17 +5667,15 @@ static bool CheckTemplateSpecializationScope(Sema &S, return false; } -/// \brief Subroutine of Sema::CheckClassTemplatePartialSpecializationArgs +/// \brief Subroutine of Sema::CheckTemplatePartialSpecializationArgs /// that checks non-type template partial specialization arguments. -static bool CheckNonTypeClassTemplatePartialSpecializationArgs(Sema &S, - NonTypeTemplateParmDecl *Param, - const TemplateArgument *Args, - unsigned NumArgs) { +static bool CheckNonTypeTemplatePartialSpecializationArgs( + Sema &S, NonTypeTemplateParmDecl *Param, const TemplateArgument *Args, + unsigned NumArgs) { for (unsigned I = 0; I != NumArgs; ++I) { if (Args[I].getKind() == TemplateArgument::Pack) { - if (CheckNonTypeClassTemplatePartialSpecializationArgs(S, Param, - Args[I].pack_begin(), - Args[I].pack_size())) + if (CheckNonTypeTemplatePartialSpecializationArgs( + S, Param, Args[I].pack_begin(), Args[I].pack_size())) return true; continue; @@ -5179,9 +5746,9 @@ static bool CheckNonTypeClassTemplatePartialSpecializationArgs(Sema &S, /// partial specialization. /// /// \returns true if there was an error, false otherwise. -static bool CheckClassTemplatePartialSpecializationArgs(Sema &S, - TemplateParameterList *TemplateParams, - SmallVectorImpl<TemplateArgument> &TemplateArgs) { +static bool CheckTemplatePartialSpecializationArgs( + Sema &S, TemplateParameterList *TemplateParams, + SmallVectorImpl<TemplateArgument> &TemplateArgs) { const TemplateArgument *ArgList = TemplateArgs.data(); for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { @@ -5190,8 +5757,7 @@ static bool CheckClassTemplatePartialSpecializationArgs(Sema &S, if (!Param) continue; - if (CheckNonTypeClassTemplatePartialSpecializationArgs(S, Param, - &ArgList[I], 1)) + if (CheckNonTypeTemplatePartialSpecializationArgs(S, Param, &ArgList[I], 1)) return true; } @@ -5219,7 +5785,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, ? TemplateParameterLists[0]->getTemplateLoc() : SourceLocation(); // Find the class template we're specializing - TemplateName Name = TemplateD.getAsVal<TemplateName>(); + TemplateName Name = TemplateD.get(); ClassTemplateDecl *ClassTemplate = dyn_cast_or_null<ClassTemplateDecl>(Name.getAsTemplateDecl()); @@ -5238,15 +5804,10 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // FIXME: We probably shouldn't complain about these headers for // friend declarations. bool Invalid = false; - TemplateParameterList *TemplateParams - = MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, - TemplateNameLoc, - SS, - TemplateParameterLists.data(), - TemplateParameterLists.size(), - TUK == TUK_Friend, - isExplicitSpecialization, - Invalid); + TemplateParameterList *TemplateParams = + MatchTemplateParametersToScopeSpecifier( + TemplateNameLoc, TemplateNameLoc, SS, TemplateParameterLists, + TUK == TUK_Friend, isExplicitSpecialization, Invalid); if (Invalid) return true; @@ -5300,6 +5861,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, } else if (TUK != TUK_Friend) { Diag(KWLoc, diag::err_template_spec_needs_header) << FixItHint::CreateInsertion(KWLoc, "template<> "); + TemplateKWLoc = KWLoc; isExplicitSpecialization = true; } @@ -5341,9 +5903,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // Find the class template (partial) specialization declaration that // corresponds to these arguments. if (isPartialSpecialization) { - if (CheckClassTemplatePartialSpecializationArgs(*this, - ClassTemplate->getTemplateParameters(), - Converted)) + if (CheckTemplatePartialSpecializationArgs( + *this, ClassTemplate->getTemplateParameters(), Converted)) return true; bool InstantiationDependent; @@ -5416,7 +5977,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // -- The argument list of the specialization shall not be identical // to the implicit argument list of the primary template. Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template) - << (TUK == TUK_Definition) + << /*class template*/0 << (TUK == TUK_Definition) << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc)); return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS, ClassTemplate->getIdentifier(), @@ -5431,8 +5992,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // Create a new class template partial specialization declaration node. ClassTemplatePartialSpecializationDecl *PrevPartial = cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl); - unsigned SequenceNumber = PrevPartial? PrevPartial->getSequenceNumber() - : ClassTemplate->getNextPartialSpecSequenceNumber(); ClassTemplatePartialSpecializationDecl *Partial = ClassTemplatePartialSpecializationDecl::Create(Context, Kind, ClassTemplate->getDeclContext(), @@ -5443,8 +6002,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, Converted.size(), TemplateArgs, CanonType, - PrevPartial, - SequenceNumber); + PrevPartial); SetNestedNameSpecifier(Partial, SS); if (TemplateParameterLists.size() > 1 && SS.isSet()) { Partial->setTemplateParameterListsInfo(Context, @@ -5473,7 +6031,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, if (!DeducibleParams.all()) { unsigned NumNonDeducible = DeducibleParams.size()-DeducibleParams.count(); Diag(TemplateNameLoc, diag::warn_partial_specs_not_deducible) - << (NumNonDeducible > 1) + << /*class template*/0 << (NumNonDeducible > 1) << SourceRange(TemplateNameLoc, RAngleLoc); for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) { if (!DeducibleParams[I]) { @@ -5710,7 +6268,10 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, switch (NewTSK) { case TSK_Undeclared: case TSK_ImplicitInstantiation: - llvm_unreachable("Don't check implicit instantiations here"); + assert( + (PrevTSK == TSK_Undeclared || PrevTSK == TSK_ImplicitInstantiation) && + "previous declaration must be implicit!"); + return false; case TSK_ExplicitSpecialization: switch (PrevTSK) { @@ -5916,13 +6477,13 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD, /// /// \param Previous the set of declarations that may be specialized by /// this function specialization. -bool -Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, - TemplateArgumentListInfo *ExplicitTemplateArgs, - LookupResult &Previous) { +bool Sema::CheckFunctionTemplateSpecialization( + FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs, + LookupResult &Previous) { // The set of function template specializations that could match this // explicit function template specialization. UnresolvedSet<8> Candidates; + TemplateSpecCandidateSet FailedCandidates(FD->getLocation()); DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext(); for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); @@ -5948,9 +6509,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.TypeQuals |= Qualifiers::Const; - FT = Context.getFunctionType(FPT->getResultType(), - ArrayRef<QualType>(FPT->arg_type_begin(), - FPT->getNumArgs()), + FT = Context.getFunctionType(FPT->getResultType(), FPT->getArgTypes(), EPI); } } @@ -5962,13 +6521,16 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, // Perform template argument deduction to determine whether we may be // specializing this template. // FIXME: It is somewhat wasteful to build - TemplateDeductionInfo Info(FD->getLocation()); + TemplateDeductionInfo Info(FailedCandidates.getLocation()); FunctionDecl *Specialization = 0; - if (TemplateDeductionResult TDK - = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs, FT, - Specialization, Info)) { - // FIXME: Template argument deduction failed; record why it failed, so + if (TemplateDeductionResult TDK = DeduceTemplateArguments( + cast<FunctionTemplateDecl>(FunTmpl->getFirstDecl()), + ExplicitTemplateArgs, FT, Specialization, Info)) { + // Template argument deduction failed; record why it failed, so // that we can provide nifty diagnostics. + FailedCandidates.addCandidate() + .set(FunTmpl->getTemplatedDecl(), + MakeDeductionFailureInfo(Context, TDK, Info)); (void)TDK; continue; } @@ -5979,14 +6541,14 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, } // Find the most specialized function template. - UnresolvedSetIterator Result - = getMostSpecialized(Candidates.begin(), Candidates.end(), - TPOC_Other, 0, FD->getLocation(), - PDiag(diag::err_function_template_spec_no_match) - << FD->getDeclName(), - PDiag(diag::err_function_template_spec_ambiguous) - << FD->getDeclName() << (ExplicitTemplateArgs != 0), - PDiag(diag::note_function_template_spec_matched)); + UnresolvedSetIterator Result = getMostSpecialized( + Candidates.begin(), Candidates.end(), FailedCandidates, + FD->getLocation(), + PDiag(diag::err_function_template_spec_no_match) << FD->getDeclName(), + PDiag(diag::err_function_template_spec_ambiguous) + << FD->getDeclName() << (ExplicitTemplateArgs != 0), + PDiag(diag::note_function_template_spec_matched)); + if (Result == Candidates.end()) return true; @@ -6213,9 +6775,8 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { InstantiationVar->setLocation(Member->getLocation()); } - Context.setInstantiatedFromStaticDataMember(cast<VarDecl>(Member), - cast<VarDecl>(InstantiatedFrom), - TSK_ExplicitSpecialization); + cast<VarDecl>(Member)->setInstantiationOfStaticDataMember( + cast<VarDecl>(InstantiatedFrom), TSK_ExplicitSpecialization); MarkUnusedFileScopedDecl(InstantiationVar); } else if (isa<CXXRecordDecl>(Member)) { CXXRecordDecl *InstantiationClass = cast<CXXRecordDecl>(Instantiation); @@ -6340,15 +6901,23 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation RAngleLoc, AttributeList *Attr) { // Find the class template we're specializing - TemplateName Name = TemplateD.getAsVal<TemplateName>(); - ClassTemplateDecl *ClassTemplate - = cast<ClassTemplateDecl>(Name.getAsTemplateDecl()); - + TemplateName Name = TemplateD.get(); + TemplateDecl *TD = Name.getAsTemplateDecl(); // Check that the specialization uses the same tag kind as the // original template. TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); assert(Kind != TTK_Enum && "Invalid enum tag in class template explicit instantiation!"); + + if (isa<TypeAliasTemplateDecl>(TD)) { + Diag(KWLoc, diag::err_tag_reference_non_tag) << Kind; + Diag(TD->getTemplatedDecl()->getLocation(), + diag::note_previous_use); + return true; + } + + ClassTemplateDecl *ClassTemplate = cast<ClassTemplateDecl>(TD); + if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(), Kind, /*isDefinition*/false, KWLoc, *ClassTemplate->getIdentifier())) { @@ -6695,7 +7264,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, diag::err_explicit_instantiation_inline : diag::warn_explicit_instantiation_inline_0x) << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc()); - if (D.getDeclSpec().isConstexprSpecified()) + if (D.getDeclSpec().isConstexprSpecified() && R->isFunctionType()) // FIXME: Add a fix-it to remove the 'constexpr' and add a 'const' if one is // not already specified. Diag(D.getDeclSpec().getConstexprSpecLoc(), @@ -6717,28 +7286,78 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // A [...] static data member of a class template can be explicitly // instantiated from the member definition associated with its class // template. + // C++1y [temp.explicit]p1: + // A [...] variable [...] template specialization can be explicitly + // instantiated from its template. if (Previous.isAmbiguous()) return true; VarDecl *Prev = Previous.getAsSingle<VarDecl>(); - if (!Prev || !Prev->isStaticDataMember()) { - // We expect to see a data data member here. - Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_not_known) - << Name; - for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); - P != PEnd; ++P) - Diag((*P)->getLocation(), diag::note_explicit_instantiation_here); - return true; - } + VarTemplateDecl *PrevTemplate = Previous.getAsSingle<VarTemplateDecl>(); + + if (!PrevTemplate) { + if (!Prev || !Prev->isStaticDataMember()) { + // We expect to see a data data member here. + Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_not_known) + << Name; + for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); + P != PEnd; ++P) + Diag((*P)->getLocation(), diag::note_explicit_instantiation_here); + return true; + } - if (!Prev->getInstantiatedFromStaticDataMember()) { - // FIXME: Check for explicit specialization? - Diag(D.getIdentifierLoc(), - diag::err_explicit_instantiation_data_member_not_instantiated) - << Prev; - Diag(Prev->getLocation(), diag::note_explicit_instantiation_here); - // FIXME: Can we provide a note showing where this was declared? - return true; + if (!Prev->getInstantiatedFromStaticDataMember()) { + // FIXME: Check for explicit specialization? + Diag(D.getIdentifierLoc(), + diag::err_explicit_instantiation_data_member_not_instantiated) + << Prev; + Diag(Prev->getLocation(), diag::note_explicit_instantiation_here); + // FIXME: Can we provide a note showing where this was declared? + return true; + } + } else { + // Explicitly instantiate a variable template. + + // C++1y [dcl.spec.auto]p6: + // ... A program that uses auto or decltype(auto) in a context not + // explicitly allowed in this section is ill-formed. + // + // This includes auto-typed variable template instantiations. + if (R->isUndeducedType()) { + Diag(T->getTypeLoc().getLocStart(), + diag::err_auto_not_allowed_var_inst); + return true; + } + + if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) { + // C++1y [temp.explicit]p3: + // If the explicit instantiation is for a variable, the unqualified-id + // in the declaration shall be a template-id. + Diag(D.getIdentifierLoc(), + diag::err_explicit_instantiation_without_template_id) + << PrevTemplate; + Diag(PrevTemplate->getLocation(), + diag::note_explicit_instantiation_here); + return true; + } + + // Translate the parser's template argument list into our AST format. + TemplateArgumentListInfo TemplateArgs; + TemplateIdAnnotation *TemplateId = D.getName().TemplateId; + TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc); + TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc); + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + translateTemplateArguments(TemplateArgsPtr, TemplateArgs); + + DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc, + D.getIdentifierLoc(), TemplateArgs); + if (Res.isInvalid()) + return true; + + // Ignore access control bits, we don't need them for redeclaration + // checking. + Prev = cast<VarDecl>(Res.get()); } // C++0x [temp.explicit]p2: @@ -6748,7 +7367,10 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // name shall be a simple-template-id. // // C++98 has the same restriction, just worded differently. - if (!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec())) + // + // This does not apply to variable template specializations, where the + // template-id is in the unqualified-id instead. + if (!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()) && !PrevTemplate) Diag(D.getIdentifierLoc(), diag::ext_explicit_instantiation_without_qualified_id) << Prev << D.getCXXScopeSpec().getRange(); @@ -6757,21 +7379,35 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, CheckExplicitInstantiationScope(*this, Prev, D.getIdentifierLoc(), true); // Verify that it is okay to explicitly instantiate here. - MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo(); - assert(MSInfo && "Missing static data member specialization info?"); + TemplateSpecializationKind PrevTSK = Prev->getTemplateSpecializationKind(); + SourceLocation POI = Prev->getPointOfInstantiation(); bool HasNoEffect = false; if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev, - MSInfo->getTemplateSpecializationKind(), - MSInfo->getPointOfInstantiation(), - HasNoEffect)) + PrevTSK, POI, HasNoEffect)) return true; - if (HasNoEffect) - return (Decl*) 0; - // Instantiate static data member. - Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); - if (TSK == TSK_ExplicitInstantiationDefinition) - InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev); + if (!HasNoEffect) { + // Instantiate static data member or variable template. + + Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); + if (PrevTemplate) { + // Merge attributes. + if (AttributeList *Attr = D.getDeclSpec().getAttributes().getList()) + ProcessDeclAttributeList(S, Prev, Attr); + } + if (TSK == TSK_ExplicitInstantiationDefinition) + InstantiateVariableDefinition(D.getIdentifierLoc(), Prev); + } + + // Check the new variable specialization against the parsed input. + if (PrevTemplate && Prev && !Context.hasSameType(Prev->getType(), R)) { + Diag(T->getTypeLoc().getLocStart(), + diag::err_invalid_var_template_spec_type) + << 0 << PrevTemplate << R << Prev->getType(); + Diag(PrevTemplate->getLocation(), diag::note_template_declared_here) + << 2 << PrevTemplate->getDeclName(); + return true; + } // FIXME: Create an ExplicitInstantiation node? return (Decl*) 0; @@ -6797,12 +7433,14 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // instantiated from the member definition associated with its class // template. UnresolvedSet<8> Matches; + TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc()); for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); P != PEnd; ++P) { NamedDecl *Prev = *P; if (!HasExplicitTemplateArgs) { if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) { - if (Context.hasSameUnqualifiedType(Method->getType(), R)) { + QualType Adjusted = adjustCCAndNoReturn(R, Method->getType()); + if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) { Matches.clear(); Matches.addDecl(Method, P.getAccess()); @@ -6816,13 +7454,16 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (!FunTmpl) continue; - TemplateDeductionInfo Info(D.getIdentifierLoc()); + TemplateDeductionInfo Info(FailedCandidates.getLocation()); FunctionDecl *Specialization = 0; if (TemplateDeductionResult TDK = DeduceTemplateArguments(FunTmpl, (HasExplicitTemplateArgs ? &TemplateArgs : 0), R, Specialization, Info)) { - // FIXME: Keep track of almost-matches? + // Keep track of almost-matches. + FailedCandidates.addCandidate() + .set(FunTmpl->getTemplatedDecl(), + MakeDeductionFailureInfo(Context, TDK, Info)); (void)TDK; continue; } @@ -6831,12 +7472,12 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, } // Find the most specialized function template specialization. - UnresolvedSetIterator Result - = getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other, 0, - D.getIdentifierLoc(), - PDiag(diag::err_explicit_instantiation_not_known) << Name, - PDiag(diag::err_explicit_instantiation_ambiguous) << Name, - PDiag(diag::note_explicit_instantiation_candidate)); + UnresolvedSetIterator Result = getMostSpecialized( + Matches.begin(), Matches.end(), FailedCandidates, + D.getIdentifierLoc(), + PDiag(diag::err_explicit_instantiation_not_known) << Name, + PDiag(diag::err_explicit_instantiation_ambiguous) << Name, + PDiag(diag::note_explicit_instantiation_candidate)); if (Result == Matches.end()) return true; @@ -7373,11 +8014,26 @@ Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params, return Out.str(); } -void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, bool Flag) { +void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD, + CachedTokens &Toks) { if (!FD) return; - FD->setLateTemplateParsed(Flag); -} + + LateParsedTemplate *LPT = new LateParsedTemplate; + + // Take tokens to avoid allocations + LPT->Toks.swap(Toks); + LPT->D = FnD; + LateParsedTemplateMap[FD] = LPT; + + FD->setLateTemplateParsed(true); +} + +void Sema::UnmarkAsLateParsedTemplate(FunctionDecl *FD) { + if (!FD) + return; + FD->setLateTemplateParsed(false); +} bool Sema::IsInsideALocalClassWithinATemplateFunction() { DeclContext *DC = CurContext; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp index 8efc7a026347..8d66ff68efa6 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -13,6 +13,7 @@ #include "clang/Sema/TemplateDeduction.h" #include "TreeTransform.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" @@ -26,7 +27,6 @@ namespace clang { using namespace sema; - /// \brief Various flags that control template argument deduction. /// /// These flags can be bitwise-OR'd together. @@ -89,7 +89,7 @@ DeduceTemplateArguments(Sema &S, const TemplateArgument &Param, TemplateArgument Arg, TemplateDeductionInfo &Info, - SmallVectorImpl<DeducedTemplateArgument> &Deduced); + SmallVectorImpl<DeducedTemplateArgument> &Deduced); /// \brief Whether template argument deduction for two reference parameters /// resulted in the argument type, parameter type, or neither type being more @@ -375,10 +375,10 @@ DeduceNonTypeTemplateArgument(Sema &S, /// \returns true if deduction succeeded, false otherwise. static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(Sema &S, - NonTypeTemplateParmDecl *NTTP, - ValueDecl *D, - TemplateDeductionInfo &Info, - SmallVectorImpl<DeducedTemplateArgument> &Deduced) { + NonTypeTemplateParmDecl *NTTP, + ValueDecl *D, + TemplateDeductionInfo &Info, + SmallVectorImpl<DeducedTemplateArgument> &Deduced) { assert(NTTP->getDepth() == 0 && "Cannot deduce non-type template argument with depth > 0"); @@ -405,7 +405,7 @@ DeduceTemplateArguments(Sema &S, TemplateName Param, TemplateName Arg, TemplateDeductionInfo &Info, - SmallVectorImpl<DeducedTemplateArgument> &Deduced) { + SmallVectorImpl<DeducedTemplateArgument> &Deduced) { TemplateDecl *ParamDecl = Param.getAsTemplateDecl(); if (!ParamDecl) { // The parameter type is dependent and is not a template template parameter, @@ -464,7 +464,7 @@ DeduceTemplateArguments(Sema &S, const TemplateSpecializationType *Param, QualType Arg, TemplateDeductionInfo &Info, - SmallVectorImpl<DeducedTemplateArgument> &Deduced) { + SmallVectorImpl<DeducedTemplateArgument> &Deduced) { assert(Arg.isCanonical() && "Argument type must be canonical"); // Check whether the template argument is a dependent template-id. @@ -575,20 +575,23 @@ getDepthAndIndex(UnexpandedParameterPack UPP) { static TemplateParameter makeTemplateParameter(Decl *D) { if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(D)) return TemplateParameter(TTP); - else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) + if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) return TemplateParameter(NTTP); return TemplateParameter(cast<TemplateTemplateParmDecl>(D)); } +typedef SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2> + NewlyDeducedPacksType; + /// \brief Prepare to perform template argument deduction for all of the /// arguments in a set of argument packs. -static void PrepareArgumentPackDeduction(Sema &S, - SmallVectorImpl<DeducedTemplateArgument> &Deduced, - ArrayRef<unsigned> PackIndices, - SmallVectorImpl<DeducedTemplateArgument> &SavedPacks, - SmallVectorImpl< - SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks) { +static void +PrepareArgumentPackDeduction(Sema &S, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + ArrayRef<unsigned> PackIndices, + SmallVectorImpl<DeducedTemplateArgument> &SavedPacks, + NewlyDeducedPacksType &NewlyDeducedPacks) { // Save the deduced template arguments for each parameter pack expanded // by this pack expansion, then clear out the deduction. for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) { @@ -620,14 +623,13 @@ static void PrepareArgumentPackDeduction(Sema &S, /// deductions. static Sema::TemplateDeductionResult FinishArgumentPackDeduction(Sema &S, - TemplateParameterList *TemplateParams, - bool HasAnyArguments, - SmallVectorImpl<DeducedTemplateArgument> &Deduced, - ArrayRef<unsigned> PackIndices, - SmallVectorImpl<DeducedTemplateArgument> &SavedPacks, - SmallVectorImpl< - SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks, - TemplateDeductionInfo &Info) { + TemplateParameterList *TemplateParams, + bool HasAnyArguments, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + ArrayRef<unsigned> PackIndices, + SmallVectorImpl<DeducedTemplateArgument> &SavedPacks, + NewlyDeducedPacksType &NewlyDeducedPacks, + TemplateDeductionInfo &Info) { // Build argument packs for each of the parameter packs expanded by this // pack expansion. for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) { @@ -709,7 +711,7 @@ DeduceTemplateArguments(Sema &S, const QualType *Params, unsigned NumParams, const QualType *Args, unsigned NumArgs, TemplateDeductionInfo &Info, - SmallVectorImpl<DeducedTemplateArgument> &Deduced, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, unsigned TDF, bool PartialOrdering = false, SmallVectorImpl<RefParamPartialOrderingComparison> * @@ -793,8 +795,7 @@ DeduceTemplateArguments(Sema &S, // Keep track of the deduced template arguments for each parameter pack // expanded by this pack expansion (the outer index) and for each // template argument (the inner SmallVectors). - SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2> - NewlyDeducedPacks(PackIndices.size()); + NewlyDeducedPacksType NewlyDeducedPacks(PackIndices.size()); SmallVector<DeducedTemplateArgument, 2> SavedPacks(PackIndices.size()); PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks, @@ -1430,8 +1431,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, Deduced.end()); while (!ToVisit.empty()) { // Retrieve the next class in the inheritance hierarchy. - const RecordType *NextT = ToVisit.back(); - ToVisit.pop_back(); + const RecordType *NextT = ToVisit.pop_back_val(); // If we have already seen this type, skip it. if (!Visited.insert(NextT)) @@ -1635,7 +1635,7 @@ DeduceTemplateArguments(Sema &S, const TemplateArgument &Param, TemplateArgument Arg, TemplateDeductionInfo &Info, - SmallVectorImpl<DeducedTemplateArgument> &Deduced) { + SmallVectorImpl<DeducedTemplateArgument> &Deduced) { // If the template argument is a pack expansion, perform template argument // deduction against the pattern of that expansion. This only occurs during // partial ordering. @@ -1871,8 +1871,7 @@ DeduceTemplateArguments(Sema &S, // by this pack expansion, then clear out the deduction. SmallVector<DeducedTemplateArgument, 2> SavedPacks(PackIndices.size()); - SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2> - NewlyDeducedPacks(PackIndices.size()); + NewlyDeducedPacksType NewlyDeducedPacks(PackIndices.size()); PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks, NewlyDeducedPacks); @@ -1921,7 +1920,7 @@ DeduceTemplateArguments(Sema &S, const TemplateArgumentList &ParamList, const TemplateArgumentList &ArgList, TemplateDeductionInfo &Info, - SmallVectorImpl<DeducedTemplateArgument> &Deduced) { + SmallVectorImpl<DeducedTemplateArgument> &Deduced) { return DeduceTemplateArguments(S, TemplateParams, ParamList.data(), ParamList.size(), ArgList.data(), ArgList.size(), @@ -2064,14 +2063,15 @@ getTrivialTemplateArgumentLoc(Sema &S, /// \brief Convert the given deduced template argument and add it to the set of /// fully-converted template arguments. -static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param, - DeducedTemplateArgument Arg, - NamedDecl *Template, - QualType NTTPType, - unsigned ArgumentPackIndex, - TemplateDeductionInfo &Info, - bool InFunctionTemplate, - SmallVectorImpl<TemplateArgument> &Output) { +static bool +ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param, + DeducedTemplateArgument Arg, + NamedDecl *Template, + QualType NTTPType, + unsigned ArgumentPackIndex, + TemplateDeductionInfo &Info, + bool InFunctionTemplate, + SmallVectorImpl<TemplateArgument> &Output) { if (Arg.getKind() == TemplateArgument::Pack) { // This is a template argument pack, so check each of its arguments against // the template parameter. @@ -2090,8 +2090,7 @@ static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param, return true; // Move the converted template argument into our argument pack. - PackedArgsBuilder.push_back(Output.back()); - Output.pop_back(); + PackedArgsBuilder.push_back(Output.pop_back_val()); } // Create the resulting argument pack. @@ -2200,14 +2199,15 @@ FinishTemplateArgumentDeduction(Sema &S, // to the class template. LocalInstantiationScope InstScope(S); ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate(); - const TemplateArgumentLoc *PartialTemplateArgs + const ASTTemplateArgumentListInfo *PartialTemplArgInfo = Partial->getTemplateArgsAsWritten(); + const TemplateArgumentLoc *PartialTemplateArgs + = PartialTemplArgInfo->getTemplateArgs(); - // Note that we don't provide the langle and rangle locations. - TemplateArgumentListInfo InstArgs; + TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc, + PartialTemplArgInfo->RAngleLoc); - if (S.Subst(PartialTemplateArgs, - Partial->getNumTemplateArgsAsWritten(), + if (S.Subst(PartialTemplateArgs, PartialTemplArgInfo->NumTemplateArgs, InstArgs, MultiLevelTemplateArgumentList(*DeducedArgumentList))) { unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx; if (ParamIdx >= Partial->getTemplateParameters()->size()) @@ -2276,7 +2276,171 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end()); InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial, DeducedArgs, Info); - if (Inst) + if (Inst.isInvalid()) + return TDK_InstantiationDepth; + + if (Trap.hasErrorOccurred()) + return Sema::TDK_SubstitutionFailure; + + return ::FinishTemplateArgumentDeduction(*this, Partial, TemplateArgs, + Deduced, Info); +} + +/// Complete template argument deduction for a variable template partial +/// specialization. +/// TODO: Unify with ClassTemplatePartialSpecializationDecl version? +/// May require unifying ClassTemplate(Partial)SpecializationDecl and +/// VarTemplate(Partial)SpecializationDecl with a new data +/// structure Template(Partial)SpecializationDecl, and +/// using Template(Partial)SpecializationDecl as input type. +static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction( + Sema &S, VarTemplatePartialSpecializationDecl *Partial, + const TemplateArgumentList &TemplateArgs, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + TemplateDeductionInfo &Info) { + // Unevaluated SFINAE context. + EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated); + Sema::SFINAETrap Trap(S); + + // C++ [temp.deduct.type]p2: + // [...] or if any template argument remains neither deduced nor + // explicitly specified, template argument deduction fails. + SmallVector<TemplateArgument, 4> Builder; + TemplateParameterList *PartialParams = Partial->getTemplateParameters(); + for (unsigned I = 0, N = PartialParams->size(); I != N; ++I) { + NamedDecl *Param = PartialParams->getParam(I); + if (Deduced[I].isNull()) { + Info.Param = makeTemplateParameter(Param); + return Sema::TDK_Incomplete; + } + + // We have deduced this argument, so it still needs to be + // checked and converted. + + // First, for a non-type template parameter type that is + // initialized by a declaration, we need the type of the + // corresponding non-type template parameter. + QualType NTTPType; + if (NonTypeTemplateParmDecl *NTTP = + dyn_cast<NonTypeTemplateParmDecl>(Param)) { + NTTPType = NTTP->getType(); + if (NTTPType->isDependentType()) { + TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, + Builder.data(), Builder.size()); + NTTPType = + S.SubstType(NTTPType, MultiLevelTemplateArgumentList(TemplateArgs), + NTTP->getLocation(), NTTP->getDeclName()); + if (NTTPType.isNull()) { + Info.Param = makeTemplateParameter(Param); + // FIXME: These template arguments are temporary. Free them! + Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(), + Builder.size())); + return Sema::TDK_SubstitutionFailure; + } + } + } + + if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Partial, NTTPType, + 0, Info, false, Builder)) { + Info.Param = makeTemplateParameter(Param); + // FIXME: These template arguments are temporary. Free them! + Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(), + Builder.size())); + return Sema::TDK_SubstitutionFailure; + } + } + + // Form the template argument list from the deduced template arguments. + TemplateArgumentList *DeducedArgumentList = TemplateArgumentList::CreateCopy( + S.Context, Builder.data(), Builder.size()); + + Info.reset(DeducedArgumentList); + + // Substitute the deduced template arguments into the template + // arguments of the class template partial specialization, and + // verify that the instantiated template arguments are both valid + // and are equivalent to the template arguments originally provided + // to the class template. + LocalInstantiationScope InstScope(S); + VarTemplateDecl *VarTemplate = Partial->getSpecializedTemplate(); + const ASTTemplateArgumentListInfo *PartialTemplArgInfo + = Partial->getTemplateArgsAsWritten(); + const TemplateArgumentLoc *PartialTemplateArgs + = PartialTemplArgInfo->getTemplateArgs(); + + TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc, + PartialTemplArgInfo->RAngleLoc); + + if (S.Subst(PartialTemplateArgs, PartialTemplArgInfo->NumTemplateArgs, + InstArgs, MultiLevelTemplateArgumentList(*DeducedArgumentList))) { + unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx; + if (ParamIdx >= Partial->getTemplateParameters()->size()) + ParamIdx = Partial->getTemplateParameters()->size() - 1; + + Decl *Param = const_cast<NamedDecl *>( + Partial->getTemplateParameters()->getParam(ParamIdx)); + Info.Param = makeTemplateParameter(Param); + Info.FirstArg = PartialTemplateArgs[ArgIdx].getArgument(); + return Sema::TDK_SubstitutionFailure; + } + SmallVector<TemplateArgument, 4> ConvertedInstArgs; + if (S.CheckTemplateArgumentList(VarTemplate, Partial->getLocation(), InstArgs, + false, ConvertedInstArgs)) + return Sema::TDK_SubstitutionFailure; + + TemplateParameterList *TemplateParams = VarTemplate->getTemplateParameters(); + for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) { + TemplateArgument InstArg = ConvertedInstArgs.data()[I]; + if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg)) { + Info.Param = makeTemplateParameter(TemplateParams->getParam(I)); + Info.FirstArg = TemplateArgs[I]; + Info.SecondArg = InstArg; + return Sema::TDK_NonDeducedMismatch; + } + } + + if (Trap.hasErrorOccurred()) + return Sema::TDK_SubstitutionFailure; + + return Sema::TDK_Success; +} + +/// \brief Perform template argument deduction to determine whether +/// the given template arguments match the given variable template +/// partial specialization per C++ [temp.class.spec.match]. +/// TODO: Unify with ClassTemplatePartialSpecializationDecl version? +/// May require unifying ClassTemplate(Partial)SpecializationDecl and +/// VarTemplate(Partial)SpecializationDecl with a new data +/// structure Template(Partial)SpecializationDecl, and +/// using Template(Partial)SpecializationDecl as input type. +Sema::TemplateDeductionResult +Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial, + const TemplateArgumentList &TemplateArgs, + TemplateDeductionInfo &Info) { + if (Partial->isInvalidDecl()) + return TDK_Invalid; + + // C++ [temp.class.spec.match]p2: + // A partial specialization matches a given actual template + // 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 = ::DeduceTemplateArguments( + *this, Partial->getTemplateParameters(), Partial->getTemplateArgs(), + TemplateArgs, Info, Deduced)) + return Result; + + SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end()); + InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial, + DeducedArgs, Info); + if (Inst.isInvalid()) return TDK_InstantiationDepth; if (Trap.hasErrorOccurred()) @@ -2364,7 +2528,7 @@ Sema::SubstituteExplicitTemplateArguments( FunctionTemplate, DeducedArgs, ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution, Info); - if (Inst) + if (Inst.isInvalid()) return TDK_InstantiationDepth; if (CheckTemplateArgumentList(FunctionTemplate, @@ -2423,7 +2587,6 @@ Sema::SubstituteExplicitTemplateArguments( } // Instantiate the return type. - // FIXME: exception-specifications? QualType ResultType; { // C++11 [expr.prim.general]p3: @@ -2524,13 +2687,16 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg, Qualifiers AQuals = A.getQualifiers(); Qualifiers DeducedAQuals = DeducedA.getQualifiers(); - // Under Objective-C++ ARC, the deduced type may have implicitly been - // given strong lifetime. If so, update the original qualifiers to - // include this strong lifetime. + // Under Objective-C++ ARC, the deduced type may have implicitly + // been given strong or (when dealing with a const reference) + // unsafe_unretained lifetime. If so, update the original + // qualifiers to include this lifetime. if (S.getLangOpts().ObjCAutoRefCount && - DeducedAQuals.getObjCLifetime() == Qualifiers::OCL_Strong && - AQuals.getObjCLifetime() == Qualifiers::OCL_None) { - AQuals.setObjCLifetime(Qualifiers::OCL_Strong); + ((DeducedAQuals.getObjCLifetime() == Qualifiers::OCL_Strong && + AQuals.getObjCLifetime() == Qualifiers::OCL_None) || + (DeducedAQuals.hasConst() && + DeducedAQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone))) { + AQuals.setObjCLifetime(DeducedAQuals.getObjCLifetime()); } if (AQuals == DeducedAQuals) { @@ -2551,7 +2717,7 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg, // // Also allow conversions which merely strip [[noreturn]] from function types // (recursively) as an extension. - // FIXME: Currently, this doesn't place nicely with qualfication conversions. + // FIXME: Currently, this doesn't play nicely with qualification conversions. bool ObjCLifetimeConversion = false; QualType ResultTy; if ((A->isAnyPointerType() || A->isMemberPointerType()) && @@ -2616,7 +2782,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, FunctionTemplate, DeducedArgs, ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution, Info); - if (Inst) + if (Inst.isInvalid()) return TDK_InstantiationDepth; ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl()); @@ -2704,18 +2870,21 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, } // Substitute into the default template argument, if available. + bool HasDefaultArg = false; TemplateArgumentLoc DefArg = SubstDefaultTemplateArgumentIfAvailable(FunctionTemplate, FunctionTemplate->getLocation(), FunctionTemplate->getSourceRange().getEnd(), Param, - Builder); + Builder, HasDefaultArg); // If there was no default argument, deduction is incomplete. if (DefArg.getArgument().isNull()) { Info.Param = makeTemplateParameter( const_cast<NamedDecl *>(TemplateParams->getParam(I))); - return TDK_Incomplete; + Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(), + Builder.size())); + return HasDefaultArg ? TDK_SubstitutionFailure : TDK_Incomplete; } // Check whether we can actually use the default argument. @@ -2792,7 +2961,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, // keep track of these diagnostics. They'll be emitted if this specialization // is actually used. if (Info.diag_begin() != Info.diag_end()) { - llvm::DenseMap<Decl *, SmallVector<PartialDiagnosticAt, 1> >::iterator + SuppressedDiagnosticsMap::iterator Pos = SuppressedDiagnostics.find(Specialization->getCanonicalDecl()); if (Pos == SuppressedDiagnostics.end()) SuppressedDiagnostics[Specialization->getCanonicalDecl()] @@ -3099,12 +3268,10 @@ DeduceTemplateArgumentByListElement(Sema &S, /// about template argument deduction. /// /// \returns the result of template argument deduction. -Sema::TemplateDeductionResult -Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - TemplateArgumentListInfo *ExplicitTemplateArgs, - llvm::ArrayRef<Expr *> Args, - FunctionDecl *&Specialization, - TemplateDeductionInfo &Info) { +Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( + FunctionTemplateDecl *FunctionTemplate, + TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, + FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { if (FunctionTemplate->isInvalidDecl()) return TDK_Invalid; @@ -3251,8 +3418,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // Keep track of the deduced template arguments for each parameter pack // expanded by this pack expansion (the outer index) and for each // template argument (the inner SmallVectors). - SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2> - NewlyDeducedPacks(PackIndices.size()); + NewlyDeducedPacksType NewlyDeducedPacks(PackIndices.size()); SmallVector<DeducedTemplateArgument, 2> SavedPacks(PackIndices.size()); PrepareArgumentPackDeduction(*this, Deduced, PackIndices, SavedPacks, @@ -3335,6 +3501,28 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, Specialization, Info, &OriginalCallArgs); } +QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType, + QualType FunctionType) { + if (ArgFunctionType.isNull()) + return ArgFunctionType; + + const FunctionProtoType *FunctionTypeP = + FunctionType->castAs<FunctionProtoType>(); + CallingConv CC = FunctionTypeP->getCallConv(); + bool NoReturn = FunctionTypeP->getNoReturnAttr(); + const FunctionProtoType *ArgFunctionTypeP = + ArgFunctionType->getAs<FunctionProtoType>(); + if (ArgFunctionTypeP->getCallConv() == CC && + ArgFunctionTypeP->getNoReturnAttr() == NoReturn) + return ArgFunctionType; + + FunctionType::ExtInfo EI = ArgFunctionTypeP->getExtInfo().withCallingConv(CC); + EI = EI.withNoReturn(NoReturn); + ArgFunctionTypeP = + cast<FunctionProtoType>(Context.adjustFunctionType(ArgFunctionTypeP, EI)); + return QualType(ArgFunctionTypeP, 0); +} + /// \brief Deduce template arguments when taking the address of a function /// template (C++ [temp.deduct.funcaddr]) or matching a specialization to /// a template. @@ -3372,6 +3560,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); QualType FunctionType = Function->getType(); + if (!InOverloadResolution) + ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType); // Substitute any explicit template arguments. LocalInstantiationScope InstScope(*this); @@ -3397,11 +3587,11 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // If the function has a deduced return type, substitute it for a dependent // type so that we treat it as a non-deduced context in what follows. - bool HasUndeducedReturnType = false; + bool HasDeducedReturnType = false; if (getLangOpts().CPlusPlus1y && InOverloadResolution && - Function->getResultType()->isUndeducedType()) { + Function->getResultType()->getContainedAutoType()) { FunctionType = SubstAutoType(FunctionType, Context.DependentTy); - HasUndeducedReturnType = true; + HasDeducedReturnType = true; } if (!ArgFunctionType.isNull()) { @@ -3423,7 +3613,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // If the function has a deduced return type, deduce it now, so we can check // that the deduced function type matches the requested type. - if (HasUndeducedReturnType && + if (HasDeducedReturnType && Specialization->getResultType()->isUndeducedType() && DeduceReturnType(Specialization, Info.getLocation(), false)) return TDK_MiscellaneousDeductionFailure; @@ -3444,20 +3634,130 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, return TDK_Success; } +/// \brief Given a function declaration (e.g. a generic lambda conversion +/// function) that contains an 'auto' in its result type, substitute it +/// with TypeToReplaceAutoWith. Be careful to pass in the type you want +/// to replace 'auto' with and not the actual result type you want +/// to set the function to. +static inline void +SubstAutoWithinFunctionReturnType(FunctionDecl *F, + QualType TypeToReplaceAutoWith, Sema &S) { + assert(!TypeToReplaceAutoWith->getContainedAutoType()); + QualType AutoResultType = F->getResultType(); + assert(AutoResultType->getContainedAutoType()); + QualType DeducedResultType = S.SubstAutoType(AutoResultType, + TypeToReplaceAutoWith); + S.Context.adjustDeducedFunctionResultType(F, DeducedResultType); +} + +/// \brief Given a specialized conversion operator of a generic lambda +/// create the corresponding specializations of the call operator and +/// the static-invoker. If the return type of the call operator is auto, +/// deduce its return type and check if that matches the +/// return type of the destination function ptr. + +static inline Sema::TemplateDeductionResult +SpecializeCorrespondingLambdaCallOperatorAndInvoker( + CXXConversionDecl *ConversionSpecialized, + SmallVectorImpl<DeducedTemplateArgument> &DeducedArguments, + QualType ReturnTypeOfDestFunctionPtr, + TemplateDeductionInfo &TDInfo, + Sema &S) { + + CXXRecordDecl *LambdaClass = ConversionSpecialized->getParent(); + assert(LambdaClass && LambdaClass->isGenericLambda()); + + CXXMethodDecl *CallOpGeneric = LambdaClass->getLambdaCallOperator(); + QualType CallOpResultType = CallOpGeneric->getResultType(); + const bool GenericLambdaCallOperatorHasDeducedReturnType = + CallOpResultType->getContainedAutoType(); + + FunctionTemplateDecl *CallOpTemplate = + CallOpGeneric->getDescribedFunctionTemplate(); + + FunctionDecl *CallOpSpecialized = 0; + // Use the deduced arguments of the conversion function, to specialize our + // generic lambda's call operator. + if (Sema::TemplateDeductionResult Result + = S.FinishTemplateArgumentDeduction(CallOpTemplate, + DeducedArguments, + 0, CallOpSpecialized, TDInfo)) + return Result; + + // If we need to deduce the return type, do so (instantiates the callop). + if (GenericLambdaCallOperatorHasDeducedReturnType && + CallOpSpecialized->getResultType()->isUndeducedType()) + S.DeduceReturnType(CallOpSpecialized, + CallOpSpecialized->getPointOfInstantiation(), + /*Diagnose*/ true); + + // Check to see if the return type of the destination ptr-to-function + // matches the return type of the call operator. + if (!S.Context.hasSameType(CallOpSpecialized->getResultType(), + ReturnTypeOfDestFunctionPtr)) + return Sema::TDK_NonDeducedMismatch; + // Since we have succeeded in matching the source and destination + // ptr-to-functions (now including return type), and have successfully + // specialized our corresponding call operator, we are ready to + // specialize the static invoker with the deduced arguments of our + // ptr-to-function. + FunctionDecl *InvokerSpecialized = 0; + FunctionTemplateDecl *InvokerTemplate = LambdaClass-> + getLambdaStaticInvoker()->getDescribedFunctionTemplate(); + + Sema::TemplateDeductionResult LLVM_ATTRIBUTE_UNUSED Result + = S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0, + InvokerSpecialized, TDInfo); + assert(Result == Sema::TDK_Success && + "If the call operator succeeded so should the invoker!"); + // Set the result type to match the corresponding call operator + // specialization's result type. + if (GenericLambdaCallOperatorHasDeducedReturnType && + InvokerSpecialized->getResultType()->isUndeducedType()) { + // Be sure to get the type to replace 'auto' with and not + // the full result type of the call op specialization + // to substitute into the 'auto' of the invoker and conversion + // function. + // For e.g. + // int* (*fp)(int*) = [](auto* a) -> auto* { return a; }; + // We don't want to subst 'int*' into 'auto' to get int**. + + QualType TypeToReplaceAutoWith = + CallOpSpecialized->getResultType()-> + getContainedAutoType()->getDeducedType(); + SubstAutoWithinFunctionReturnType(InvokerSpecialized, + TypeToReplaceAutoWith, S); + SubstAutoWithinFunctionReturnType(ConversionSpecialized, + TypeToReplaceAutoWith, S); + } + + // Ensure that static invoker doesn't have a const qualifier. + // FIXME: When creating the InvokerTemplate in SemaLambda.cpp + // do not use the CallOperator's TypeSourceInfo which allows + // the const qualifier to leak through. + const FunctionProtoType *InvokerFPT = InvokerSpecialized-> + getType().getTypePtr()->castAs<FunctionProtoType>(); + FunctionProtoType::ExtProtoInfo EPI = InvokerFPT->getExtProtoInfo(); + EPI.TypeQuals = 0; + InvokerSpecialized->setType(S.Context.getFunctionType( + InvokerFPT->getResultType(), InvokerFPT->getArgTypes(),EPI)); + return Sema::TDK_Success; +} /// \brief Deduce template arguments for a templated conversion /// function (C++ [temp.deduct.conv]) and, if successful, produce a /// conversion function template specialization. Sema::TemplateDeductionResult -Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, +Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate, QualType ToType, CXXConversionDecl *&Specialization, TemplateDeductionInfo &Info) { - if (FunctionTemplate->isInvalidDecl()) + if (ConversionTemplate->isInvalidDecl()) return TDK_Invalid; - CXXConversionDecl *Conv - = cast<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()); - QualType FromType = Conv->getConversionType(); + CXXConversionDecl *ConversionGeneric + = cast<CXXConversionDecl>(ConversionTemplate->getTemplatedDecl()); + + QualType FromType = ConversionGeneric->getConversionType(); // Canonicalize the types for deduction. QualType P = Context.getCanonicalType(FromType); @@ -3512,7 +3812,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // type that is required as the result of the conversion (call it // A) as described in 14.8.2.4. TemplateParameterList *TemplateParams - = FunctionTemplate->getTemplateParameters(); + = ConversionTemplate->getTemplateParameters(); SmallVector<DeducedTemplateArgument, 4> Deduced; Deduced.resize(TemplateParams->size()); @@ -3541,13 +3841,43 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, P, A, Info, Deduced, TDF)) return Result; - // Finish template argument deduction. + // Create an Instantiation Scope for finalizing the operator. LocalInstantiationScope InstScope(*this); - FunctionDecl *Spec = 0; + // Finish template argument deduction. + FunctionDecl *ConversionSpecialized = 0; TemplateDeductionResult Result - = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, 0, Spec, - Info); - Specialization = cast_or_null<CXXConversionDecl>(Spec); + = FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0, + ConversionSpecialized, Info); + Specialization = cast_or_null<CXXConversionDecl>(ConversionSpecialized); + + // If the conversion operator is being invoked on a lambda closure to convert + // to a ptr-to-function, use the deduced arguments from the conversion function + // to specialize the corresponding call operator. + // e.g., int (*fp)(int) = [](auto a) { return a; }; + if (Result == TDK_Success && isLambdaConversionOperator(ConversionGeneric)) { + + // Get the return type of the destination ptr-to-function we are converting + // to. This is necessary for matching the lambda call operator's return + // type to that of the destination ptr-to-function's return type. + assert(A->isPointerType() && + "Can only convert from lambda to ptr-to-function"); + const FunctionType *ToFunType = + A->getPointeeType().getTypePtr()->getAs<FunctionType>(); + const QualType DestFunctionPtrReturnType = ToFunType->getResultType(); + + // Create the corresponding specializations of the call operator and + // the static-invoker; and if the return type is auto, + // deduce the return type and check if it matches the + // DestFunctionPtrReturnType. + // For instance: + // auto L = [](auto a) { return f(a); }; + // int (*fp)(int) = L; + // char (*fp2)(int) = L; <-- Not OK. + + Result = SpecializeCorrespondingLambdaCallOperatorAndInvoker( + Specialization, Deduced, DestFunctionPtrReturnType, + Info, *this); + } return Result; } @@ -3750,17 +4080,29 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) { return DAR_Succeeded; } -QualType Sema::SubstAutoType(QualType Type, QualType Deduced) { - return SubstituteAutoTransform(*this, Deduced).TransformType(Type); +QualType Sema::SubstAutoType(QualType TypeWithAuto, + QualType TypeToReplaceAuto) { + return SubstituteAutoTransform(*this, TypeToReplaceAuto). + TransformType(TypeWithAuto); +} + +TypeSourceInfo* Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, + QualType TypeToReplaceAuto) { + return SubstituteAutoTransform(*this, TypeToReplaceAuto). + TransformType(TypeWithAuto); } void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) { if (isa<InitListExpr>(Init)) Diag(VDecl->getLocation(), - diag::err_auto_var_deduction_failure_from_init_list) + VDecl->isInitCapture() + ? diag::err_init_capture_deduction_failure_from_init_list + : 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) + Diag(VDecl->getLocation(), + VDecl->isInitCapture() ? diag::err_init_capture_deduction_failure + : diag::err_auto_var_deduction_failure) << VDecl->getDeclName() << VDecl->getType() << Init->getType() << Init->getSourceRange(); } @@ -3788,9 +4130,10 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, llvm::SmallBitVector &Deduced); /// \brief If this is a non-static member function, -static void AddImplicitObjectParameterType(ASTContext &Context, - CXXMethodDecl *Method, - SmallVectorImpl<QualType> &ArgTypes) { +static void +AddImplicitObjectParameterType(ASTContext &Context, + CXXMethodDecl *Method, + SmallVectorImpl<QualType> &ArgTypes) { // C++11 [temp.func.order]p3: // [...] The new parameter is of type "reference to cv A," where cv are // the cv-qualifiers of the function template (if any) and A is @@ -3815,7 +4158,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, TemplatePartialOrderingContext TPOC, - unsigned NumCallArguments, + unsigned NumCallArguments1, SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) { FunctionDecl *FD1 = FT1->getTemplatedDecl(); FunctionDecl *FD2 = FT2->getTemplatedDecl(); @@ -3831,19 +4174,13 @@ static bool isAtLeastAsSpecializedAs(Sema &S, // The types used to determine the ordering depend on the context in which // the partial ordering is done: TemplateDeductionInfo Info(Loc); - CXXMethodDecl *Method1 = 0; - CXXMethodDecl *Method2 = 0; - bool IsNonStatic2 = false; - bool IsNonStatic1 = false; - unsigned Skip2 = 0; + SmallVector<QualType, 4> Args2; switch (TPOC) { case TPOC_Call: { // - In the context of a function call, the function parameter types are // used. - Method1 = dyn_cast<CXXMethodDecl>(FD1); - Method2 = dyn_cast<CXXMethodDecl>(FD2); - IsNonStatic1 = Method1 && !Method1->isStatic(); - IsNonStatic2 = Method2 && !Method2->isStatic(); + CXXMethodDecl *Method1 = dyn_cast<CXXMethodDecl>(FD1); + CXXMethodDecl *Method2 = dyn_cast<CXXMethodDecl>(FD2); // C++11 [temp.func.order]p3: // [...] If only one of the function templates is a non-static @@ -3862,26 +4199,39 @@ static bool isAtLeastAsSpecializedAs(Sema &S, // first argument of the free function, which seems to match // existing practice. SmallVector<QualType, 4> Args1; - unsigned Skip1 = !S.getLangOpts().CPlusPlus11 && IsNonStatic2 && !Method1; - if (S.getLangOpts().CPlusPlus11 && IsNonStatic1 && !Method2) - AddImplicitObjectParameterType(S.Context, Method1, Args1); + + unsigned Skip1 = 0, Skip2 = 0; + unsigned NumComparedArguments = NumCallArguments1; + + if (!Method2 && Method1 && !Method1->isStatic()) { + if (S.getLangOpts().CPlusPlus11) { + // Compare 'this' from Method1 against first parameter from Method2. + AddImplicitObjectParameterType(S.Context, Method1, Args1); + ++NumComparedArguments; + } else + // Ignore first parameter from Method2. + ++Skip2; + } else if (!Method1 && Method2 && !Method2->isStatic()) { + if (S.getLangOpts().CPlusPlus11) + // Compare 'this' from Method2 against first parameter from Method1. + AddImplicitObjectParameterType(S.Context, Method2, Args2); + else + // Ignore first parameter from Method1. + ++Skip1; + } + Args1.insert(Args1.end(), Proto1->arg_type_begin() + Skip1, Proto1->arg_type_end()); - - SmallVector<QualType, 4> Args2; - Skip2 = !S.getLangOpts().CPlusPlus11 && IsNonStatic1 && !Method2; - if (S.getLangOpts().CPlusPlus11 && IsNonStatic2 && !Method1) - AddImplicitObjectParameterType(S.Context, Method2, Args2); Args2.insert(Args2.end(), Proto2->arg_type_begin() + Skip2, Proto2->arg_type_end()); // C++ [temp.func.order]p5: // The presence of unused ellipsis and default arguments has no effect on // the partial ordering of function templates. - if (Args1.size() > NumCallArguments) - Args1.resize(NumCallArguments); - if (Args2.size() > NumCallArguments) - Args2.resize(NumCallArguments); + if (Args1.size() > NumComparedArguments) + Args1.resize(NumComparedArguments); + if (Args2.size() > NumComparedArguments) + Args2.resize(NumComparedArguments); if (DeduceTemplateArguments(S, TemplateParams, Args2.data(), Args2.size(), Args1.data(), Args1.size(), Info, Deduced, TDF_None, /*PartialOrdering=*/true, @@ -3935,20 +4285,12 @@ static bool isAtLeastAsSpecializedAs(Sema &S, // Figure out which template parameters were used. llvm::SmallBitVector UsedParameters(TemplateParams->size()); switch (TPOC) { - case TPOC_Call: { - unsigned NumParams = std::min(NumCallArguments, - std::min(Proto1->getNumArgs(), - Proto2->getNumArgs())); - if (S.getLangOpts().CPlusPlus11 && IsNonStatic2 && !IsNonStatic1) - ::MarkUsedTemplateParameters(S.Context, Method2->getThisType(S.Context), - false, - TemplateParams->getDepth(), UsedParameters); - for (unsigned I = Skip2; I < NumParams; ++I) - ::MarkUsedTemplateParameters(S.Context, Proto2->getArgType(I), false, + case TPOC_Call: + for (unsigned I = 0, N = Args2.size(); I != N; ++I) + ::MarkUsedTemplateParameters(S.Context, Args2[I], false, TemplateParams->getDepth(), UsedParameters); break; - } case TPOC_Conversion: ::MarkUsedTemplateParameters(S.Context, Proto2->getResultType(), false, @@ -4003,8 +4345,11 @@ static bool isVariadicFunctionTemplate(FunctionTemplateDecl *FunTmpl) { /// \param TPOC the context in which we are performing partial ordering of /// function templates. /// -/// \param NumCallArguments The number of arguments in a call, used only -/// when \c TPOC is \c TPOC_Call. +/// \param NumCallArguments1 The number of arguments in the call to FT1, used +/// only when \c TPOC is \c TPOC_Call. +/// +/// \param NumCallArguments2 The number of arguments in the call to FT2, used +/// only when \c TPOC is \c TPOC_Call. /// /// \returns the more specialized function template. If neither /// template is more specialized, returns NULL. @@ -4013,12 +4358,13 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, SourceLocation Loc, TemplatePartialOrderingContext TPOC, - unsigned NumCallArguments) { + unsigned NumCallArguments1, + unsigned NumCallArguments2) { SmallVector<RefParamPartialOrderingComparison, 4> RefParamComparisons; bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC, - NumCallArguments, 0); + NumCallArguments1, 0); bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC, - NumCallArguments, + NumCallArguments2, &RefParamComparisons); if (Better1 != Better2) // We have a clear winner @@ -4122,12 +4468,6 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) { /// \param SpecEnd the end iterator of the function template /// specializations, paired with \p SpecBegin. /// -/// \param TPOC the partial ordering context to use to compare the function -/// template specializations. -/// -/// \param NumCallArguments The number of arguments in a call, used only -/// when \c TPOC is \c TPOC_Call. -/// /// \param Loc the location where the ambiguity or no-specializations /// diagnostic should occur. /// @@ -4144,23 +4484,17 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) { /// /// \returns the most specialized function template specialization, if /// found. Otherwise, returns SpecEnd. -/// -/// \todo FIXME: Consider passing in the "also-ran" candidates that failed -/// template argument deduction. -UnresolvedSetIterator -Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin, - UnresolvedSetIterator SpecEnd, - TemplatePartialOrderingContext TPOC, - unsigned NumCallArguments, - SourceLocation Loc, - const PartialDiagnostic &NoneDiag, - const PartialDiagnostic &AmbigDiag, - const PartialDiagnostic &CandidateDiag, - bool Complain, - QualType TargetType) { +UnresolvedSetIterator Sema::getMostSpecialized( + UnresolvedSetIterator SpecBegin, UnresolvedSetIterator SpecEnd, + TemplateSpecCandidateSet &FailedCandidates, + SourceLocation Loc, const PartialDiagnostic &NoneDiag, + const PartialDiagnostic &AmbigDiag, const PartialDiagnostic &CandidateDiag, + bool Complain, QualType TargetType) { if (SpecBegin == SpecEnd) { - if (Complain) + if (Complain) { Diag(Loc, NoneDiag); + FailedCandidates.NoteCandidates(*this, Loc); + } return SpecEnd; } @@ -4178,7 +4512,7 @@ Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin, = cast<FunctionDecl>(*I)->getPrimaryTemplate(); assert(Challenger && "Not a function template specialization?"); if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger, - Loc, TPOC, NumCallArguments), + Loc, TPOC_Other, 0, 0), Challenger)) { Best = I; BestTemplate = Challenger; @@ -4193,7 +4527,7 @@ Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin, = cast<FunctionDecl>(*I)->getPrimaryTemplate(); if (I != Best && !isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger, - Loc, TPOC, NumCallArguments), + Loc, TPOC_Other, 0, 0), BestTemplate)) { Ambiguous = true; break; @@ -4279,6 +4613,67 @@ Sema::getMoreSpecializedPartialSpecialization( /*RefParamComparisons=*/0); if (Better1) { SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end()); + InstantiatingTemplate Inst(*this, PS2->getLocation(), PS2, DeducedArgs, + Info); + Better1 = !::FinishTemplateArgumentDeduction( + *this, PS2, PS1->getTemplateArgs(), Deduced, Info); + } + + // Determine whether PS2 is at least as specialized as PS1 + Deduced.clear(); + Deduced.resize(PS1->getTemplateParameters()->size()); + bool Better2 = !DeduceTemplateArgumentsByTypeMatch( + *this, PS1->getTemplateParameters(), PT1, PT2, Info, Deduced, TDF_None, + /*PartialOrdering=*/true, + /*RefParamComparisons=*/0); + if (Better2) { + SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), + Deduced.end()); + InstantiatingTemplate Inst(*this, PS1->getLocation(), PS1, DeducedArgs, + Info); + Better2 = !::FinishTemplateArgumentDeduction( + *this, PS1, PS2->getTemplateArgs(), Deduced, Info); + } + + if (Better1 == Better2) + return 0; + + return Better1 ? PS1 : PS2; +} + +/// TODO: Unify with ClassTemplatePartialSpecializationDecl version? +/// May require unifying ClassTemplate(Partial)SpecializationDecl and +/// VarTemplate(Partial)SpecializationDecl with a new data +/// structure Template(Partial)SpecializationDecl, and +/// using Template(Partial)SpecializationDecl as input type. +VarTemplatePartialSpecializationDecl * +Sema::getMoreSpecializedPartialSpecialization( + VarTemplatePartialSpecializationDecl *PS1, + VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc) { + SmallVector<DeducedTemplateArgument, 4> Deduced; + TemplateDeductionInfo Info(Loc); + + assert(PS1->getSpecializedTemplate() == PS1->getSpecializedTemplate() && + "the partial specializations being compared should specialize" + " the same template."); + TemplateName Name(PS1->getSpecializedTemplate()); + TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name); + QualType PT1 = Context.getTemplateSpecializationType( + CanonTemplate, PS1->getTemplateArgs().data(), + PS1->getTemplateArgs().size()); + QualType PT2 = Context.getTemplateSpecializationType( + CanonTemplate, PS2->getTemplateArgs().data(), + PS2->getTemplateArgs().size()); + + // Determine whether PS1 is at least as specialized as PS2 + Deduced.resize(PS2->getTemplateParameters()->size()); + bool Better1 = !DeduceTemplateArgumentsByTypeMatch( + *this, PS2->getTemplateParameters(), PT2, PT1, Info, Deduced, TDF_None, + /*PartialOrdering=*/true, + /*RefParamComparisons=*/0); + if (Better1) { + SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), + Deduced.end()); InstantiatingTemplate Inst(*this, PS2->getLocation(), PS2, DeducedArgs, Info); Better1 = !::FinishTemplateArgumentDeduction(*this, PS2, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp index 7ef04e964dc6..8904f3794955 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -14,6 +14,7 @@ #include "TreeTransform.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/Basic/LangOptions.h" @@ -61,7 +62,24 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D, DeclContext *Ctx = dyn_cast<DeclContext>(D); if (!Ctx) { Ctx = D->getDeclContext(); - + + // Add template arguments from a variable template instantiation. + if (VarTemplateSpecializationDecl *Spec = + dyn_cast<VarTemplateSpecializationDecl>(D)) { + // We're done when we hit an explicit specialization. + if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization && + !isa<VarTemplatePartialSpecializationDecl>(Spec)) + return Result; + + Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs()); + + // If this variable template specialization was instantiated from a + // specialized member that is a variable template, we're done. + assert(Spec->getSpecializedTemplate() && "No variable template?"); + if (Spec->getSpecializedTemplate()->isMemberSpecialization()) + return Result; + } + // If we have a template template parameter with translation unit context, // then we're performing substitution into a default template argument of // this template template parameter before we've constructed the template @@ -72,7 +90,7 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D, if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) { for (unsigned I = 0, N = TTP->getDepth() + 1; I != N; ++I) - Result.addOuterTemplateArguments(0, 0); + Result.addOuterTemplateArguments(None); return Result; } } @@ -113,12 +131,15 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D, assert(Function->getPrimaryTemplate() && "No function template?"); if (Function->getPrimaryTemplate()->isMemberSpecialization()) break; + + // If this function is a generic lambda specialization, we are done. + if (isGenericLambdaCallOperatorSpecialization(Function)) + break; + } else if (FunctionTemplateDecl *FunTmpl = Function->getDescribedFunctionTemplate()) { // Add the "injected" template arguments. - std::pair<const TemplateArgument *, unsigned> - Injected = FunTmpl->getInjectedTemplateArgs(); - Result.addOuterTemplateArguments(Injected.first, Injected.second); + Result.addOuterTemplateArguments(FunTmpl->getInjectedTemplateArgs()); } // If this is a friend declaration and it declares an entity at @@ -135,9 +156,10 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D, } else if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Ctx)) { if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) { QualType T = ClassTemplate->getInjectedClassNameSpecialization(); - const TemplateSpecializationType *TST - = cast<TemplateSpecializationType>(Context.getCanonicalType(T)); - Result.addOuterTemplateArguments(TST->getArgs(), TST->getNumArgs()); + const TemplateSpecializationType *TST = + cast<TemplateSpecializationType>(Context.getCanonicalType(T)); + Result.addOuterTemplateArguments( + llvm::makeArrayRef(TST->getArgs(), TST->getNumArgs())); if (ClassTemplate->isMemberSpecialization()) break; } @@ -293,6 +315,29 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, } } +Sema::InstantiatingTemplate::InstantiatingTemplate( + Sema &SemaRef, SourceLocation PointOfInstantiation, + VarTemplatePartialSpecializationDecl *PartialSpec, + ArrayRef<TemplateArgument> TemplateArgs, + sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange) + : SemaRef(SemaRef), SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) { + Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange); + if (!Invalid) { + ActiveTemplateInstantiation Inst; + Inst.Kind = + ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Entity = PartialSpec; + Inst.TemplateArgs = TemplateArgs.data(); + Inst.NumTemplateArgs = TemplateArgs.size(); + Inst.DeductionInfo = &DeductionInfo; + Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + } +} + Sema::InstantiatingTemplate:: InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, ParmVarDecl *Param, @@ -399,6 +444,18 @@ void Sema::InstantiatingTemplate::Clear() { } SemaRef.InNonInstantiationSFINAEContext = SavedInNonInstantiationSFINAEContext; + + // Name lookup no longer looks in this template's defining module. + assert(SemaRef.ActiveTemplateInstantiations.size() >= + SemaRef.ActiveTemplateInstantiationLookupModules.size() && + "forgot to remove a lookup module for a template instantiation"); + if (SemaRef.ActiveTemplateInstantiations.size() == + SemaRef.ActiveTemplateInstantiationLookupModules.size()) { + if (Module *M = SemaRef.ActiveTemplateInstantiationLookupModules.back()) + SemaRef.LookupModulesCache.erase(M); + SemaRef.ActiveTemplateInstantiationLookupModules.pop_back(); + } + SemaRef.ActiveTemplateInstantiations.pop_back(); Invalid = true; } @@ -436,7 +493,7 @@ void Sema::PrintInstantiationStack() { // FIXME: In all of these cases, we need to show the template arguments unsigned InstantiationIdx = 0; - for (SmallVector<ActiveTemplateInstantiation, 16>::reverse_iterator + for (SmallVectorImpl<ActiveTemplateInstantiation>::reverse_iterator Active = ActiveTemplateInstantiations.rbegin(), ActiveEnd = ActiveTemplateInstantiations.rend(); Active != ActiveEnd; @@ -473,7 +530,9 @@ void Sema::PrintInstantiationStack() { << Active->InstantiationRange; } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { Diags.Report(Active->PointOfInstantiation, - diag::note_template_static_data_member_def_here) + VD->isStaticDataMember()? + diag::note_template_static_data_member_def_here + : diag::note_template_variable_def_here) << VD << Active->InstantiationRange; } else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) { @@ -616,7 +675,7 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const { if (InNonInstantiationSFINAEContext) return Optional<TemplateDeductionInfo *>(0); - for (SmallVector<ActiveTemplateInstantiation, 16>::const_reverse_iterator + for (SmallVectorImpl<ActiveTemplateInstantiation>::const_reverse_iterator Active = ActiveTemplateInstantiations.rbegin(), ActiveEnd = ActiveTemplateInstantiations.rend(); Active != ActiveEnd; @@ -708,9 +767,8 @@ namespace { bool TryExpandParameterPacks(SourceLocation EllipsisLoc, SourceRange PatternRange, - llvm::ArrayRef<UnexpandedParameterPack> Unexpanded, - bool &ShouldExpand, - bool &RetainExpansion, + ArrayRef<UnexpandedParameterPack> Unexpanded, + bool &ShouldExpand, bool &RetainExpansion, Optional<unsigned> &NumExpansions) { return getSema().CheckParameterPacksForExpansion(EllipsisLoc, PatternRange, Unexpanded, @@ -859,13 +917,38 @@ namespace { } ExprResult TransformLambdaScope(LambdaExpr *E, - CXXMethodDecl *CallOperator) { - CallOperator->setInstantiationOfMemberFunction(E->getCallOperator(), - TSK_ImplicitInstantiation); - return TreeTransform<TemplateInstantiator>:: - TransformLambdaScope(E, CallOperator); + CXXMethodDecl *NewCallOperator, + ArrayRef<InitCaptureInfoTy> InitCaptureExprsAndTypes) { + CXXMethodDecl *const OldCallOperator = E->getCallOperator(); + // In the generic lambda case, we set the NewTemplate to be considered + // an "instantiation" of the OldTemplate. + if (FunctionTemplateDecl *const NewCallOperatorTemplate = + NewCallOperator->getDescribedFunctionTemplate()) { + + FunctionTemplateDecl *const OldCallOperatorTemplate = + OldCallOperator->getDescribedFunctionTemplate(); + NewCallOperatorTemplate->setInstantiatedFromMemberTemplate( + OldCallOperatorTemplate); + // Mark the NewCallOperatorTemplate a specialization. + NewCallOperatorTemplate->setMemberSpecialization(); + } else + // For a non-generic lambda we set the NewCallOperator to + // be an instantiation of the OldCallOperator. + NewCallOperator->setInstantiationOfMemberFunction(OldCallOperator, + TSK_ImplicitInstantiation); + + return inherited::TransformLambdaScope(E, NewCallOperator, + InitCaptureExprsAndTypes); + } + TemplateParameterList *TransformTemplateParameterList(
+ TemplateParameterList *OrigTPL) { + if (!OrigTPL || !OrigTPL->size()) return OrigTPL; + + DeclContext *Owner = OrigTPL->getParam(0)->getDeclContext(); + TemplateDeclInstantiator DeclInstantiator(getSema(), + /* DeclContext *Owner */ Owner, TemplateArgs); + return DeclInstantiator.SubstTemplateParams(OrigTPL); } - private: ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm, SourceLocation loc, @@ -884,6 +967,16 @@ bool TemplateInstantiator::AlreadyTransformed(QualType T) { return true; } +static TemplateArgument +getPackSubstitutedTemplateArgument(Sema &S, TemplateArgument Arg) { + assert(S.ArgumentPackSubstitutionIndex >= 0); + assert(S.ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); + Arg = Arg.pack_begin()[S.ArgumentPackSubstitutionIndex]; + if (Arg.isPackExpansion()) + Arg = Arg.getPackExpansionPattern(); + return Arg; +} + Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) { if (!D) return 0; @@ -903,10 +996,7 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) { if (TTP->isParameterPack()) { assert(Arg.getKind() == TemplateArgument::Pack && "Missing argument pack"); - - assert(getSema().ArgumentPackSubstitutionIndex >= 0); - assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); - Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); } TemplateName Template = Arg.getAsTemplate(); @@ -951,8 +1041,7 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D, if (getSema().ArgumentPackSubstitutionIndex == -1) return 0; - assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); - Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); } QualType T = Arg.getAsType(); @@ -1054,9 +1143,8 @@ TemplateName TemplateInstantiator::TransformTemplateName(CXXScopeSpec &SS, // keep the entire argument pack. return getSema().Context.getSubstTemplateTemplateParmPack(TTP, Arg); } - - assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); - Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + + Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); } TemplateName Template = Arg.getAsTemplate(); @@ -1078,11 +1166,9 @@ TemplateName TemplateInstantiator::TransformTemplateName(CXXScopeSpec &SS, if (getSema().ArgumentPackSubstitutionIndex == -1) return Name; - const TemplateArgument &ArgPack = SubstPack->getArgumentPack(); - assert(getSema().ArgumentPackSubstitutionIndex < (int)ArgPack.pack_size() && - "Pack substitution index out-of-range"); - return ArgPack.pack_begin()[getSema().ArgumentPackSubstitutionIndex] - .getAsTemplate(); + TemplateArgument Arg = SubstPack->getArgumentPack(); + Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); + return Arg.getAsTemplate(); } return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType, @@ -1094,25 +1180,7 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) { if (!E->isTypeDependent()) return SemaRef.Owned(E); - FunctionDecl *currentDecl = getSema().getCurFunctionDecl(); - assert(currentDecl && "Must have current function declaration when " - "instantiating."); - - PredefinedExpr::IdentType IT = E->getIdentType(); - - unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length(); - - llvm::APInt LengthI(32, Length + 1); - QualType ResTy; - if (IT == PredefinedExpr::LFunction) - ResTy = getSema().Context.WCharTy.withConst(); - else - ResTy = getSema().Context.CharTy.withConst(); - ResTy = getSema().Context.getConstantArrayType(ResTy, LengthI, - ArrayType::Normal, 0); - PredefinedExpr *PE = - new (getSema().Context) PredefinedExpr(E->getLocation(), ResTy, IT); - return getSema().Owned(PE); + return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentType()); } ExprResult @@ -1147,8 +1215,7 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, Arg); } - assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); - Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); } return transformNonTypeTemplateParmRef(NTTP, E->getLocation(), Arg); @@ -1161,14 +1228,6 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef( ExprResult result; QualType type; - // If the argument is a pack expansion, the parameter must actually be a - // parameter pack, and we should substitute the pattern itself, producing - // an expression which contains an unexpanded parameter pack. - if (arg.isPackExpansion()) { - assert(parm->isParameterPack() && "pack expansion for non-pack"); - arg = arg.getPackExpansionPattern(); - } - // The template argument itself might be an expression, in which // case we just return that expression. if (arg.getKind() == TemplateArgument::Expression) { @@ -1234,12 +1293,9 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr( // We aren't expanding the parameter pack, so just return ourselves. return getSema().Owned(E); } - - const TemplateArgument &ArgPack = E->getArgumentPack(); - unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex; - assert(Index < ArgPack.pack_size() && "Substitution index out-of-range"); - - const TemplateArgument &Arg = ArgPack.pack_begin()[Index]; + + TemplateArgument Arg = E->getArgumentPack(); + Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); return transformNonTypeTemplateParmRef(E->getParameterPack(), E->getParameterPackLocation(), Arg); @@ -1410,8 +1466,7 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, return Result; } - assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); - Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); } assert(Arg.getKind() == TemplateArgument::Type && @@ -1459,12 +1514,11 @@ TemplateInstantiator::TransformSubstTemplateTypeParmPackType( NewTL.setNameLoc(TL.getNameLoc()); return TL.getType(); } - - const TemplateArgument &ArgPack = TL.getTypePtr()->getArgumentPack(); - unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex; - assert(Index < ArgPack.pack_size() && "Substitution index out-of-range"); - - QualType Result = ArgPack.pack_begin()[Index].getAsType(); + + TemplateArgument Arg = TL.getTypePtr()->getArgumentPack(); + Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); + QualType Result = Arg.getAsType(); + Result = getSema().Context.getSubstTemplateTypeParmType( TL.getTypePtr()->getReplacedParameter(), Result); @@ -1577,6 +1631,9 @@ static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) { for (unsigned I = 0, E = FP.getNumArgs(); I != E; ++I) { ParmVarDecl *P = FP.getArg(I); + // This must be synthesized from a typedef. + if (!P) continue; + // The parameter's type as written might be dependent even if the // decayed type was not dependent. if (TypeSourceInfo *TSInfo = P->getTypeSourceInfo()) @@ -1755,6 +1812,10 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, Base = Pattern->bases_begin(), BaseEnd = Pattern->bases_end(); Base != BaseEnd; ++Base) { if (!Base->getType()->isDependentType()) { + if (const CXXRecordDecl *RD = Base->getType()->getAsCXXRecordDecl()) { + if (RD->isInvalidDecl()) + Instantiation->setInvalidDecl(); + } InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(*Base)); continue; } @@ -1949,7 +2010,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, } InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation); - if (Inst) + if (Inst.isInvalid()) return true; // Enter the scope of this instantiation. We don't use @@ -2081,6 +2142,14 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, E = LateAttrs.end(); I != E; ++I) { assert(CurrentInstantiationScope == Instantiator.getStartingScope()); CurrentInstantiationScope = I->Scope; + + // Allow 'this' within late-parsed attributes. + NamedDecl *ND = dyn_cast<NamedDecl>(I->NewDecl); + CXXRecordDecl *ThisContext = + dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext()); + CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0, + ND && ND->isCXXInstanceMember()); + Attr *NewAttr = instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs); I->NewDecl->addAttr(NewAttr); @@ -2104,13 +2173,25 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, // Instantiate any out-of-line class template partial // specializations now. - for (TemplateDeclInstantiator::delayed_partial_spec_iterator + for (TemplateDeclInstantiator::delayed_partial_spec_iterator P = Instantiator.delayed_partial_spec_begin(), PEnd = Instantiator.delayed_partial_spec_end(); P != PEnd; ++P) { if (!Instantiator.InstantiateClassTemplatePartialSpecialization( - P->first, - P->second)) { + P->first, P->second)) { + Instantiation->setInvalidDecl(); + break; + } + } + + // Instantiate any out-of-line variable template partial + // specializations now. + for (TemplateDeclInstantiator::delayed_var_partial_spec_iterator + P = Instantiator.delayed_var_partial_spec_begin(), + PEnd = Instantiator.delayed_var_partial_spec_end(); + P != PEnd; ++P) { + if (!Instantiator.InstantiateVarTemplatePartialSpecialization( + P->first, P->second)) { Instantiation->setInvalidDecl(); break; } @@ -2166,7 +2247,7 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation, } InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation); - if (Inst) + if (Inst.isInvalid()) return true; // Enter the scope of this instantiation. We don't use @@ -2198,12 +2279,10 @@ namespace { }; } -bool -Sema::InstantiateClassTemplateSpecialization( - SourceLocation PointOfInstantiation, - ClassTemplateSpecializationDecl *ClassTemplateSpec, - TemplateSpecializationKind TSK, - bool Complain) { +bool Sema::InstantiateClassTemplateSpecialization( + SourceLocation PointOfInstantiation, + ClassTemplateSpecializationDecl *ClassTemplateSpec, + TemplateSpecializationKind TSK, bool Complain) { // Perform the actual instantiation on the canonical declaration. ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>( ClassTemplateSpec->getCanonicalDecl()); @@ -2252,15 +2331,18 @@ Sema::InstantiateClassTemplateSpecialization( SmallVector<MatchResult, 4> Matched; SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs; Template->getPartialSpecializations(PartialSpecs); + TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation); for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) { ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I]; - TemplateDeductionInfo Info(PointOfInstantiation); + TemplateDeductionInfo Info(FailedCandidates.getLocation()); if (TemplateDeductionResult Result = DeduceTemplateArguments(Partial, ClassTemplateSpec->getTemplateArgs(), Info)) { - // FIXME: Store the failed-deduction information for use in - // diagnostics, later. + // Store the failed-deduction information for use in diagnostics, later. + // TODO: Actually use the failed-deduction info? + FailedCandidates.addCandidate() + .set(Partial, MakeDeductionFailureInfo(Context, Result, Info)); (void)Result; } else { Matched.push_back(PartialSpecMatchResult()); @@ -2275,7 +2357,7 @@ Sema::InstantiateClassTemplateSpecialization( SmallVector<const NamedDecl *, 4> InstantiatedTemplateParameters; if (Matched.size() >= 1) { - SmallVector<MatchResult, 4>::iterator Best = Matched.begin(); + SmallVectorImpl<MatchResult>::iterator Best = Matched.begin(); if (Matched.size() == 1) { // -- If exactly one matching specialization is found, the // instantiation is generated from that specialization. @@ -2288,8 +2370,8 @@ Sema::InstantiateClassTemplateSpecialization( // specialized than all of the other matching // specializations, then the use of the class template is // ambiguous and the program is ill-formed. - for (SmallVector<MatchResult, 4>::iterator P = Best + 1, - PEnd = Matched.end(); + for (SmallVectorImpl<MatchResult>::iterator P = Best + 1, + PEnd = Matched.end(); P != PEnd; ++P) { if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial, PointOfInstantiation) @@ -2300,8 +2382,8 @@ Sema::InstantiateClassTemplateSpecialization( // Determine if the best partial specialization is more specialized than // the others. bool Ambiguous = false; - for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(), - PEnd = Matched.end(); + for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(), + PEnd = Matched.end(); P != PEnd; ++P) { if (P != Best && getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial, @@ -2319,8 +2401,8 @@ Sema::InstantiateClassTemplateSpecialization( << ClassTemplateSpec; // Print the matching partial specializations. - for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(), - PEnd = Matched.end(); + for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(), + PEnd = Matched.end(); P != PEnd; ++P) Diag(P->Partial->getLocation(), diag::note_partial_spec_match) << getTemplateArgumentBindingsText( @@ -2377,6 +2459,11 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, CXXRecordDecl *Instantiation, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateSpecializationKind TSK) { + assert( + (TSK == TSK_ExplicitInstantiationDefinition || + TSK == TSK_ExplicitInstantiationDeclaration || + (TSK == TSK_ImplicitInstantiation && Instantiation->isLocalClass())) && + "Unexpected template specialization kind!"); for (DeclContext::decl_iterator D = Instantiation->decls_begin(), DEnd = Instantiation->decls_end(); D != DEnd; ++D) { @@ -2417,9 +2504,15 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, InstantiateFunctionDefinition(PointOfInstantiation, Function); } else { Function->setTemplateSpecializationKind(TSK, PointOfInstantiation); + if (TSK == TSK_ImplicitInstantiation) + PendingLocalImplicitInstantiations.push_back( + std::make_pair(Function, PointOfInstantiation)); } } } else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) { + if (isa<VarTemplateSpecializationDecl>(Var)) + continue; + if (Var->isStaticDataMember()) { MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); assert(MSInfo && "No member specialization information?"); @@ -2689,6 +2782,12 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) { break; } + // If we're performing a partial substitution during template argument + // deduction, we may not have values for template parameters yet. + if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) || + isa<TemplateTemplateParmDecl>(D)) + return 0; + // If we didn't find the decl, then we either have a sema bug, or we have a // forward reference to a label declaration. Return null to indicate that // we have an uninstantiated label. diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index d1428c51a4f9..5c28e3b7a828 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -25,6 +25,17 @@ using namespace clang; +static bool isDeclWithinFunction(const Decl *D) { + const DeclContext *DC = D->getDeclContext(); + if (DC->isFunctionOrMethod()) + return true; + + if (DC->isRecord()) + return cast<CXXRecordDecl>(DC)->isLocalClass(); + + return false; +} + bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl, DeclaratorDecl *NewDecl) { if (!OldDecl->getQualifierLoc()) @@ -142,6 +153,13 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, Saved = CurrentInstantiationScope->cloneScopes(OuterMostScope); LateAttrs->push_back(LateInstantiatedAttribute(TmplAttr, Saved, New)); } else { + // Allow 'this' within late-parsed attributes. + NamedDecl *ND = dyn_cast<NamedDecl>(New); + CXXRecordDecl *ThisContext = + dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext()); + CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0, + ND && ND->isCXXInstanceMember()); + Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, *this, TemplateArgs); if (NewAttr) @@ -247,7 +265,7 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, // If the typedef types are not identical, reject them. SemaRef.isIncompatibleTypedef(InstPrevTypedef, Typedef); - Typedef->setPreviousDeclaration(InstPrevTypedef); + Typedef->setPreviousDecl(InstPrevTypedef); } SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef); @@ -299,7 +317,7 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { = TypeAliasTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getDeclName(), InstParams, AliasInst); if (PrevAliasTemplate) - Inst->setPreviousDeclaration(PrevAliasTemplate); + Inst->setPreviousDecl(PrevAliasTemplate); Inst->setAccess(D->getAccess()); @@ -312,6 +330,12 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { } Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { + return VisitVarDecl(D, /*InstantiatingVarTemplate=*/false); +} + +Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, + bool InstantiatingVarTemplate) { + // If this is the variable for an anonymous struct or union, // instantiate the anonymous struct/union type first. if (const RecordType *RecordTy = D->getType()->getAs<RecordType>()) @@ -333,105 +357,26 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { return 0; } - // Build the instantiated declaration - VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner, - D->getInnerLocStart(), - D->getLocation(), D->getIdentifier(), - DI->getType(), DI, - D->getStorageClass()); - Var->setTSCSpec(D->getTSCSpec()); - Var->setInitStyle(D->getInitStyle()); - Var->setCXXForRangeDecl(D->isCXXForRangeDecl()); - Var->setConstexpr(D->isConstexpr()); - - // Substitute the nested name specifier, if any. - if (SubstQualifier(D, Var)) - return 0; - - // If we are instantiating a static data member defined - // out-of-line, the instantiation will have the same lexical - // context (which will be a namespace scope) as the template. - if (D->isOutOfLine()) - Var->setLexicalDeclContext(D->getLexicalDeclContext()); - - Var->setAccess(D->getAccess()); - - if (!D->isStaticDataMember()) { - Var->setUsed(D->isUsed(false)); - Var->setReferenced(D->isReferenced()); - } - - SemaRef.InstantiateAttrs(TemplateArgs, D, Var, LateAttrs, StartingScope); + DeclContext *DC = Owner; + if (D->isLocalExternDecl()) + SemaRef.adjustContextForLocalExternDecl(DC); - if (Var->hasAttrs()) - SemaRef.CheckAlignasUnderalignment(Var); + // Build the instantiated declaration. + VarDecl *Var = VarDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(), + D->getLocation(), D->getIdentifier(), + DI->getType(), DI, D->getStorageClass()); - // FIXME: In theory, we could have a previous declaration for variables that - // are not static data members. - // FIXME: having to fake up a LookupResult is dumb. - LookupResult Previous(SemaRef, Var->getDeclName(), Var->getLocation(), - 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()) { - D->getLexicalDeclContext()->addDecl(Var); - Owner->makeDeclVisibleInContext(Var); - } else { - Owner->addDecl(Var); - if (Owner->isFunctionOrMethod()) - SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Var); - } - - // Link instantiations of static data members back to the template from - // which they were instantiated. - if (Var->isStaticDataMember()) - SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D, - TSK_ImplicitInstantiation); - - if (Var->getAnyInitializer()) { - // We already have an initializer in the class. - } else if (D->getInit()) { - if (Var->isStaticDataMember() && !D->isOutOfLine()) - SemaRef.PushExpressionEvaluationContext(Sema::ConstantEvaluated, D); - else - SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated, D); - - // Instantiate the initializer. - ExprResult Init = SemaRef.SubstInitializer(D->getInit(), TemplateArgs, - D->getInitStyle() == VarDecl::CallInit); - if (!Init.isInvalid()) { - bool TypeMayContainAuto = true; - if (Init.get()) { - bool DirectInit = D->isDirectInit(); - SemaRef.AddInitializerToDecl(Var, Init.take(), DirectInit, - TypeMayContainAuto); - } else - SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto); - } else { - // FIXME: Not too happy about invalidating the declaration - // because of a bogus initializer. - Var->setInvalidDecl(); - } - - SemaRef.PopExpressionEvaluationContext(); - } else if ((!Var->isStaticDataMember() || Var->isOutOfLine()) && - !Var->isCXXForRangeDecl()) - SemaRef.ActOnUninitializedDecl(Var, false); - - // Diagnose unused local variables with dependent types, where the diagnostic - // will have been deferred. - if (!Var->isInvalidDecl() && Owner->isFunctionOrMethod() && !Var->isUsed() && - D->getType()->isDependentType()) - SemaRef.DiagnoseUnusedDecl(Var); + // Substitute the nested name specifier, if any. + if (SubstQualifier(D, Var)) + return 0; + SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner, + StartingScope, InstantiatingVarTemplate); return Var; } @@ -723,19 +668,17 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { } } - 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())) + // + // DR1484 clarifies that enumeration definitions inside of a template + // declaration aren't considered entities that can be separately instantiated + // from the rest of the entity they are declared inside of. + if (isDeclWithinFunction(D) ? D == Def : Def && !Enum->isScoped()) { + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum); InstantiateEnumDefinition(Enum, Def); + } return Enum; } @@ -953,7 +896,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { else Inst->setAccess(D->getAccess()); - Inst->setObjectOfFriendDecl(PrevClassTemplate != 0); + Inst->setObjectOfFriendDecl(); // TODO: do we want to track the instantiation progeny of this // friend target decl? } else { @@ -988,7 +931,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs; D->getPartialSpecializations(PartialSpecs); for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) - if (PartialSpecs[I]->isOutOfLine()) + if (PartialSpecs[I]->getFirstDecl()->isOutOfLine()) OutOfLinePartialSpecs.push_back(std::make_pair(Inst, PartialSpecs[I])); } @@ -1019,6 +962,85 @@ TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl( return InstantiateClassTemplatePartialSpecialization(InstClassTemplate, D); } +Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) { + assert(D->getTemplatedDecl()->isStaticDataMember() && + "Only static data member templates are allowed."); + + // Create a local instantiation scope for this variable template, which + // will contain the instantiations of the template parameters. + LocalInstantiationScope Scope(SemaRef); + TemplateParameterList *TempParams = D->getTemplateParameters(); + TemplateParameterList *InstParams = SubstTemplateParams(TempParams); + if (!InstParams) + return NULL; + + VarDecl *Pattern = D->getTemplatedDecl(); + VarTemplateDecl *PrevVarTemplate = 0; + + if (Pattern->getPreviousDecl()) { + DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); + if (!Found.empty()) + PrevVarTemplate = dyn_cast<VarTemplateDecl>(Found.front()); + } + + VarDecl *VarInst = + cast_or_null<VarDecl>(VisitVarDecl(Pattern, + /*InstantiatingVarTemplate=*/true)); + + DeclContext *DC = Owner; + + VarTemplateDecl *Inst = VarTemplateDecl::Create( + SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams, + VarInst, PrevVarTemplate); + VarInst->setDescribedVarTemplate(Inst); + + Inst->setAccess(D->getAccess()); + if (!PrevVarTemplate) + Inst->setInstantiatedFromMemberTemplate(D); + + if (D->isOutOfLine()) { + Inst->setLexicalDeclContext(D->getLexicalDeclContext()); + VarInst->setLexicalDeclContext(D->getLexicalDeclContext()); + } + + Owner->addDecl(Inst); + + if (!PrevVarTemplate) { + // Queue up any out-of-line partial specializations of this member + // variable template; the client will force their instantiation once + // the enclosing class has been instantiated. + SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs; + D->getPartialSpecializations(PartialSpecs); + for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) + if (PartialSpecs[I]->getFirstDecl()->isOutOfLine()) + OutOfLineVarPartialSpecs.push_back( + std::make_pair(Inst, PartialSpecs[I])); + } + + return Inst; +} + +Decl *TemplateDeclInstantiator::VisitVarTemplatePartialSpecializationDecl( + VarTemplatePartialSpecializationDecl *D) { + assert(D->isStaticDataMember() && + "Only static data member templates are allowed."); + + VarTemplateDecl *VarTemplate = D->getSpecializedTemplate(); + + // Lookup the already-instantiated declaration and return that. + DeclContext::lookup_result Found = Owner->lookup(VarTemplate->getDeclName()); + assert(!Found.empty() && "Instantiation found nothing?"); + + VarTemplateDecl *InstVarTemplate = dyn_cast<VarTemplateDecl>(Found.front()); + assert(InstVarTemplate && "Instantiation did not find a variable template?"); + + if (VarTemplatePartialSpecializationDecl *Result = + InstVarTemplate->findPartialSpecInstantiatedFromMember(D)) + return Result; + + return InstantiateVarTemplatePartialSpecialization(InstVarTemplate, D); +} + Decl * TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { // Create a local instantiation scope for this function template, which @@ -1103,17 +1125,30 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { // If the original function was part of a friend declaration, // inherit its namespace state. - if (Decl::FriendObjectKind FOK = D->getFriendObjectKind()) - Record->setObjectOfFriendDecl(FOK == Decl::FOK_Declared); + if (D->getFriendObjectKind()) + Record->setObjectOfFriendDecl(); // Make sure that anonymous structs and unions are recorded. - if (D->isAnonymousStructOrUnion()) { + if (D->isAnonymousStructOrUnion()) Record->setAnonymousStructOrUnion(true); - if (Record->getDeclContext()->getRedeclContext()->isFunctionOrMethod()) - SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Record); - } + + if (D->isLocalClass()) + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Record); Owner->addDecl(Record); + + // DR1484 clarifies that the members of a local class are instantiated as part + // of the instantiation of their enclosing entity. + if (D->isCompleteDefinition() && D->isLocalClass()) { + if (SemaRef.InstantiateClass(D->getLocation(), Record, D, TemplateArgs, + TSK_ImplicitInstantiation, + /*Complain=*/true)) { + llvm_unreachable("InstantiateClass shouldn't fail here!"); + } else { + SemaRef.InstantiateClassMembers(D->getLocation(), Record, TemplateArgs, + TSK_ImplicitInstantiation); + } + } return Record; } @@ -1136,9 +1171,7 @@ static QualType adjustFunctionTypeForInstantiation(ASTContext &Context, FunctionProtoType::ExtProtoInfo NewEPI = NewFunc->getExtProtoInfo(); NewEPI.ExtInfo = OrigFunc->getExtInfo(); return Context.getFunctionType(NewFunc->getResultType(), - ArrayRef<QualType>(NewFunc->arg_type_begin(), - NewFunc->getNumArgs()), - NewEPI); + NewFunc->getArgTypes(), NewEPI); } /// Normal class members are of more specific types and therefore @@ -1191,11 +1224,13 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, } // If we're instantiating a local function declaration, put the result - // in the owner; otherwise we need to find the instantiated context. + // in the enclosing namespace; otherwise we need to find the instantiated + // context. DeclContext *DC; - if (D->getDeclContext()->isFunctionOrMethod()) + if (D->isLocalExternDecl()) { DC = Owner; - else if (isFriend && QualifierLoc) { + SemaRef.adjustContextForLocalExternDecl(DC); + } else if (isFriend && QualifierLoc) { CXXScopeSpec SS; SS.Adopt(QualifierLoc); DC = SemaRef.computeDeclContext(SS); @@ -1211,6 +1246,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, D->getCanonicalDecl()->getStorageClass(), D->isInlineSpecified(), D->hasWrittenPrototype(), D->isConstexpr()); + Function->setRangeEnd(D->getSourceRange().getEnd()); if (D->isInlined()) Function->setImplicitlyInline(); @@ -1218,8 +1254,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, if (QualifierLoc) Function->setQualifierInfo(QualifierLoc); + if (D->isLocalExternDecl()) + Function->setLocalExternDecl(); + DeclContext *LexicalDC = Owner; - if (!isFriend && D->isOutOfLine()) { + if (!isFriend && D->isOutOfLine() && !D->isLocalExternDecl()) { assert(D->getDeclContext()->isFileContext()); LexicalDC = D->getDeclContext(); } @@ -1227,26 +1266,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, Function->setLexicalDeclContext(LexicalDC); // Attach the parameters - if (isa<FunctionProtoType>(Function->getType().IgnoreParens())) { - // Adopt the already-instantiated parameters into our own context. - for (unsigned P = 0; P < Params.size(); ++P) - if (Params[P]) - Params[P]->setOwningFunction(Function); - } else { - // Since we were instantiated via a typedef of a function type, create - // new parameters. - const FunctionProtoType *Proto - = Function->getType()->getAs<FunctionProtoType>(); - assert(Proto && "No function prototype in template instantiation?"); - for (FunctionProtoType::arg_type_iterator AI = Proto->arg_type_begin(), - AE = Proto->arg_type_end(); AI != AE; ++AI) { - ParmVarDecl *Param - = SemaRef.BuildParmVarDeclForTypedef(Function, Function->getLocation(), - *AI); - Param->setScopeInfo(0, Params.size()); - Params.push_back(Param); - } - } + for (unsigned P = 0; P < Params.size(); ++P) + if (Params[P]) + Params[P]->setOwningFunction(Function); Function->setParams(Params); SourceLocation InstantiateAtPOI; @@ -1302,15 +1324,18 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, bool isExplicitSpecialization = false; - LookupResult Previous(SemaRef, Function->getDeclName(), SourceLocation(), - Sema::LookupOrdinaryName, Sema::ForRedeclaration); + LookupResult Previous( + SemaRef, Function->getDeclName(), SourceLocation(), + D->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage + : Sema::LookupOrdinaryName, + Sema::ForRedeclaration); if (DependentFunctionTemplateSpecializationInfo *Info = D->getDependentSpecializationInfo()) { assert(isFriend && "non-friend has dependent specialization info?"); // This needs to be set now for future sanity. - Function->setObjectOfFriendDecl(/*HasPrevious*/ true); + Function->setObjectOfFriendDecl(); // Instantiate the explicit template arguments. TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), @@ -1360,13 +1385,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, // If the original function was part of a friend declaration, // inherit its namespace state and add it to the owner. if (isFriend) { - NamedDecl *PrevDecl; - if (TemplateParams) - PrevDecl = FunctionTemplate->getPreviousDecl(); - else - PrevDecl = Function->getPreviousDecl(); - - PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0); + PrincipalDecl->setObjectOfFriendDecl(); DC->makeDeclVisibleInContext(PrincipalDecl); bool queuedInstantiation = false; @@ -1441,6 +1460,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, } } + if (Function->isLocalExternDecl() && !Function->getPreviousDecl()) + DC->makeDeclVisibleInContext(PrincipalDecl); + if (Function->isOverloadedOperator() && !DC->isRecord() && PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) PrincipalDecl->setNonMemberOperator(); @@ -1502,24 +1524,6 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, return 0; QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo); - // \brief If the type of this function, after ignoring parentheses, - // is not *directly* a function type, then we're instantiating a function - // that was declared via a typedef, e.g., - // - // typedef int functype(int, int); - // functype func; - // - // In this case, we'll just go instantiate the ParmVarDecls that we - // synthesized in the method declaration. - if (!isa<FunctionProtoType>(T.IgnoreParens())) { - assert(!Params.size() && "Instantiating type could not yield parameters"); - SmallVector<QualType, 4> ParamTypes; - if (SemaRef.SubstParmTypes(D->getLocation(), D->param_begin(), - D->getNumParams(), TemplateArgs, ParamTypes, - &Params)) - return 0; - } - NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); if (QualifierLoc) { QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, @@ -1572,7 +1576,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, "inheriting constructor template in dependent context?"); Sema::InstantiatingTemplate Inst(SemaRef, Constructor->getLocation(), Inh); - if (Inst) + if (Inst.isInvalid()) return 0; Sema::ContextRAII SavedContext(SemaRef, Inh->getDeclContext()); LocalInstantiationScope LocalScope(SemaRef); @@ -1634,7 +1638,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, TemplateParams, Method); if (isFriend) { FunctionTemplate->setLexicalDeclContext(Owner); - FunctionTemplate->setObjectOfFriendDecl(true); + FunctionTemplate->setObjectOfFriendDecl(); } else if (D->isOutOfLine()) FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext()); Method->setDescribedFunctionTemplate(FunctionTemplate); @@ -1661,7 +1665,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, TempParamLists.data()); Method->setLexicalDeclContext(Owner); - Method->setObjectOfFriendDecl(true); + Method->setObjectOfFriendDecl(); } else if (D->isOutOfLine()) Method->setLexicalDeclContext(D->getLexicalDeclContext()); @@ -1750,7 +1754,7 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) { return VisitCXXMethodDecl(D); } -ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { +Decl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0, None, /*ExpectParameterPack=*/ false); } @@ -1769,8 +1773,13 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( D->isParameterPack()); Inst->setAccess(AS_public); - if (D->hasDefaultArgument()) - Inst->setDefaultArgument(D->getDefaultArgumentInfo(), false); + if (D->hasDefaultArgument()) { + TypeSourceInfo *InstantiatedDefaultArg = + SemaRef.SubstType(D->getDefaultArgumentInfo(), TemplateArgs, + D->getDefaultArgumentLoc(), D->getDeclName()); + if (InstantiatedDefaultArg) + Inst->setDefaultArgument(InstantiatedDefaultArg, false); + } // Introduce this template parameter's instantiation into the instantiation // scope. @@ -1920,7 +1929,11 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( if (Invalid) Param->setInvalidDecl(); - Param->setDefaultArgument(D->getDefaultArgument(), false); + if (D->hasDefaultArgument()) { + ExprResult Value = SemaRef.SubstExpr(D->getDefaultArgument(), TemplateArgs); + if (!Value.isInvalid()) + Param->setDefaultArgument(Value.get(), false); + } // Introduce this template parameter's instantiation into the instantiation // scope. @@ -2043,7 +2056,21 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( D->getPosition(), D->isParameterPack(), D->getIdentifier(), InstParams); - Param->setDefaultArgument(D->getDefaultArgument(), false); + if (D->hasDefaultArgument()) { + NestedNameSpecifierLoc QualifierLoc = + D->getDefaultArgument().getTemplateQualifierLoc(); + QualifierLoc = + SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgs); + TemplateName TName = SemaRef.SubstTemplateName( + QualifierLoc, D->getDefaultArgument().getArgument().getAsTemplate(), + D->getDefaultArgument().getTemplateNameLoc(), TemplateArgs); + if (!TName.isNull()) + Param->setDefaultArgument( + TemplateArgumentLoc(TemplateArgument(TName), + D->getDefaultArgument().getTemplateQualifierLoc(), + D->getDefaultArgument().getTemplateNameLoc()), + false); + } Param->setAccess(AS_public); // Introduce this template parameter's instantiation into the instantiation @@ -2102,10 +2129,10 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { Sema::ForRedeclaration); UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner, - D->getUsingLocation(), + D->getUsingLoc(), QualifierLoc, NameInfo, - D->isTypeName()); + D->hasTypename()); CXXScopeSpec SS; SS.Adopt(QualifierLoc); @@ -2114,15 +2141,15 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { SemaRef.LookupQualifiedName(Prev, Owner); // Check for invalid redeclarations. - if (SemaRef.CheckUsingDeclRedeclaration(D->getUsingLocation(), - D->isTypeName(), SS, + if (SemaRef.CheckUsingDeclRedeclaration(D->getUsingLoc(), + D->hasTypename(), SS, D->getLocation(), Prev)) NewUD->setInvalidDecl(); } if (!NewUD->isInvalidDecl() && - SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS, + SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), SS, D->getLocation())) NewUD->setInvalidDecl(); @@ -2147,19 +2174,22 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { I != E; ++I) { UsingShadowDecl *Shadow = *I; NamedDecl *InstTarget = - cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl( - Shadow->getLocation(), - Shadow->getTargetDecl(), - TemplateArgs)); + cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl( + Shadow->getLocation(), Shadow->getTargetDecl(), TemplateArgs)); if (!InstTarget) return 0; - if (CheckRedeclaration && - SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev)) - continue; + UsingShadowDecl *PrevDecl = 0; + if (CheckRedeclaration) { + if (SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev, PrevDecl)) + continue; + } else if (UsingShadowDecl *OldPrev = Shadow->getPreviousDecl()) { + PrevDecl = cast_or_null<UsingShadowDecl>(SemaRef.FindInstantiatedDecl( + Shadow->getLocation(), OldPrev, TemplateArgs)); + } - UsingShadowDecl *InstShadow - = SemaRef.BuildUsingShadowDecl(/*Scope*/ 0, NewUD, InstTarget); + UsingShadowDecl *InstShadow = + SemaRef.BuildUsingShadowDecl(/*Scope*/0, NewUD, InstTarget, PrevDecl); SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow); if (isFunctionScope) @@ -2257,13 +2287,13 @@ Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl( Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl( OMPThreadPrivateDecl *D) { - SmallVector<DeclRefExpr *, 5> Vars; - for (ArrayRef<DeclRefExpr *>::iterator I = D->varlist_begin(), - E = D->varlist_end(); + SmallVector<Expr *, 5> Vars; + for (ArrayRef<Expr *>::iterator I = D->varlist_begin(), + E = D->varlist_end(); I != E; ++I) { Expr *Var = SemaRef.SubstExpr(*I, TemplateArgs).take(); assert(isa<DeclRefExpr>(Var) && "threadprivate arg is not a DeclRefExpr"); - Vars.push_back(cast<DeclRefExpr>(Var)); + Vars.push_back(Var); } OMPThreadPrivateDecl *TD = @@ -2272,6 +2302,262 @@ Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl( return TD; } +Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) { + return VisitFunctionDecl(D, 0); +} + +Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) { + return VisitCXXMethodDecl(D, 0); +} + +Decl *TemplateDeclInstantiator::VisitRecordDecl(RecordDecl *D) { + llvm_unreachable("There are only CXXRecordDecls in C++"); +} + +Decl * +TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( + ClassTemplateSpecializationDecl *D) { + // As a MS extension, we permit class-scope explicit specialization + // of member class templates. + ClassTemplateDecl *ClassTemplate = D->getSpecializedTemplate(); + assert(ClassTemplate->getDeclContext()->isRecord() && + D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization && + "can only instantiate an explicit specialization " + "for a member class template"); + + // Lookup the already-instantiated declaration in the instantiation + // of the class template. FIXME: Diagnose or assert if this fails? + DeclContext::lookup_result Found + = Owner->lookup(ClassTemplate->getDeclName()); + if (Found.empty()) + return 0; + ClassTemplateDecl *InstClassTemplate + = dyn_cast<ClassTemplateDecl>(Found.front()); + if (!InstClassTemplate) + return 0; + + // Substitute into the template arguments of the class template explicit + // specialization. + TemplateSpecializationTypeLoc Loc = D->getTypeAsWritten()->getTypeLoc(). + castAs<TemplateSpecializationTypeLoc>(); + TemplateArgumentListInfo InstTemplateArgs(Loc.getLAngleLoc(), + Loc.getRAngleLoc()); + SmallVector<TemplateArgumentLoc, 4> ArgLocs; + for (unsigned I = 0; I != Loc.getNumArgs(); ++I) + ArgLocs.push_back(Loc.getArgLoc(I)); + if (SemaRef.Subst(ArgLocs.data(), ArgLocs.size(), + InstTemplateArgs, TemplateArgs)) + return 0; + + // Check that the template argument list is well-formed for this + // class template. + SmallVector<TemplateArgument, 4> Converted; + if (SemaRef.CheckTemplateArgumentList(InstClassTemplate, + D->getLocation(), + InstTemplateArgs, + false, + Converted)) + return 0; + + // Figure out where to insert this class template explicit specialization + // in the member template's set of class template explicit specializations. + void *InsertPos = 0; + ClassTemplateSpecializationDecl *PrevDecl = + InstClassTemplate->findSpecialization(Converted.data(), Converted.size(), + InsertPos); + + // Check whether we've already seen a conflicting instantiation of this + // declaration (for instance, if there was a prior implicit instantiation). + bool Ignored; + if (PrevDecl && + SemaRef.CheckSpecializationInstantiationRedecl(D->getLocation(), + D->getSpecializationKind(), + PrevDecl, + PrevDecl->getSpecializationKind(), + PrevDecl->getPointOfInstantiation(), + Ignored)) + return 0; + + // If PrevDecl was a definition and D is also a definition, diagnose. + // This happens in cases like: + // + // template<typename T, typename U> + // struct Outer { + // template<typename X> struct Inner; + // template<> struct Inner<T> {}; + // template<> struct Inner<U> {}; + // }; + // + // Outer<int, int> outer; // error: the explicit specializations of Inner + // // have the same signature. + if (PrevDecl && PrevDecl->getDefinition() && + D->isThisDeclarationADefinition()) { + SemaRef.Diag(D->getLocation(), diag::err_redefinition) << PrevDecl; + SemaRef.Diag(PrevDecl->getDefinition()->getLocation(), + diag::note_previous_definition); + return 0; + } + + // Create the class template partial specialization declaration. + ClassTemplateSpecializationDecl *InstD + = ClassTemplateSpecializationDecl::Create(SemaRef.Context, + D->getTagKind(), + Owner, + D->getLocStart(), + D->getLocation(), + InstClassTemplate, + Converted.data(), + Converted.size(), + PrevDecl); + + // Add this partial specialization to the set of class template partial + // specializations. + if (!PrevDecl) + InstClassTemplate->AddSpecialization(InstD, InsertPos); + + // Substitute the nested name specifier, if any. + if (SubstQualifier(D, InstD)) + return 0; + + // Build the canonical type that describes the converted template + // arguments of the class template explicit specialization. + QualType CanonType = SemaRef.Context.getTemplateSpecializationType( + TemplateName(InstClassTemplate), Converted.data(), Converted.size(), + SemaRef.Context.getRecordType(InstD)); + + // Build the fully-sugared type for this class template + // specialization as the user wrote in the specialization + // itself. This means that we'll pretty-print the type retrieved + // from the specialization's declaration the way that the user + // actually wrote the specialization, rather than formatting the + // name based on the "canonical" representation used to store the + // template arguments in the specialization. + TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo( + TemplateName(InstClassTemplate), D->getLocation(), InstTemplateArgs, + CanonType); + + InstD->setAccess(D->getAccess()); + InstD->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation); + InstD->setSpecializationKind(D->getSpecializationKind()); + InstD->setTypeAsWritten(WrittenTy); + InstD->setExternLoc(D->getExternLoc()); + InstD->setTemplateKeywordLoc(D->getTemplateKeywordLoc()); + + Owner->addDecl(InstD); + + // Instantiate the members of the class-scope explicit specialization eagerly. + // We don't have support for lazy instantiation of an explicit specialization + // yet, and MSVC eagerly instantiates in this case. + if (D->isThisDeclarationADefinition() && + SemaRef.InstantiateClass(D->getLocation(), InstD, D, TemplateArgs, + TSK_ImplicitInstantiation, + /*Complain=*/true)) + return 0; + + return InstD; +} + +Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( + VarTemplateSpecializationDecl *D) { + + TemplateArgumentListInfo VarTemplateArgsInfo; + VarTemplateDecl *VarTemplate = D->getSpecializedTemplate(); + assert(VarTemplate && + "A template specialization without specialized template?"); + + // Substitute the current template arguments. + const TemplateArgumentListInfo &TemplateArgsInfo = D->getTemplateArgsInfo(); + VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo.getLAngleLoc()); + VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo.getRAngleLoc()); + + if (SemaRef.Subst(TemplateArgsInfo.getArgumentArray(), + TemplateArgsInfo.size(), VarTemplateArgsInfo, TemplateArgs)) + return 0; + + // Check that the template argument list is well-formed for this template. + SmallVector<TemplateArgument, 4> Converted; + bool ExpansionIntoFixedList = false; + if (SemaRef.CheckTemplateArgumentList( + VarTemplate, VarTemplate->getLocStart(), + const_cast<TemplateArgumentListInfo &>(VarTemplateArgsInfo), false, + Converted, &ExpansionIntoFixedList)) + return 0; + + // Find the variable template specialization declaration that + // corresponds to these arguments. + void *InsertPos = 0; + if (VarTemplateSpecializationDecl *VarSpec = VarTemplate->findSpecialization( + Converted.data(), Converted.size(), InsertPos)) + // If we already have a variable template specialization, return it. + return VarSpec; + + return VisitVarTemplateSpecializationDecl(VarTemplate, D, InsertPos, + VarTemplateArgsInfo, Converted); +} + +Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( + VarTemplateDecl *VarTemplate, VarDecl *D, void *InsertPos, + const TemplateArgumentListInfo &TemplateArgsInfo, + llvm::ArrayRef<TemplateArgument> Converted) { + + // If this is the variable for an anonymous struct or union, + // instantiate the anonymous struct/union type first. + if (const RecordType *RecordTy = D->getType()->getAs<RecordType>()) + if (RecordTy->getDecl()->isAnonymousStructOrUnion()) + if (!VisitCXXRecordDecl(cast<CXXRecordDecl>(RecordTy->getDecl()))) + return 0; + + // Do substitution on the type of the declaration + TypeSourceInfo *DI = + SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs, + D->getTypeSpecStartLoc(), D->getDeclName()); + if (!DI) + return 0; + + if (DI->getType()->isFunctionType()) { + SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function) + << D->isStaticDataMember() << DI->getType(); + return 0; + } + + // Build the instantiated declaration + VarTemplateSpecializationDecl *Var = VarTemplateSpecializationDecl::Create( + SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), + VarTemplate, DI->getType(), DI, D->getStorageClass(), Converted.data(), + Converted.size()); + Var->setTemplateArgsInfo(TemplateArgsInfo); + if (InsertPos) + VarTemplate->AddSpecialization(Var, InsertPos); + + // Substitute the nested name specifier, if any. + if (SubstQualifier(D, Var)) + return 0; + + SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, + Owner, StartingScope); + + return Var; +} + +Decl *TemplateDeclInstantiator::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) { + llvm_unreachable("@defs is not supported in Objective-C++"); +} + +Decl *TemplateDeclInstantiator::VisitFriendTemplateDecl(FriendTemplateDecl *D) { + // FIXME: We need to be able to instantiate FriendTemplateDecls. + unsigned DiagID = SemaRef.getDiagnostics().getCustomDiagID( + DiagnosticsEngine::Error, + "cannot instantiate %0 yet"); + SemaRef.Diag(D->getLocation(), DiagID) + << D->getDeclKindName(); + + return 0; +} + +Decl *TemplateDeclInstantiator::VisitDecl(Decl *D) { + llvm_unreachable("Unexpected decl"); +} + Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner, const MultiLevelTemplateArgumentList &TemplateArgs) { TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs); @@ -2343,9 +2629,12 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( // Substitute into the template arguments of the class template partial // specialization. - TemplateArgumentListInfo InstTemplateArgs; // no angle locations - if (SemaRef.Subst(PartialSpec->getTemplateArgsAsWritten(), - PartialSpec->getNumTemplateArgsAsWritten(), + const ASTTemplateArgumentListInfo *TemplArgInfo + = PartialSpec->getTemplateArgsAsWritten(); + TemplateArgumentListInfo InstTemplateArgs(TemplArgInfo->LAngleLoc, + TemplArgInfo->RAngleLoc); + if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(), + TemplArgInfo->NumTemplateArgs, InstTemplateArgs, TemplateArgs)) return 0; @@ -2424,8 +2713,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( Converted.size(), InstTemplateArgs, CanonType, - 0, - ClassTemplate->getNextPartialSpecSequenceNumber()); + 0); // Substitute the nested name specifier, if any. if (SubstQualifier(PartialSpec, InstPartialSpec)) return 0; @@ -2439,6 +2727,137 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( return InstPartialSpec; } +/// \brief Instantiate the declaration of a variable template partial +/// specialization. +/// +/// \param VarTemplate the (instantiated) variable template that is partially +/// specialized by the instantiation of \p PartialSpec. +/// +/// \param PartialSpec the (uninstantiated) variable template partial +/// specialization that we are instantiating. +/// +/// \returns The instantiated partial specialization, if successful; otherwise, +/// NULL to indicate an error. +VarTemplatePartialSpecializationDecl * +TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization( + VarTemplateDecl *VarTemplate, + VarTemplatePartialSpecializationDecl *PartialSpec) { + // Create a local instantiation scope for this variable template partial + // specialization, which will contain the instantiations of the template + // parameters. + LocalInstantiationScope Scope(SemaRef); + + // Substitute into the template parameters of the variable template partial + // specialization. + TemplateParameterList *TempParams = PartialSpec->getTemplateParameters(); + TemplateParameterList *InstParams = SubstTemplateParams(TempParams); + if (!InstParams) + return 0; + + // Substitute into the template arguments of the variable template partial + // specialization. + const ASTTemplateArgumentListInfo *TemplArgInfo + = PartialSpec->getTemplateArgsAsWritten(); + TemplateArgumentListInfo InstTemplateArgs(TemplArgInfo->LAngleLoc, + TemplArgInfo->RAngleLoc); + if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(), + TemplArgInfo->NumTemplateArgs, + InstTemplateArgs, TemplateArgs)) + return 0; + + // Check that the template argument list is well-formed for this + // class template. + SmallVector<TemplateArgument, 4> Converted; + if (SemaRef.CheckTemplateArgumentList(VarTemplate, PartialSpec->getLocation(), + InstTemplateArgs, false, Converted)) + return 0; + + // Figure out where to insert this variable template partial specialization + // in the member template's set of variable template partial specializations. + void *InsertPos = 0; + VarTemplateSpecializationDecl *PrevDecl = + VarTemplate->findPartialSpecialization(Converted.data(), Converted.size(), + InsertPos); + + // Build the canonical type that describes the converted template + // arguments of the variable template partial specialization. + QualType CanonType = SemaRef.Context.getTemplateSpecializationType( + TemplateName(VarTemplate), Converted.data(), Converted.size()); + + // Build the fully-sugared type for this variable template + // specialization as the user wrote in the specialization + // itself. This means that we'll pretty-print the type retrieved + // from the specialization's declaration the way that the user + // actually wrote the specialization, rather than formatting the + // name based on the "canonical" representation used to store the + // template arguments in the specialization. + TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo( + TemplateName(VarTemplate), PartialSpec->getLocation(), InstTemplateArgs, + CanonType); + + if (PrevDecl) { + // We've already seen a partial specialization with the same template + // parameters and template arguments. This can happen, for example, when + // substituting the outer template arguments ends up causing two + // variable template partial specializations of a member variable template + // to have identical forms, e.g., + // + // template<typename T, typename U> + // struct Outer { + // template<typename X, typename Y> pair<X,Y> p; + // template<typename Y> pair<T, Y> p; + // template<typename Y> pair<U, Y> p; + // }; + // + // Outer<int, int> outer; // error: the partial specializations of Inner + // // have the same signature. + SemaRef.Diag(PartialSpec->getLocation(), + diag::err_var_partial_spec_redeclared) + << WrittenTy->getType(); + SemaRef.Diag(PrevDecl->getLocation(), + diag::note_var_prev_partial_spec_here); + return 0; + } + + // Do substitution on the type of the declaration + TypeSourceInfo *DI = SemaRef.SubstType( + PartialSpec->getTypeSourceInfo(), TemplateArgs, + PartialSpec->getTypeSpecStartLoc(), PartialSpec->getDeclName()); + if (!DI) + return 0; + + if (DI->getType()->isFunctionType()) { + SemaRef.Diag(PartialSpec->getLocation(), + diag::err_variable_instantiates_to_function) + << PartialSpec->isStaticDataMember() << DI->getType(); + return 0; + } + + // Create the variable template partial specialization declaration. + VarTemplatePartialSpecializationDecl *InstPartialSpec = + VarTemplatePartialSpecializationDecl::Create( + SemaRef.Context, Owner, PartialSpec->getInnerLocStart(), + PartialSpec->getLocation(), InstParams, VarTemplate, DI->getType(), + DI, PartialSpec->getStorageClass(), Converted.data(), + Converted.size(), InstTemplateArgs); + + // Substitute the nested name specifier, if any. + if (SubstQualifier(PartialSpec, InstPartialSpec)) + return 0; + + InstPartialSpec->setInstantiatedFromMember(PartialSpec); + InstPartialSpec->setTypeAsWritten(WrittenTy); + + // Add this partial specialization to the set of variable template partial + // specializations. The instantiation of the initializer is not necessary. + VarTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/0); + + SemaRef.BuildVariableInstantiation(InstPartialSpec, PartialSpec, TemplateArgs, + LateAttrs, Owner, StartingScope); + + return InstPartialSpec; +} + TypeSourceInfo* TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, SmallVectorImpl<ParmVarDecl *> &Params) { @@ -2449,7 +2868,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, CXXRecordDecl *ThisContext = 0; unsigned ThisTypeQuals = 0; if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { - ThisContext = Method->getParent(); + ThisContext = cast<CXXRecordDecl>(Owner); ThisTypeQuals = Method->getTypeQualifiers(); } @@ -2461,11 +2880,10 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, if (!NewTInfo) return 0; - if (NewTInfo != OldTInfo) { - // Get parameters from the new type info. - TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens(); - if (FunctionProtoTypeLoc OldProtoLoc = - OldTL.getAs<FunctionProtoTypeLoc>()) { + TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens(); + if (FunctionProtoTypeLoc OldProtoLoc = OldTL.getAs<FunctionProtoTypeLoc>()) { + if (NewTInfo != OldTInfo) { + // Get parameters from the new type info. TypeLoc NewTL = NewTInfo->getTypeLoc().IgnoreParens(); FunctionProtoTypeLoc NewProtoLoc = NewTL.castAs<FunctionProtoTypeLoc>(); unsigned NewIdx = 0; @@ -2495,22 +2913,45 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, } } } - } - } else { - // The function type itself was not dependent and therefore no - // substitution occurred. However, we still need to instantiate - // the function parameters themselves. - TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens(); - if (FunctionProtoTypeLoc OldProtoLoc = - OldTL.getAs<FunctionProtoTypeLoc>()) { + } else { + // The function type itself was not dependent and therefore no + // substitution occurred. However, we still need to instantiate + // the function parameters themselves. + const FunctionProtoType *OldProto = + cast<FunctionProtoType>(OldProtoLoc.getType()); for (unsigned i = 0, i_end = OldProtoLoc.getNumArgs(); i != i_end; ++i) { - ParmVarDecl *Parm = VisitParmVarDecl(OldProtoLoc.getArg(i)); + ParmVarDecl *OldParam = OldProtoLoc.getArg(i); + if (!OldParam) { + Params.push_back(SemaRef.BuildParmVarDeclForTypedef( + D, D->getLocation(), OldProto->getArgType(i))); + continue; + } + + ParmVarDecl *Parm = + cast_or_null<ParmVarDecl>(VisitParmVarDecl(OldParam)); if (!Parm) return 0; Params.push_back(Parm); } } + } else { + // If the type of this function, after ignoring parentheses, is not + // *directly* a function type, then we're instantiating a function that + // was declared via a typedef or with attributes, e.g., + // + // typedef int functype(int, int); + // functype func; + // int __cdecl meth(int, int); + // + // In this case, we'll just go instantiate the ParmVarDecls that we + // synthesized in the method declaration. + SmallVector<QualType, 4> ParamTypes; + if (SemaRef.SubstParmTypes(D->getLocation(), D->param_begin(), + D->getNumParams(), TemplateArgs, ParamTypes, + &Params)) + return 0; } + return NewTInfo; } @@ -2585,8 +3026,7 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New, bool Expand = false; bool RetainExpansion = false; - Optional<unsigned> NumExpansions - = PackExpansion->getNumExpansions(); + Optional<unsigned> NumExpansions = PackExpansion->getNumExpansions(); if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(), SourceRange(), Unexpanded, @@ -2674,9 +3114,7 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New, EPI.NoexceptExpr = NoexceptExpr; New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(), - ArrayRef<QualType>(NewProto->arg_type_begin(), - NewProto->getNumArgs()), - EPI)); + NewProto->getArgTypes(), EPI)); } void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, @@ -2687,15 +3125,13 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, InstantiatingTemplate Inst(*this, PointOfInstantiation, Decl, InstantiatingTemplate::ExceptionSpecification()); - if (Inst) { + if (Inst.isInvalid()) { // We hit the instantiation depth limit. Clear the exception specification // so that our callers don't have to cope with EST_Uninstantiated. FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); EPI.ExceptionSpecType = EST_None; Decl->setType(Context.getFunctionType(Proto->getResultType(), - ArrayRef<QualType>(Proto->arg_type_begin(), - Proto->getNumArgs()), - EPI)); + Proto->getArgTypes(), EPI)); return; } @@ -2774,10 +3210,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, EPI.ExceptionSpecType = NewEST; EPI.ExceptionSpecDecl = New; EPI.ExceptionSpecTemplate = ExceptionSpecTemplate; - New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(), - ArrayRef<QualType>(NewProto->arg_type_begin(), - NewProto->getNumArgs()), - EPI)); + New->setType(SemaRef.Context.getFunctionType( + NewProto->getResultType(), NewProto->getArgTypes(), EPI)); } else { ::InstantiateExceptionSpec(SemaRef, New, Proto, TemplateArgs); } @@ -2862,11 +3296,17 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, return; } - // Call the LateTemplateParser callback if there a need to late parse + // Call the LateTemplateParser callback if there is a need to late parse // a templated function definition. if (!Pattern && PatternDecl->isLateTemplateParsed() && LateTemplateParser) { - LateTemplateParser(OpaqueParser, PatternDecl); + // FIXME: Optimize to allow individual templates to be deserialized. + if (PatternDecl->isFromASTFile()) + ExternalSource->ReadLateParsedTemplates(LateParsedTemplateMap); + + LateParsedTemplate *LPT = LateParsedTemplateMap.lookup(PatternDecl); + assert(LPT && "missing LateParsedTemplate"); + LateTemplateParser(OpaqueParser, *LPT); Pattern = PatternDecl->getBody(PatternDecl); } @@ -2902,14 +3342,14 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, if (Function->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDeclaration && !PatternDecl->isInlined() && - !PatternDecl->getResultType()->isUndeducedType()) + !PatternDecl->getResultType()->getContainedAutoType()) return; if (PatternDecl->isInlined()) Function->setImplicitlyInline(); InstantiatingTemplate Inst(*this, PointOfInstantiation, Function); - if (Inst) + if (Inst.isInvalid()) return; // Copy the inner loc start from the pattern. @@ -2920,6 +3360,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // while we're still within our own instantiation context. SmallVector<VTableUse, 16> SavedVTableUses; std::deque<PendingImplicitInstantiation> SavedPendingInstantiations; + SavePendingLocalImplicitInstantiationsRAII + SavedPendingLocalImplicitInstantiations(*this); if (Recursive) { VTableUses.swap(SavedVTableUses); PendingInstantiations.swap(SavedPendingInstantiations); @@ -3002,6 +3444,202 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, } } +VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( + VarTemplateDecl *VarTemplate, VarDecl *FromVar, + const TemplateArgumentList &TemplateArgList, + const TemplateArgumentListInfo &TemplateArgsInfo, + SmallVectorImpl<TemplateArgument> &Converted, + SourceLocation PointOfInstantiation, void *InsertPos, + LateInstantiatedAttrVec *LateAttrs, + LocalInstantiationScope *StartingScope) { + if (FromVar->isInvalidDecl()) + return 0; + + InstantiatingTemplate Inst(*this, PointOfInstantiation, FromVar); + if (Inst.isInvalid()) + return 0; + + MultiLevelTemplateArgumentList TemplateArgLists; + TemplateArgLists.addOuterTemplateArguments(&TemplateArgList); + + // Instantiate the first declaration of the variable template: for a partial + // specialization of a static data member template, the first declaration may + // or may not be the declaration in the class; if it's in the class, we want + // to instantiate a member in the class (a declaration), and if it's outside, + // we want to instantiate a definition. + FromVar = FromVar->getFirstDecl(); + + MultiLevelTemplateArgumentList MultiLevelList(TemplateArgList); + TemplateDeclInstantiator Instantiator(*this, FromVar->getDeclContext(), + MultiLevelList); + + // TODO: Set LateAttrs and StartingScope ... + + return cast_or_null<VarTemplateSpecializationDecl>( + Instantiator.VisitVarTemplateSpecializationDecl( + VarTemplate, FromVar, InsertPos, TemplateArgsInfo, Converted)); +} + +/// \brief Instantiates a variable template specialization by completing it +/// with appropriate type information and initializer. +VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl( + VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl, + const MultiLevelTemplateArgumentList &TemplateArgs) { + + // Do substitution on the type of the declaration + TypeSourceInfo *DI = + SubstType(PatternDecl->getTypeSourceInfo(), TemplateArgs, + PatternDecl->getTypeSpecStartLoc(), PatternDecl->getDeclName()); + if (!DI) + return 0; + + // Update the type of this variable template specialization. + VarSpec->setType(DI->getType()); + + // Instantiate the initializer. + InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs); + + return VarSpec; +} + +/// BuildVariableInstantiation - Used after a new variable has been created. +/// Sets basic variable data and decides whether to postpone the +/// variable instantiation. +void Sema::BuildVariableInstantiation( + VarDecl *NewVar, VarDecl *OldVar, + const MultiLevelTemplateArgumentList &TemplateArgs, + LateInstantiatedAttrVec *LateAttrs, DeclContext *Owner, + LocalInstantiationScope *StartingScope, + bool InstantiatingVarTemplate) { + + // If we are instantiating a local extern declaration, the + // instantiation belongs lexically to the containing function. + // If we are instantiating a static data member defined + // out-of-line, the instantiation will have the same lexical + // context (which will be a namespace scope) as the template. + if (OldVar->isLocalExternDecl()) { + NewVar->setLocalExternDecl(); + NewVar->setLexicalDeclContext(Owner); + } else if (OldVar->isOutOfLine()) + NewVar->setLexicalDeclContext(OldVar->getLexicalDeclContext()); + NewVar->setTSCSpec(OldVar->getTSCSpec()); + NewVar->setInitStyle(OldVar->getInitStyle()); + NewVar->setCXXForRangeDecl(OldVar->isCXXForRangeDecl()); + NewVar->setConstexpr(OldVar->isConstexpr()); + NewVar->setInitCapture(OldVar->isInitCapture()); + NewVar->setPreviousDeclInSameBlockScope( + OldVar->isPreviousDeclInSameBlockScope()); + NewVar->setAccess(OldVar->getAccess()); + + if (!OldVar->isStaticDataMember()) { + if (OldVar->isUsed(false)) + NewVar->setIsUsed(); + NewVar->setReferenced(OldVar->isReferenced()); + } + + // See if the old variable had a type-specifier that defined an anonymous tag. + // If it did, mark the new variable as being the declarator for the new + // anonymous tag. + if (const TagType *OldTagType = OldVar->getType()->getAs<TagType>()) { + TagDecl *OldTag = OldTagType->getDecl(); + if (OldTag->getDeclaratorForAnonDecl() == OldVar) { + TagDecl *NewTag = NewVar->getType()->castAs<TagType>()->getDecl(); + assert(!NewTag->hasNameForLinkage() && + !NewTag->hasDeclaratorForAnonDecl()); + NewTag->setDeclaratorForAnonDecl(NewVar); + } + } + + InstantiateAttrs(TemplateArgs, OldVar, NewVar, LateAttrs, StartingScope); + + if (NewVar->hasAttrs()) + CheckAlignasUnderalignment(NewVar); + + LookupResult Previous( + *this, NewVar->getDeclName(), NewVar->getLocation(), + NewVar->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage + : Sema::LookupOrdinaryName, + Sema::ForRedeclaration); + + if (NewVar->isLocalExternDecl() && OldVar->getPreviousDecl()) { + // We have a previous declaration. Use that one, so we merge with the + // right type. + if (NamedDecl *NewPrev = FindInstantiatedDecl( + NewVar->getLocation(), OldVar->getPreviousDecl(), TemplateArgs)) + Previous.addDecl(NewPrev); + } else if (!isa<VarTemplateSpecializationDecl>(NewVar) && + OldVar->hasLinkage()) + LookupQualifiedName(Previous, NewVar->getDeclContext(), false); + CheckVariableDeclaration(NewVar, Previous); + + if (!InstantiatingVarTemplate) { + NewVar->getLexicalDeclContext()->addHiddenDecl(NewVar); + if (!NewVar->isLocalExternDecl() || !NewVar->getPreviousDecl()) + NewVar->getDeclContext()->makeDeclVisibleInContext(NewVar); + } + + if (!OldVar->isOutOfLine()) { + if (NewVar->getDeclContext()->isFunctionOrMethod()) + CurrentInstantiationScope->InstantiatedLocal(OldVar, NewVar); + } + + // Link instantiations of static data members back to the template from + // which they were instantiated. + if (NewVar->isStaticDataMember() && !InstantiatingVarTemplate) + NewVar->setInstantiationOfStaticDataMember(OldVar, + TSK_ImplicitInstantiation); + + // Delay instantiation of the initializer for variable templates until a + // definition of the variable is needed. + if (!isa<VarTemplateSpecializationDecl>(NewVar) && !InstantiatingVarTemplate) + InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs); + + // Diagnose unused local variables with dependent types, where the diagnostic + // will have been deferred. + if (!NewVar->isInvalidDecl() && + NewVar->getDeclContext()->isFunctionOrMethod() && !NewVar->isUsed() && + OldVar->getType()->isDependentType()) + DiagnoseUnusedDecl(NewVar); +} + +/// \brief Instantiate the initializer of a variable. +void Sema::InstantiateVariableInitializer( + VarDecl *Var, VarDecl *OldVar, + const MultiLevelTemplateArgumentList &TemplateArgs) { + + if (Var->getAnyInitializer()) + // We already have an initializer in the class. + return; + + if (OldVar->getInit()) { + if (Var->isStaticDataMember() && !OldVar->isOutOfLine()) + PushExpressionEvaluationContext(Sema::ConstantEvaluated, OldVar); + else + PushExpressionEvaluationContext(Sema::PotentiallyEvaluated, OldVar); + + // Instantiate the initializer. + ExprResult Init = + SubstInitializer(OldVar->getInit(), TemplateArgs, + OldVar->getInitStyle() == VarDecl::CallInit); + if (!Init.isInvalid()) { + bool TypeMayContainAuto = true; + if (Init.get()) { + bool DirectInit = OldVar->isDirectInit(); + AddInitializerToDecl(Var, Init.take(), DirectInit, TypeMayContainAuto); + } else + ActOnUninitializedDecl(Var, TypeMayContainAuto); + } else { + // FIXME: Not too happy about invalidating the declaration + // because of a bogus initializer. + Var->setInvalidDecl(); + } + + PopExpressionEvaluationContext(); + } else if ((!Var->isStaticDataMember() || Var->isOutOfLine()) && + !Var->isCXXForRangeDecl()) + ActOnUninitializedDecl(Var, false); +} + /// \brief Instantiate the definition of the given variable from its /// template. /// @@ -3023,26 +3661,151 @@ void Sema::InstantiateStaticDataMemberDefinition( VarDecl *Var, bool Recursive, bool DefinitionRequired) { + InstantiateVariableDefinition(PointOfInstantiation, Var, Recursive, + DefinitionRequired); +} + +void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, + VarDecl *Var, bool Recursive, + bool DefinitionRequired) { if (Var->isInvalidDecl()) return; - // Find the out-of-line definition of this static data member. - VarDecl *Def = Var->getInstantiatedFromStaticDataMember(); - assert(Def && "This data member was not instantiated from a template?"); - assert(Def->isStaticDataMember() && "Not a static data member?"); - Def = Def->getOutOfLineDefinition(); + VarTemplateSpecializationDecl *VarSpec = + dyn_cast<VarTemplateSpecializationDecl>(Var); + VarDecl *PatternDecl = 0, *Def = 0; + MultiLevelTemplateArgumentList TemplateArgs = + getTemplateInstantiationArgs(Var); + + if (VarSpec) { + // If this is a variable template specialization, make sure that it is + // non-dependent, then find its instantiation pattern. + bool InstantiationDependent = false; + assert(!TemplateSpecializationType::anyDependentTemplateArguments( + VarSpec->getTemplateArgsInfo(), InstantiationDependent) && + "Only instantiate variable template specializations that are " + "not type-dependent"); + (void)InstantiationDependent; + + // Find the variable initialization that we'll be substituting. If the + // pattern was instantiated from a member template, look back further to + // find the real pattern. + assert(VarSpec->getSpecializedTemplate() && + "Specialization without specialized template?"); + llvm::PointerUnion<VarTemplateDecl *, + VarTemplatePartialSpecializationDecl *> PatternPtr = + VarSpec->getSpecializedTemplateOrPartial(); + if (PatternPtr.is<VarTemplatePartialSpecializationDecl *>()) { + VarTemplatePartialSpecializationDecl *Tmpl = + PatternPtr.get<VarTemplatePartialSpecializationDecl *>(); + while (VarTemplatePartialSpecializationDecl *From = + Tmpl->getInstantiatedFromMember()) { + if (Tmpl->isMemberSpecialization()) + break; + + Tmpl = From; + } + PatternDecl = Tmpl; + } else { + VarTemplateDecl *Tmpl = PatternPtr.get<VarTemplateDecl *>(); + while (VarTemplateDecl *From = + Tmpl->getInstantiatedFromMemberTemplate()) { + if (Tmpl->isMemberSpecialization()) + break; + + Tmpl = From; + } + PatternDecl = Tmpl->getTemplatedDecl(); + } + + // If this is a static data member template, there might be an + // uninstantiated initializer on the declaration. If so, instantiate + // it now. + if (PatternDecl->isStaticDataMember() && + (PatternDecl = PatternDecl->getFirstDecl())->hasInit() && + !Var->hasInit()) { + // FIXME: Factor out the duplicated instantiation context setup/tear down + // code here. + InstantiatingTemplate Inst(*this, PointOfInstantiation, Var); + if (Inst.isInvalid()) + return; + + // 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. + SmallVector<VTableUse, 16> SavedVTableUses; + std::deque<PendingImplicitInstantiation> SavedPendingInstantiations; + if (Recursive) { + VTableUses.swap(SavedVTableUses); + PendingInstantiations.swap(SavedPendingInstantiations); + } + + LocalInstantiationScope Local(*this); + + // Enter the scope of this instantiation. We don't use + // PushDeclContext because we don't have a scope. + ContextRAII PreviousContext(*this, Var->getDeclContext()); + InstantiateVariableInitializer(Var, PatternDecl, TemplateArgs); + PreviousContext.pop(); + + // FIXME: Need to inform the ASTConsumer that we instantiated the + // initializer? + // This variable may have local implicit instantiations that need to be + // instantiated within this scope. + PerformPendingInstantiations(/*LocalOnly=*/true); + + Local.Exit(); + + if (Recursive) { + // Define any newly required vtables. + DefineUsedVTables(); + + // Instantiate any pending implicit instantiations found during the + // instantiation of this template. + PerformPendingInstantiations(); + + // Restore the set of pending vtables. + assert(VTableUses.empty() && + "VTableUses should be empty before it is discarded."); + VTableUses.swap(SavedVTableUses); + + // Restore the set of pending implicit instantiations. + assert(PendingInstantiations.empty() && + "PendingInstantiations should be empty before it is discarded."); + PendingInstantiations.swap(SavedPendingInstantiations); + } + } + + // Find actual definition + Def = PatternDecl->getDefinition(getASTContext()); + } else { + // If this is a static data member, find its out-of-line definition. + assert(Var->isStaticDataMember() && "not a static data member?"); + PatternDecl = Var->getInstantiatedFromStaticDataMember(); + + assert(PatternDecl && "data member was not instantiated from a template?"); + assert(PatternDecl->isStaticDataMember() && "not a static data member?"); + Def = PatternDecl->getOutOfLineDefinition(); + } + + // If we don't have a definition of the variable template, we won't perform + // any instantiation. Rather, we rely on the user to instantiate this + // definition (or provide a specialization for it) in another translation + // unit. if (!Def) { - // We did not find an out-of-line definition of this static data member, - // so we won't perform any instantiation. Rather, we rely on the user to - // instantiate this definition (or provide a specialization for it) in - // another translation unit. if (DefinitionRequired) { - Def = Var->getInstantiatedFromStaticDataMember(); - Diag(PointOfInstantiation, - diag::err_explicit_instantiation_undefined_member) - << 2 << Var->getDeclName() << Var->getDeclContext(); - Diag(Def->getLocation(), diag::note_explicit_instantiation_here); + if (VarSpec) + Diag(PointOfInstantiation, + diag::err_explicit_instantiation_undefined_var_template) << Var; + else + Diag(PointOfInstantiation, + diag::err_explicit_instantiation_undefined_member) + << 2 << Var->getDeclName() << Var->getDeclContext(); + Diag(PatternDecl->getLocation(), + diag::note_explicit_instantiation_here); + if (VarSpec) + Var->setInvalidDecl(); } else if (Var->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition) { PendingInstantiations.push_back( @@ -3058,8 +3821,8 @@ void Sema::InstantiateStaticDataMemberDefinition( if (TSK == TSK_ExplicitSpecialization) return; - // C++0x [temp.explicit]p9: - // Except for inline functions, other explicit instantiation declarations + // C++11 [temp.explicit]p10: + // Except for inline functions, [...] explicit instantiation declarations // have the effect of suppressing the implicit instantiation of the entity // to which they refer. if (TSK == TSK_ExplicitInstantiationDeclaration) @@ -3088,7 +3851,7 @@ void Sema::InstantiateStaticDataMemberDefinition( } InstantiatingTemplate Inst(*this, PointOfInstantiation, Var); - if (Inst) + if (Inst.isInvalid()) return; // If we're performing recursive template instantiation, create our own @@ -3096,6 +3859,8 @@ void Sema::InstantiateStaticDataMemberDefinition( // while we're still within our own instantiation context. SmallVector<VTableUse, 16> SavedVTableUses; std::deque<PendingImplicitInstantiation> SavedPendingInstantiations; + SavePendingLocalImplicitInstantiationsRAII + SavedPendingLocalImplicitInstantiations(*this); if (Recursive) { VTableUses.swap(SavedVTableUses); PendingInstantiations.swap(SavedPendingInstantiations); @@ -3103,22 +3868,58 @@ 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()); + ContextRAII PreviousContext(*this, Var->getDeclContext()); LocalInstantiationScope Local(*this); - + VarDecl *OldVar = Var; - Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(), - getTemplateInstantiationArgs(Var))); + if (!VarSpec) + Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(), + TemplateArgs)); + else if (Var->isStaticDataMember() && + Var->getLexicalDeclContext()->isRecord()) { + // We need to instantiate the definition of a static data member template, + // and all we have is the in-class declaration of it. Instantiate a separate + // declaration of the definition. + TemplateDeclInstantiator Instantiator(*this, Var->getDeclContext(), + TemplateArgs); + Var = cast_or_null<VarDecl>(Instantiator.VisitVarTemplateSpecializationDecl( + VarSpec->getSpecializedTemplate(), Def, 0, + VarSpec->getTemplateArgsInfo(), VarSpec->getTemplateArgs().asArray())); + if (Var) { + llvm::PointerUnion<VarTemplateDecl *, + VarTemplatePartialSpecializationDecl *> PatternPtr = + VarSpec->getSpecializedTemplateOrPartial(); + if (VarTemplatePartialSpecializationDecl *Partial = + PatternPtr.dyn_cast<VarTemplatePartialSpecializationDecl *>()) + cast<VarTemplateSpecializationDecl>(Var)->setInstantiationOf( + Partial, &VarSpec->getTemplateInstantiationArgs()); + + // Merge the definition with the declaration. + LookupResult R(*this, Var->getDeclName(), Var->getLocation(), + LookupOrdinaryName, ForRedeclaration); + R.addDecl(OldVar); + MergeVarDecl(Var, R); + + // Attach the initializer. + InstantiateVariableInitializer(Var, Def, TemplateArgs); + } + } else + // Complete the existing variable's definition with an appropriately + // substituted type and initializer. + Var = CompleteVarTemplateSpecializationDecl(VarSpec, Def, TemplateArgs); - previousContext.pop(); + PreviousContext.pop(); if (Var) { PassToConsumerRAII.Var = Var; - MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo(); - assert(MSInfo && "Missing member specialization information?"); - Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(), - MSInfo->getPointOfInstantiation()); + Var->setTemplateSpecializationKind(OldVar->getTemplateSpecializationKind(), + OldVar->getPointOfInstantiation()); } + + // This variable may have local implicit instantiations that need to be + // instantiated within this scope. + PerformPendingInstantiations(/*LocalOnly=*/true); + Local.Exit(); if (Recursive) { @@ -3131,14 +3932,12 @@ void Sema::InstantiateStaticDataMemberDefinition( // Restore the set of pending vtables. assert(VTableUses.empty() && - "VTableUses should be empty before it is discarded, " - "while instantiating static data member."); + "VTableUses should be empty before it is discarded."); VTableUses.swap(SavedVTableUses); // Restore the set of pending implicit instantiations. assert(PendingInstantiations.empty() && - "PendingInstantiations should be empty before it is discarded, " - "while instantiating static data member."); + "PendingInstantiations should be empty before it is discarded."); PendingInstantiations.swap(SavedPendingInstantiations); } } @@ -3167,8 +3966,9 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, if (Init->isPackExpansion()) { // This is a pack expansion. We should expand it now. TypeLoc BaseTL = Init->getTypeSourceInfo()->getTypeLoc(); - SmallVector<UnexpandedParameterPack, 2> Unexpanded; + SmallVector<UnexpandedParameterPack, 4> Unexpanded; collectUnexpandedParameterPacks(BaseTL, Unexpanded); + collectUnexpandedParameterPacks(Init->getInit(), Unexpanded); bool ShouldExpand = false; bool RetainExpansion = false; Optional<unsigned> NumExpansions; @@ -3523,14 +4323,33 @@ DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC, /// template struct X<int>; /// \endcode /// -/// In the instantiation of X<int>::getKind(), we need to map the -/// EnumConstantDecl for KnownValue (which refers to -/// X<T>::\<Kind>\::KnownValue) to its instantiation -/// (X<int>::\<Kind>\::KnownValue). InstantiateCurrentDeclRef() performs -/// this mapping from within the instantiation of X<int>. +/// In the instantiation of <tt>X<int>::getKind()</tt>, we need to map the +/// \p EnumConstantDecl for \p KnownValue (which refers to +/// <tt>X<T>::<Kind>::KnownValue</tt>) to its instantiation +/// (<tt>X<int>::<Kind>::KnownValue</tt>). \p FindInstantiatedDecl performs +/// this mapping from within the instantiation of <tt>X<int></tt>. NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs) { DeclContext *ParentDC = D->getDeclContext(); + // FIXME: Parmeters of pointer to functions (y below) that are themselves + // parameters (p below) can have their ParentDC set to the translation-unit + // - thus we can not consistently check if the ParentDC of such a parameter + // is Dependent or/and a FunctionOrMethod. + // For e.g. this code, during Template argument deduction tries to + // find an instantiated decl for (T y) when the ParentDC for y is + // the translation unit. + // e.g. template <class T> void Foo(auto (*p)(T y) -> decltype(y())) {} + // float baz(float(*)()) { return 0.0; }
+ // Foo(baz); + // The better fix here is perhaps to ensure that a ParmVarDecl, by the time + // it gets here, always has a FunctionOrMethod as its ParentDC?? + // For now: + // - as long as we have a ParmVarDecl whose parent is non-dependent and + // whose type is not instantiation dependent, do nothing to the decl + // - otherwise find its instantiated decl. + if (isa<ParmVarDecl>(D) && !ParentDC->isDependentContext() && + !cast<ParmVarDecl>(D)->getType()->isInstantiationDependentType()) + return D; if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) || (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext()) || @@ -3550,6 +4369,16 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, return cast<NamedDecl>((*Found->get<DeclArgumentPack *>())[PackIdx]); } + // If we're performing a partial substitution during template argument + // deduction, we may not have values for template parameters yet. They + // just map to themselves. + if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) || + isa<TemplateTemplateParmDecl>(D)) + return D; + + if (D->isInvalidDecl()) + return 0; + // If we didn't find the decl, then we must have a label decl that hasn't // been found yet. Lazily instantiate it and return it now. assert(isa<LabelDecl>(D)); @@ -3561,6 +4390,20 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, return cast<LabelDecl>(Inst); } + // For variable template specializations, update those that are still + // type-dependent. + if (VarTemplateSpecializationDecl *VarSpec = + dyn_cast<VarTemplateSpecializationDecl>(D)) { + bool InstantiationDependent = false; + const TemplateArgumentListInfo &VarTemplateArgs = + VarSpec->getTemplateArgsInfo(); + if (TemplateSpecializationType::anyDependentTemplateArguments( + VarTemplateArgs, InstantiationDependent)) + D = cast<NamedDecl>( + SubstDecl(D, VarSpec->getDeclContext(), TemplateArgs)); + return D; + } + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) { if (!Record->isDependentContext()) return D; @@ -3573,7 +4416,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, 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; @@ -3582,7 +4425,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, // 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. @@ -3592,13 +4435,12 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, 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; } - - + // Move to the outer template scope. if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) { if (FD->getFriendObjectKind() && FD->getDeclContext()->isFileContext()){ @@ -3606,7 +4448,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, continue; } } - + DC = DC->getParent(); } @@ -3739,9 +4581,13 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { continue; } - // Instantiate static data member definitions. + // Instantiate variable definitions VarDecl *Var = cast<VarDecl>(Inst.first); - assert(Var->isStaticDataMember() && "Not a static data member?"); + + assert((Var->isStaticDataMember() || + isa<VarTemplateSpecializationDecl>(Var)) && + "Not a static data member, nor a variable template" + " specialization?"); // Don't try to instantiate declarations if the most recent redeclaration // is invalid. @@ -3764,14 +4610,15 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { break; } - PrettyDeclStackTraceEntry CrashInfo(*this, Var, Var->getLocation(), - "instantiating static data member " - "definition"); - + PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(), + "instantiating variable definition"); bool DefinitionRequired = Var->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; - InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true, - DefinitionRequired); + + // Instantiate static data member definitions or variable template + // specializations. + InstantiateVariableDefinition(/*FIXME:*/ Inst.second, Var, true, + DefinitionRequired); } } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp index db885aeec7b7..78aa7f893a1a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -18,6 +18,7 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" +#include "TypeLocBuilder.h" using namespace clang; @@ -179,10 +180,14 @@ namespace { // If any capture names a function parameter pack, that pack is expanded // when the lambda is expanded. for (LambdaExpr::capture_iterator I = Lambda->capture_begin(), - E = Lambda->capture_end(); I != E; ++I) - if (VarDecl *VD = I->getCapturedVar()) + E = Lambda->capture_end(); + I != E; ++I) { + if (I->capturesVariable()) { + VarDecl *VD = I->getCapturedVar(); if (VD->isParameterPack()) Unexpanded.push_back(std::make_pair(VD, I->getLocation())); + } + } inherited::TraverseLambdaExpr(Lambda); @@ -459,17 +464,13 @@ Sema::CheckPackExpansion(TypeSourceInfo *Pattern, SourceLocation EllipsisLoc, EllipsisLoc, NumExpansions); if (Result.isNull()) return 0; - - TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result); - PackExpansionTypeLoc TL = - TSResult->getTypeLoc().castAs<PackExpansionTypeLoc>(); + + TypeLocBuilder TLB; + TLB.pushFullCopy(Pattern->getTypeLoc()); + PackExpansionTypeLoc TL = TLB.push<PackExpansionTypeLoc>(Result); TL.setEllipsisLoc(EllipsisLoc); - - // Copy over the source-location information from the type. - memcpy(TL.getNextTypeLoc().getOpaqueData(), - Pattern->getTypeLoc().getOpaqueData(), - Pattern->getTypeLoc().getFullDataSize()); - return TSResult; + + return TLB.getTypeSourceInfo(Context, Result); } QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange, @@ -818,16 +819,12 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, 0, Validator)) { - std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); + diagnoseTypo(Corrected, + PDiag(diag::err_sizeof_pack_no_pack_name_suggest) << &Name, + PDiag(diag::note_parameter_pack_here)); 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: case LookupResult::FoundUnresolvedValue: break; @@ -848,3 +845,63 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, return new (Context) SizeOfPackExpr(Context.getSizeType(), OpLoc, ParameterPack, NameLoc, RParenLoc); } + +TemplateArgumentLoc +Sema::getTemplateArgumentPackExpansionPattern( + TemplateArgumentLoc OrigLoc, + SourceLocation &Ellipsis, Optional<unsigned> &NumExpansions) const { + const TemplateArgument &Argument = OrigLoc.getArgument(); + assert(Argument.isPackExpansion()); + switch (Argument.getKind()) { + case TemplateArgument::Type: { + // FIXME: We shouldn't ever have to worry about missing + // type-source info! + TypeSourceInfo *ExpansionTSInfo = OrigLoc.getTypeSourceInfo(); + if (!ExpansionTSInfo) + ExpansionTSInfo = Context.getTrivialTypeSourceInfo(Argument.getAsType(), + Ellipsis); + PackExpansionTypeLoc Expansion = + ExpansionTSInfo->getTypeLoc().castAs<PackExpansionTypeLoc>(); + Ellipsis = Expansion.getEllipsisLoc(); + + TypeLoc Pattern = Expansion.getPatternLoc(); + NumExpansions = Expansion.getTypePtr()->getNumExpansions(); + + // We need to copy the TypeLoc because TemplateArgumentLocs store a + // TypeSourceInfo. + // FIXME: Find some way to avoid the copy? + TypeLocBuilder TLB; + TLB.pushFullCopy(Pattern); + TypeSourceInfo *PatternTSInfo = + TLB.getTypeSourceInfo(Context, Pattern.getType()); + return TemplateArgumentLoc(TemplateArgument(Pattern.getType()), + PatternTSInfo); + } + + case TemplateArgument::Expression: { + PackExpansionExpr *Expansion + = cast<PackExpansionExpr>(Argument.getAsExpr()); + Expr *Pattern = Expansion->getPattern(); + Ellipsis = Expansion->getEllipsisLoc(); + NumExpansions = Expansion->getNumExpansions(); + return TemplateArgumentLoc(Pattern, Pattern); + } + + case TemplateArgument::TemplateExpansion: + Ellipsis = OrigLoc.getTemplateEllipsisLoc(); + NumExpansions = Argument.getNumTemplateExpansions(); + return TemplateArgumentLoc(Argument.getPackExpansionPattern(), + OrigLoc.getTemplateQualifierLoc(), + OrigLoc.getTemplateNameLoc()); + + case TemplateArgument::Declaration: + case TemplateArgument::NullPtr: + case TemplateArgument::Template: + case TemplateArgument::Integral: + case TemplateArgument::Pack: + case TemplateArgument::Null: + return TemplateArgumentLoc(); + } + + llvm_unreachable("Invalid TemplateArgument Kind!"); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp index 5ce4012fdccd..aa7459de2726 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" +#include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" @@ -33,8 +34,16 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" +#include "TypeLocBuilder.h" + using namespace clang; +enum TypeDiagSelector { + TDS_Function, + TDS_Pointer, + TDS_ObjCObjOrBlock +}; + /// isOmittedBlockReturnType - Return true if this declarator is missing a /// return type because this is a omitted return type on a block literal. static bool isOmittedBlockReturnType(const Declarator &D) { @@ -56,23 +65,15 @@ static bool isOmittedBlockReturnType(const Declarator &D) { /// doesn't apply to the given type. static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, QualType type) { - bool useExpansionLoc = false; - - unsigned diagID = 0; + TypeDiagSelector WhichType; + bool useExpansionLoc = true; switch (attr.getKind()) { - case AttributeList::AT_ObjCGC: - diagID = diag::warn_pointer_attribute_wrong_type; - useExpansionLoc = true; - break; - - case AttributeList::AT_ObjCOwnership: - diagID = diag::warn_objc_object_attribute_wrong_type; - useExpansionLoc = true; - break; - + case AttributeList::AT_ObjCGC: WhichType = TDS_Pointer; break; + case AttributeList::AT_ObjCOwnership: WhichType = TDS_ObjCObjOrBlock; break; default: // Assume everything else was a function attribute. - diagID = diag::warn_function_attribute_wrong_type; + WhichType = TDS_Function; + useExpansionLoc = false; break; } @@ -80,15 +81,17 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, StringRef name = attr.getName()->getName(); // The GC attributes are usually written with macros; special-case them. - if (useExpansionLoc && loc.isMacroID() && attr.getParameterName()) { - if (attr.getParameterName()->isStr("strong")) { + IdentifierInfo *II = attr.isArgIdent(0) ? attr.getArgAsIdent(0)->Ident : 0; + if (useExpansionLoc && loc.isMacroID() && II) { + if (II->isStr("strong")) { if (S.findMacroSpelling(loc, "__strong")) name = "__strong"; - } else if (attr.getParameterName()->isStr("weak")) { + } else if (II->isStr("weak")) { if (S.findMacroSpelling(loc, "__weak")) name = "__weak"; } } - S.Diag(loc, diagID) << name << type; + S.Diag(loc, diag::warn_type_attribute_wrong_type) << name << WhichType + << type; } // objc_gc applies to Objective-C pointers or, otherwise, to the @@ -110,7 +113,14 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, case AttributeList::AT_Regparm: \ case AttributeList::AT_Pcs: \ case AttributeList::AT_PnaclCall: \ - case AttributeList::AT_IntelOclBicc \ + case AttributeList::AT_IntelOclBicc + +// Microsoft-specific type qualifiers. +#define MS_TYPE_ATTRS_CASELIST \ + case AttributeList::AT_Ptr32: \ + case AttributeList::AT_Ptr64: \ + case AttributeList::AT_SPtr: \ + case AttributeList::AT_UPtr namespace { /// An object which stores processing state for the entire @@ -225,26 +235,6 @@ namespace { savedAttrs.back()->setNext(0); } }; - - /// Basically std::pair except that we really want to avoid an - /// implicit operator= for safety concerns. It's also a minor - /// link-time optimization for this to be a private type. - struct AttrAndList { - /// The attribute. - AttributeList &first; - - /// The head of the list the attribute is currently in. - AttributeList *&second; - - AttrAndList(AttributeList &attr, AttributeList *&head) - : first(attr), second(head) {} - }; -} - -namespace llvm { - template <> struct isPodLike<AttrAndList> { - static const bool value = true; - }; } static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) { @@ -294,6 +284,10 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, AttributeList &attr, QualType &type); +static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &state, + AttributeList &attr, + QualType &type); + static bool handleObjCGCTypeAttr(TypeProcessingState &state, AttributeList &attr, QualType &type); @@ -535,12 +529,7 @@ distributeFunctionTypeAttrToInnermost(TypeProcessingState &state, return true; } - if (handleFunctionTypeAttr(state, attr, declSpecType)) { - spliceAttrOutOfList(attr, attrList); - return true; - } - - return false; + return handleFunctionTypeAttr(state, attr, declSpecType); } /// A function type attribute was written in the decl spec. Try to @@ -628,6 +617,10 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType); break; + MS_TYPE_ATTRS_CASELIST: + // Microsoft type attributes cannot go after the declarator-id. + continue; + default: break; } @@ -769,8 +762,13 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // is inferred from the return statements inside the block. // 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)) { + if (S.getLangOpts().CPlusPlus1y && + declarator.getContext() == Declarator::LambdaExprContext) { + // In C++1y, a lambda's implicit return type is 'auto'. + Result = Context.getAutoDeductType(); + break; + } else if (declarator.getContext() == Declarator::LambdaExprContext || + isOmittedBlockReturnType(declarator)) { Result = Context.DependentTy; break; } @@ -996,11 +994,54 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { case DeclSpec::TST_auto: // TypeQuals handled by caller. - Result = Context.getAutoType(QualType(), /*decltype(auto)*/false); + // If auto is mentioned in a lambda parameter context, convert it to a + // template parameter type immediately, with the appropriate depth and + // index, and update sema's state (LambdaScopeInfo) for the current lambda + // being analyzed (which tracks the invented type template parameter). + if (declarator.getContext() == Declarator::LambdaExprParameterContext) { + sema::LambdaScopeInfo *LSI = S.getCurLambda(); + assert(LSI && "No LambdaScopeInfo on the stack!"); + const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth; + const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size(); + const bool IsParameterPack = declarator.hasEllipsis(); + + // Create a name for the invented template parameter type. + std::string InventedTemplateParamName = "$auto-"; + llvm::raw_string_ostream ss(InventedTemplateParamName); + ss << TemplateParameterDepth; + ss << "-" << AutoParameterPosition; + ss.flush(); + + IdentifierInfo& TemplateParamII = Context.Idents.get( + InventedTemplateParamName.c_str()); + // Turns out we must create the TemplateTypeParmDecl here to + // retrieve the corresponding template parameter type. + TemplateTypeParmDecl *CorrespondingTemplateParam = + TemplateTypeParmDecl::Create(Context, + // Temporarily add to the TranslationUnit DeclContext. When the + // associated TemplateParameterList is attached to a template + // declaration (such as FunctionTemplateDecl), the DeclContext + // for each template parameter gets updated appropriately via + // a call to AdoptTemplateParameterList. + Context.getTranslationUnitDecl(), + /*KeyLoc*/ SourceLocation(), + /*NameLoc*/ declarator.getLocStart(), + TemplateParameterDepth, + AutoParameterPosition, // our template param index + /* Identifier*/ &TemplateParamII, false, IsParameterPack); + LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam); + // Replace the 'auto' in the function parameter with this invented + // template type parameter. + Result = QualType(CorrespondingTemplateParam->getTypeForDecl(), 0); + } else { + Result = Context.getAutoType(QualType(), /*decltype(auto)*/false, false); + } break; case DeclSpec::TST_decltype_auto: - Result = Context.getAutoType(QualType(), /*decltype(auto)*/true); + Result = Context.getAutoType(QualType(), + /*decltype(auto)*/true, + /*IsDependent*/ false); break; case DeclSpec::TST_unknown_anytype: @@ -1547,14 +1588,16 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, ASM = ArrayType::Normal; } } else if (!T->isDependentType() && !T->isVariablyModifiedType() && - !T->isIncompleteType()) { + !T->isIncompleteType() && !T->isUndeducedType()) { // Is the array too large? unsigned ActiveSizeBits = ConstantArrayType::getNumAddressingBits(Context, T, ConstVal); - if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) + if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) { Diag(ArraySize->getLocStart(), diag::err_array_too_large) << ConstVal.toString(10) << ArraySize->getSourceRange(); + return QualType(); + } } T = Context.getConstantArrayType(T, ConstVal, ASM, Quals); @@ -1569,7 +1612,6 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, if (!getLangOpts().C99) { if (T->isVariableArrayType()) { // Prohibit the use of non-POD types in VLAs. - // FIXME: C++1y allows this. QualType BaseT = Context.getBaseElementType(T); if (!T->isDependentType() && !BaseT.isPODType(Context) && @@ -1585,9 +1627,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, } // Just extwarn about VLAs. else - Diag(Loc, getLangOpts().CPlusPlus1y - ? diag::warn_cxx11_compat_array_of_runtime_bound - : diag::ext_vla); + Diag(Loc, diag::ext_vla); } else if (ASM != ArrayType::Normal || Quals != 0) Diag(Loc, getLangOpts().CPlusPlus? diag::err_c99_array_usage_cxx @@ -1618,8 +1658,9 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) { llvm::APSInt vecSize(32); if (!ArraySize->isIntegerConstantExpr(vecSize, Context)) { - Diag(AttrLoc, diag::err_attribute_argument_not_int) - << "ext_vector_type" << ArraySize->getSourceRange(); + Diag(AttrLoc, diag::err_attribute_argument_type) + << "ext_vector_type" << AANT_ArgumentIntegerConstant + << ArraySize->getSourceRange(); return QualType(); } @@ -1633,30 +1674,50 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, return QualType(); } + if (VectorType::isVectorSizeTooLarge(vectorSize)) { + Diag(AttrLoc, diag::err_attribute_size_too_large) + << ArraySize->getSourceRange(); + return QualType(); + } + return Context.getExtVectorType(T, vectorSize); } return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc); } -QualType Sema::BuildFunctionType(QualType T, - llvm::MutableArrayRef<QualType> ParamTypes, - SourceLocation Loc, DeclarationName Entity, - const FunctionProtoType::ExtProtoInfo &EPI) { +bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) { if (T->isArrayType() || T->isFunctionType()) { Diag(Loc, diag::err_func_returning_array_function) << T->isFunctionType() << T; - return QualType(); + return true; } // Functions cannot return half FP. if (T->isHalfType()) { Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 1 << FixItHint::CreateInsertion(Loc, "*"); - return QualType(); + return true; } + // Methods cannot return interface types. All ObjC objects are + // passed by reference. + if (T->isObjCObjectType()) { + Diag(Loc, diag::err_object_cannot_be_passed_returned_by_value) << 0 << T; + return 0; + } + + return false; +} + +QualType Sema::BuildFunctionType(QualType T, + llvm::MutableArrayRef<QualType> ParamTypes, + SourceLocation Loc, DeclarationName Entity, + const FunctionProtoType::ExtProtoInfo &EPI) { bool Invalid = false; + + Invalid |= CheckFunctionReturnType(T, Loc); + for (unsigned Idx = 0, Cnt = ParamTypes.size(); Idx < Cnt; ++Idx) { // FIXME: Loc is too inprecise here, should use proper locations for args. QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]); @@ -1751,6 +1812,8 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, } } + // FIXME: Adjust member function pointer calling conventions. + return Context.getMemberPointerType(T, Class.getTypePtr()); } @@ -1919,7 +1982,7 @@ static void diagnoseIgnoredQualifiers( { DeclSpec::TQ_atomic, "_Atomic", AtomicQualLoc } }; - llvm::SmallString<32> QualStr; + SmallString<32> QualStr; unsigned NumQuals = 0; SourceLocation Loc; FixItHint FixIts[4]; @@ -2064,6 +2127,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // 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. + // C++14 In generic lambdas allow 'auto' in their parameters. if (ContainsPlaceholderType && (!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator())) { int Error = -1; @@ -2076,7 +2140,12 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case Declarator::ObjCParameterContext: case Declarator::ObjCResultContext: case Declarator::PrototypeContext: - Error = 0; // Function prototype + Error = 0; + break; + case Declarator::LambdaExprParameterContext: + if (!(SemaRef.getLangOpts().CPlusPlus1y + && D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto)) + Error = 14; break; case Declarator::MemberContext: if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static) @@ -2156,8 +2225,10 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, AutoRange = D.getName().getSourceRange(); if (Error != -1) { + const bool IsDeclTypeAuto = + D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_decltype_auto; SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed) - << Error << AutoRange; + << IsDeclTypeAuto << Error << AutoRange; T = SemaRef.Context.IntTy; D.setInvalidType(true); } else @@ -2207,6 +2278,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, D.setInvalidType(true); break; case Declarator::PrototypeContext: + case Declarator::LambdaExprParameterContext: case Declarator::ObjCParameterContext: case Declarator::ObjCResultContext: case Declarator::KNRTypeListContext: @@ -2377,7 +2449,8 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D, S.Diag(DeclType.Loc, diag::note_empty_parens_default_ctor) << FixItHint::CreateRemoval(ParenRange); else { - std::string Init = S.getFixItZeroInitializerForType(RT); + std::string Init = + S.getFixItZeroInitializerForType(RT, ParenRange.getBegin()); if (Init.empty() && S.LangOpts.CPlusPlus11) Init = "{}"; if (!Init.empty()) @@ -2387,6 +2460,52 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D, } } +/// Helper for figuring out the default CC for a function declarator type. If +/// this is the outermost chunk, then we can determine the CC from the +/// declarator context. If not, then this could be either a member function +/// type or normal function type. +static CallingConv +getCCForDeclaratorChunk(Sema &S, Declarator &D, + const DeclaratorChunk::FunctionTypeInfo &FTI, + unsigned ChunkIndex) { + assert(D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function); + + bool IsCXXInstanceMethod = false; + + if (S.getLangOpts().CPlusPlus) { + // Look inwards through parentheses to see if this chunk will form a + // member pointer type or if we're the declarator. Any type attributes + // between here and there will override the CC we choose here. + unsigned I = ChunkIndex; + bool FoundNonParen = false; + while (I && !FoundNonParen) { + --I; + if (D.getTypeObject(I).Kind != DeclaratorChunk::Paren) + FoundNonParen = true; + } + + if (FoundNonParen) { + // If we're not the declarator, we're a regular function type unless we're + // in a member pointer. + IsCXXInstanceMethod = + D.getTypeObject(I).Kind == DeclaratorChunk::MemberPointer; + } else { + // We're the innermost decl chunk, so must be a function declarator. + assert(D.isFunctionDeclarator()); + + // If we're inside a record, we're declaring a method, but it could be + // explicitly or implicitly static. + IsCXXInstanceMethod = + D.isFirstDeclarationOfMember() && + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && + !D.isStaticMember(); + } + } + + return S.Context.getDefaultCallingConvention(FTI.isVariadic, + IsCXXInstanceMethod); +} + static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, QualType declSpecType, TypeSourceInfo *TInfo) { @@ -2580,8 +2699,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } } } - - if (const AutoType *AT = T->getContainedAutoType()) { + const AutoType *AT = T->getContainedAutoType(); + // Allow arrays of auto if we are a generic lambda parameter. + // i.e. [](auto (&array)[5]) { return array[0]; }; OK + if (AT && D.getContext() != Declarator::LambdaExprParameterContext) { // We've already diagnosed this for decltype(auto). if (!AT->isDecltypeAuto()) S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto) @@ -2667,6 +2788,33 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } } + // Methods cannot return interface types. All ObjC objects are + // passed by reference. + if (T->isObjCObjectType()) { + SourceLocation DiagLoc, FixitLoc; + if (TInfo) { + DiagLoc = TInfo->getTypeLoc().getLocStart(); + FixitLoc = S.PP.getLocForEndOfToken(TInfo->getTypeLoc().getLocEnd()); + } else { + DiagLoc = D.getDeclSpec().getTypeSpecTypeLoc(); + FixitLoc = S.PP.getLocForEndOfToken(D.getDeclSpec().getLocEnd()); + } + S.Diag(DiagLoc, diag::err_object_cannot_be_passed_returned_by_value) + << 0 << T + << FixItHint::CreateInsertion(FixitLoc, "*"); + + T = Context.getObjCObjectPointerType(T); + if (TInfo) { + TypeLocBuilder TLB; + TLB.pushFullCopy(TInfo->getTypeLoc()); + ObjCObjectPointerTypeLoc TLoc = TLB.push<ObjCObjectPointerTypeLoc>(T); + TLoc.setStarLoc(FixitLoc); + TInfo = TLB.getTypeSourceInfo(Context, T); + } + + D.setInvalidType(true); + } + // cv-qualifiers on return types are pointless except when the type is a // class type in C++. if ((T.getCVRQualifiers() || T->isAtomicType()) && @@ -2712,13 +2860,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } } - if (LangOpts.CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) { + if (LangOpts.CPlusPlus && D.getDeclSpec().hasTagDefinition()) { // C++ [dcl.fct]p6: // Types shall not be defined in return or parameter types. TagDecl *Tag = cast<TagDecl>(D.getDeclSpec().getRepAsDecl()); - if (Tag->isCompleteDefinition()) - S.Diag(Tag->getLocation(), diag::err_type_defined_in_result_type) - << Context.getTypeDeclType(Tag); + S.Diag(Tag->getLocation(), diag::err_type_defined_in_result_type) + << Context.getTypeDeclType(Tag); } // Exception specs are not allowed in typedefs. Complain, but add it @@ -2733,9 +2880,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (FTI.isAmbiguous) warnAboutAmbiguousFunction(S, D, DeclType, T); + FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex)); + if (!FTI.NumArgs && !FTI.isVariadic && !LangOpts.CPlusPlus) { // Simple void foo(), where the incoming T is the result type. - T = Context.getFunctionNoProtoType(T); + T = Context.getFunctionNoProtoType(T, EI); } else { // We allow a zero-parameter variadic function in C if the // function is marked with the "overloadable" attribute. Scan @@ -2760,11 +2909,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, S.Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration); D.setInvalidType(true); // Recover by creating a K&R-style function type. - T = Context.getFunctionNoProtoType(T); + T = Context.getFunctionNoProtoType(T, EI); break; } FunctionProtoType::ExtProtoInfo EPI; + EPI.ExtInfo = EI; EPI.Variadic = FTI.isVariadic; EPI.HasTrailingReturn = FTI.hasTrailingReturnType(); EPI.TypeQuals = FTI.TypeQuals; @@ -2786,10 +2936,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, QualType ArgTy = Param->getType(); assert(!ArgTy.isNull() && "Couldn't parse type?"); - // Adjust the parameter type. - assert((ArgTy == Context.getAdjustedParameterType(ArgTy)) && - "Unadjusted type?"); - // Look for 'void'. void is allowed only as a single argument to a // function with no other parameters (C99 6.7.5.3p10). We record // int(void) as a FunctionProtoType with an empty argument list. @@ -3019,9 +3165,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, EPI.TypeQuals = 0; EPI.RefQualifier = RQ_None; - T = Context.getFunctionType(FnTy->getResultType(), - ArrayRef<QualType>(FnTy->arg_type_begin(), - FnTy->getNumArgs()), + T = Context.getFunctionType(FnTy->getResultType(), FnTy->getArgTypes(), EPI); // Rebuild any parens around the identifier in the function type. for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { @@ -3056,6 +3200,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // is a parameter pack (14.5.3). [...] switch (D.getContext()) { case Declarator::PrototypeContext: + case Declarator::LambdaExprParameterContext: // C++0x [dcl.fct]p13: // [...] When it is part of a parameter-declaration-clause, the // parameter pack is a function parameter pack (14.5.3). The type T @@ -3074,7 +3219,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, T = Context.getPackExpansionType(T, None); } break; - case Declarator::TemplateParamContext: // C++0x [temp.param]p15: // If a template-parameter is a [...] is a parameter-declaration that @@ -3183,13 +3327,18 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state, case Qualifiers::OCL_Autoreleasing: attrStr = "autoreleasing"; break; } + IdentifierLoc *Arg = new (S.Context) IdentifierLoc; + Arg->Ident = &S.Context.Idents.get(attrStr); + Arg->Loc = SourceLocation(); + + ArgsUnion Args(Arg); + // If there wasn't one, add one (with an invalid source location // so that we don't make an AttributedType for it). AttributeList *attr = D.getAttributePool() .create(&S.Context.Idents.get("objc_ownership"), SourceLocation(), /*scope*/ 0, SourceLocation(), - &S.Context.Idents.get(attrStr), SourceLocation(), - /*args*/ 0, 0, AttributeList::AS_GNU); + /*args*/ &Args, 1, AttributeList::AS_GNU); spliceAttrIntoList(*attr, chunk.getAttrListRef()); // TODO: mark whether we did this inference? @@ -3293,6 +3442,7 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { case AttributedType::attr_pascal: return AttributeList::AT_Pascal; case AttributedType::attr_pcs: + case AttributedType::attr_pcs_vfp: return AttributeList::AT_Pcs; case AttributedType::attr_pnaclcall: return AttributeList::AT_PnaclCall; @@ -3302,6 +3452,14 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { return AttributeList::AT_MSABI; case AttributedType::attr_sysv_abi: return AttributeList::AT_SysVABI; + case AttributedType::attr_ptr32: + return AttributeList::AT_Ptr32; + case AttributedType::attr_ptr64: + return AttributeList::AT_Ptr64; + case AttributedType::attr_sptr: + return AttributeList::AT_SPtr; + case AttributedType::attr_uptr: + return AttributeList::AT_UPtr; } llvm_unreachable("unexpected attribute kind!"); } @@ -3318,10 +3476,10 @@ static void fillAttributedTypeLoc(AttributedTypeLoc TL, } TL.setAttrNameLoc(attrs->getLoc()); - if (TL.hasAttrExprOperand()) - TL.setAttrExprOperand(attrs->getArg(0)); - else if (TL.hasAttrEnumOperand()) - TL.setAttrEnumOperandLoc(attrs->getParameterLoc()); + if (TL.hasAttrExprOperand() && attrs->isArgExpr(0)) + TL.setAttrExprOperand(attrs->getArgAsExpr(0)); + else if (TL.hasAttrEnumOperand() && attrs->isArgIdent(0)) + TL.setAttrEnumOperandLoc(attrs->getArgAsIdent(0)->Loc); // FIXME: preserve this information to here. if (TL.hasAttrOperand()) @@ -3399,9 +3557,11 @@ namespace { TemplateSpecializationTypeLoc NamedTL = ElabTL.getNamedTypeLoc() .castAs<TemplateSpecializationTypeLoc>(); TL.copy(NamedTL); - } - else + } else { TL.copy(OldTL.castAs<TemplateSpecializationTypeLoc>()); + assert(TL.getRAngleLoc() == OldTL.castAs<TemplateSpecializationTypeLoc>().getRAngleLoc()); + } + } void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr); @@ -3515,6 +3675,9 @@ namespace { void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { llvm_unreachable("qualified type locs not expected here!"); } + void VisitDecayedTypeLoc(DecayedTypeLoc TL) { + llvm_unreachable("decayed type locs not expected here!"); + } void VisitAttributedTypeLoc(AttributedTypeLoc TL) { fillAttributedTypeLoc(TL, Chunk.getAttrs()); @@ -3775,15 +3938,17 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, // Check the attribute arguments. if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 1; Attr.setInvalid(); return; } - Expr *ASArgExpr = static_cast<Expr *>(Attr.getArg(0)); + Expr *ASArgExpr = static_cast<Expr *>(Attr.getArgAsExpr(0)); llvm::APSInt addrSpace(32); if (ASArgExpr->isTypeDependent() || ASArgExpr->isValueDependent() || !ASArgExpr->isIntegerConstantExpr(addrSpace, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_address_space_not_int) + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) + << Attr.getName() << AANT_ArgumentIntegerConstant << ASArgExpr->getSourceRange(); Attr.setInvalid(); return; @@ -3803,7 +3968,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, max = Qualifiers::MaxAddressSpace; if (addrSpace > max) { S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high) - << Qualifiers::MaxAddressSpace << ASArgExpr->getSourceRange(); + << int(Qualifiers::MaxAddressSpace) << ASArgExpr->getSourceRange(); Attr.setInvalid(); return; } @@ -3878,9 +4043,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, if (AttrLoc.isMacroID()) AttrLoc = S.getSourceManager().getImmediateExpansionRange(AttrLoc).first; - if (!attr.getParameterName()) { - S.Diag(AttrLoc, diag::err_attribute_argument_n_not_string) - << "objc_ownership" << 1; + if (!attr.isArgIdent(0)) { + S.Diag(AttrLoc, diag::err_attribute_argument_type) + << attr.getName() << AANT_ArgumentString; attr.setInvalid(); return true; } @@ -3890,18 +4055,19 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, if (!S.getLangOpts().ObjCAutoRefCount) return true; + IdentifierInfo *II = attr.getArgAsIdent(0)->Ident; Qualifiers::ObjCLifetime lifetime; - if (attr.getParameterName()->isStr("none")) + if (II->isStr("none")) lifetime = Qualifiers::OCL_ExplicitNone; - else if (attr.getParameterName()->isStr("strong")) + else if (II->isStr("strong")) lifetime = Qualifiers::OCL_Strong; - else if (attr.getParameterName()->isStr("weak")) + else if (II->isStr("weak")) lifetime = Qualifiers::OCL_Weak; - else if (attr.getParameterName()->isStr("autoreleasing")) + else if (II->isStr("autoreleasing")) lifetime = Qualifiers::OCL_Autoreleasing; else { S.Diag(AttrLoc, diag::warn_attribute_type_not_supported) - << "objc_ownership" << attr.getParameterName(); + << attr.getName() << II; attr.setInvalid(); return true; } @@ -3942,8 +4108,8 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, 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; + S.Diag(AttrLoc, diag::warn_type_attribute_wrong_type) << name + << TDS_ObjCObjOrBlock << type; } QualType origType = type; @@ -4012,27 +4178,30 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state, attr.setInvalid(); return true; } - + // Check the attribute arguments. - if (!attr.getParameterName()) { - S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) - << "objc_gc" << 1; + if (!attr.isArgIdent(0)) { + S.Diag(attr.getLoc(), diag::err_attribute_argument_type) + << attr.getName() << AANT_ArgumentString; attr.setInvalid(); return true; } Qualifiers::GC GCAttr; - if (attr.getNumArgs() != 0) { - S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + if (attr.getNumArgs() > 1) { + S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << attr.getName() << 1; attr.setInvalid(); return true; } - if (attr.getParameterName()->isStr("weak")) + + IdentifierInfo *II = attr.getArgAsIdent(0)->Ident; + if (II->isStr("weak")) GCAttr = Qualifiers::Weak; - else if (attr.getParameterName()->isStr("strong")) + else if (II->isStr("strong")) GCAttr = Qualifiers::Strong; else { S.Diag(attr.getLoc(), diag::warn_attribute_type_not_supported) - << "objc_gc" << attr.getParameterName(); + << attr.getName() << II; attr.setInvalid(); return true; } @@ -4178,6 +4347,109 @@ namespace { }; } +static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State, + AttributeList &Attr, + QualType &Type) { + Sema &S = State.getSema(); + + AttributeList::Kind Kind = Attr.getKind(); + QualType Desugared = Type; + const AttributedType *AT = dyn_cast<AttributedType>(Type); + while (AT) { + AttributedType::Kind CurAttrKind = AT->getAttrKind(); + + // You cannot specify duplicate type attributes, so if the attribute has + // already been applied, flag it. + if (getAttrListKind(CurAttrKind) == Kind) { + S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute_exact) + << Attr.getName(); + return true; + } + + // You cannot have both __sptr and __uptr on the same type, nor can you + // have __ptr32 and __ptr64. + if ((CurAttrKind == AttributedType::attr_ptr32 && + Kind == AttributeList::AT_Ptr64) || + (CurAttrKind == AttributedType::attr_ptr64 && + Kind == AttributeList::AT_Ptr32)) { + S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) + << "'__ptr32'" << "'__ptr64'"; + return true; + } else if ((CurAttrKind == AttributedType::attr_sptr && + Kind == AttributeList::AT_UPtr) || + (CurAttrKind == AttributedType::attr_uptr && + Kind == AttributeList::AT_SPtr)) { + S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) + << "'__sptr'" << "'__uptr'"; + return true; + } + + Desugared = AT->getEquivalentType(); + AT = dyn_cast<AttributedType>(Desugared); + } + + // Pointer type qualifiers can only operate on pointer types, but not + // pointer-to-member types. + if (!isa<PointerType>(Desugared)) { + S.Diag(Attr.getLoc(), Type->isMemberPointerType() ? + diag::err_attribute_no_member_pointers : + diag::err_attribute_pointers_only) << Attr.getName(); + return true; + } + + AttributedType::Kind TAK; + switch (Kind) { + default: llvm_unreachable("Unknown attribute kind"); + case AttributeList::AT_Ptr32: TAK = AttributedType::attr_ptr32; break; + case AttributeList::AT_Ptr64: TAK = AttributedType::attr_ptr64; break; + case AttributeList::AT_SPtr: TAK = AttributedType::attr_sptr; break; + case AttributeList::AT_UPtr: TAK = AttributedType::attr_uptr; break; + } + + Type = S.Context.getAttributedType(TAK, Type, Type); + return false; +} + +static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) { + assert(!Attr.isInvalid()); + switch (Attr.getKind()) { + default: + llvm_unreachable("not a calling convention attribute"); + case AttributeList::AT_CDecl: + return AttributedType::attr_cdecl; + case AttributeList::AT_FastCall: + return AttributedType::attr_fastcall; + case AttributeList::AT_StdCall: + return AttributedType::attr_stdcall; + case AttributeList::AT_ThisCall: + return AttributedType::attr_thiscall; + case AttributeList::AT_Pascal: + return AttributedType::attr_pascal; + case AttributeList::AT_Pcs: { + // The attribute may have had a fixit applied where we treated an + // identifier as a string literal. The contents of the string are valid, + // but the form may not be. + StringRef Str; + if (Attr.isArgExpr(0)) + Str = cast<StringLiteral>(Attr.getArgAsExpr(0))->getString(); + else + Str = Attr.getArgAsIdent(0)->Ident->getName(); + return llvm::StringSwitch<AttributedType::Kind>(Str) + .Case("aapcs", AttributedType::attr_pcs) + .Case("aapcs-vfp", AttributedType::attr_pcs_vfp); + } + case AttributeList::AT_PnaclCall: + return AttributedType::attr_pnaclcall; + case AttributeList::AT_IntelOclBicc: + return AttributedType::attr_inteloclbicc; + case AttributeList::AT_MSABI: + return AttributedType::attr_ms_abi; + case AttributeList::AT_SysVABI: + return AttributedType::attr_sysv_abi; + } + llvm_unreachable("unexpected attribute kind!"); +} + /// Process an individual function attribute. Returns true to /// indicate that the attribute was handled, false if it wasn't. static bool handleFunctionTypeAttr(TypeProcessingState &state, @@ -4254,34 +4526,41 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, const FunctionType *fn = unwrapped.get(); CallingConv CCOld = fn->getCallConv(); - if (S.Context.getCanonicalCallConv(CC) == - S.Context.getCanonicalCallConv(CCOld)) { - FunctionType::ExtInfo EI= unwrapped.get()->getExtInfo().withCallingConv(CC); - type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); - return true; - } + AttributedType::Kind CCAttrKind = getCCTypeAttrKind(attr); - if (CCOld != (S.LangOpts.MRTD ? CC_X86StdCall : CC_Default)) { - // Should we diagnose reapplications of the same convention? - S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible) - << FunctionType::getNameForCallConv(CC) - << FunctionType::getNameForCallConv(CCOld); - attr.setInvalid(); - return true; + if (CCOld != CC) { + // Error out on when there's already an attribute on the type + // and the CCs don't match. + const AttributedType *AT = S.getCallingConvAttributedType(type); + if (AT && AT->getAttrKind() != CCAttrKind) { + S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible) + << FunctionType::getNameForCallConv(CC) + << FunctionType::getNameForCallConv(CCOld); + attr.setInvalid(); + return true; + } } - // Diagnose the use of X86 fastcall on varargs or unprototyped functions. - if (CC == CC_X86FastCall) { - if (isa<FunctionNoProtoType>(fn)) { - S.Diag(attr.getLoc(), diag::err_cconv_knr) - << FunctionType::getNameForCallConv(CC); + // Diagnose use of callee-cleanup calling convention on variadic functions. + if (isCalleeCleanup(CC)) { + const FunctionProtoType *FnP = dyn_cast<FunctionProtoType>(fn); + if (FnP && FnP->isVariadic()) { + unsigned DiagID = diag::err_cconv_varargs; + // stdcall and fastcall are ignored with a warning for GCC and MS + // compatibility. + if (CC == CC_X86StdCall || CC == CC_X86FastCall) + DiagID = diag::warn_cconv_varargs; + + S.Diag(attr.getLoc(), DiagID) << FunctionType::getNameForCallConv(CC); attr.setInvalid(); return true; } + } - const FunctionProtoType *FnP = cast<FunctionProtoType>(fn); - if (FnP->isVariadic()) { - S.Diag(attr.getLoc(), diag::err_cconv_varargs) + // Diagnose the use of X86 fastcall on unprototyped functions. + if (CC == CC_X86FastCall) { + if (isa<FunctionNoProtoType>(fn)) { + S.Diag(attr.getLoc(), diag::err_cconv_knr) << FunctionType::getNameForCallConv(CC); attr.setInvalid(); return true; @@ -4297,27 +4576,66 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, } } + // Modify the CC from the wrapped function type, wrap it all back, and then + // wrap the whole thing in an AttributedType as written. The modified type + // might have a different CC if we ignored the attribute. FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withCallingConv(CC); - type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); + QualType Equivalent = + unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); + type = S.Context.getAttributedType(CCAttrKind, type, Equivalent); return true; } +void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic) { + const FunctionType *FT = T->castAs<FunctionType>(); + bool IsVariadic = (isa<FunctionProtoType>(FT) && + cast<FunctionProtoType>(FT)->isVariadic()); + CallingConv CC = FT->getCallConv(); + + // Only adjust types with the default convention. For example, on Windows we + // should adjust a __cdecl type to __thiscall for instance methods, and a + // __thiscall type to __cdecl for static methods. + CallingConv DefaultCC = + Context.getDefaultCallingConvention(IsVariadic, IsStatic); + if (CC != DefaultCC) + return; + + // Check if there was an explicit attribute, but only look through parens. + // The intent is to look for an attribute on the current declarator, but not + // one that came from a typedef. + QualType R = T.IgnoreParens(); + while (const AttributedType *AT = dyn_cast<AttributedType>(R)) { + if (AT->isCallingConv()) + return; + R = AT->getModifiedType().IgnoreParens(); + } + + // FIXME: This loses sugar. This should probably be fixed with an implicit + // AttributedType node that adjusts the convention. + CC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic); + FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(CC)); + FunctionTypeUnwrapper Unwrapped(*this, T); + T = Unwrapped.wrap(*this, FT); +} + /// Handle OpenCL image access qualifiers: read_only, write_only, read_write static void HandleOpenCLImageAccessAttribute(QualType& CurType, const AttributeList &Attr, Sema &S) { // Check the attribute arguments. if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 1; Attr.setInvalid(); return; } - Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0)); + Expr *sizeExpr = static_cast<Expr *>(Attr.getArgAsExpr(0)); llvm::APSInt arg(32); if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() || !sizeExpr->isIntegerConstantExpr(arg, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) - << "opencl_image_access" << sizeExpr->getSourceRange(); + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) + << Attr.getName() << AANT_ArgumentIntegerConstant + << sizeExpr->getSourceRange(); Attr.setInvalid(); return; } @@ -4348,21 +4666,25 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, Sema &S) { // Check the attribute arguments. if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 1; Attr.setInvalid(); return; } - Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0)); + Expr *sizeExpr = static_cast<Expr *>(Attr.getArgAsExpr(0)); llvm::APSInt vecSize(32); if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() || !sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) - << "vector_size" << sizeExpr->getSourceRange(); + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) + << Attr.getName() << AANT_ArgumentIntegerConstant + << sizeExpr->getSourceRange(); Attr.setInvalid(); return; } - // the base type must be integer or float, and can't already be a vector. - if (!CurType->isIntegerType() && !CurType->isRealFloatingType()) { + // The base type must be integer (not Boolean or enumeration) or float, and + // can't already be a vector. + if (!CurType->isBuiltinType() || CurType->isBooleanType() || + (!CurType->isIntegerType() && !CurType->isRealFloatingType())) { S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType; Attr.setInvalid(); return; @@ -4378,6 +4700,12 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, Attr.setInvalid(); return; } + if (VectorType::isVectorSizeTooLarge(vectorSize / typeSize)) { + S.Diag(Attr.getLoc(), diag::err_attribute_size_too_large) + << sizeExpr->getSourceRange(); + Attr.setInvalid(); + return; + } if (vectorSize == 0) { S.Diag(Attr.getLoc(), diag::err_attribute_zero_size) << sizeExpr->getSourceRange(); @@ -4396,14 +4724,21 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, static void HandleExtVectorTypeAttr(QualType &CurType, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 1; + return; + } + Expr *sizeExpr; // Special case where the argument is a template id. - if (Attr.getParameterName()) { + if (Attr.isArgIdent(0)) { CXXScopeSpec SS; SourceLocation TemplateKWLoc; UnqualifiedId id; - id.setIdentifier(Attr.getParameterName(), Attr.getLoc()); + id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc()); ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc, id, false, false); @@ -4412,12 +4747,7 @@ static void HandleExtVectorTypeAttr(QualType &CurType, sizeExpr = Size.get(); } else { - // check the attribute arguments. - if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; - return; - } - sizeExpr = Attr.getArg(0); + sizeExpr = Attr.getArgAsExpr(0); } // Create the vector type. @@ -4426,6 +4756,43 @@ static void HandleExtVectorTypeAttr(QualType &CurType, CurType = T; } +static bool isPermittedNeonBaseType(QualType &Ty, + VectorType::VectorKind VecKind, + bool IsAArch64) { + const BuiltinType *BTy = Ty->getAs<BuiltinType>(); + if (!BTy) + return false; + + if (VecKind == VectorType::NeonPolyVector) { + if (IsAArch64) { + // AArch64 polynomial vectors are unsigned and support poly64. + return BTy->getKind() == BuiltinType::UChar || + BTy->getKind() == BuiltinType::UShort || + BTy->getKind() == BuiltinType::ULongLong; + } else { + // AArch32 polynomial vector are signed. + return BTy->getKind() == BuiltinType::SChar || + BTy->getKind() == BuiltinType::Short; + } + } + + // Non-polynomial vector types: the usual suspects are allowed, as well as + // float64_t on AArch64. + if (IsAArch64 && BTy->getKind() == BuiltinType::Double) + return true; + + return BTy->getKind() == BuiltinType::SChar || + BTy->getKind() == BuiltinType::UChar || + BTy->getKind() == BuiltinType::Short || + BTy->getKind() == BuiltinType::UShort || + BTy->getKind() == BuiltinType::Int || + BTy->getKind() == BuiltinType::UInt || + BTy->getKind() == BuiltinType::LongLong || + BTy->getKind() == BuiltinType::ULongLong || + BTy->getKind() == BuiltinType::Float || + BTy->getKind() == BuiltinType::Half; +} + /// HandleNeonVectorTypeAttr - The "neon_vector_type" and /// "neon_polyvector_type" attributes are used to create vector types that /// are mangled according to ARM's ABI. Otherwise, these types are identical @@ -4435,43 +4802,41 @@ static void HandleExtVectorTypeAttr(QualType &CurType, /// match one of the standard Neon vector types. static void HandleNeonVectorTypeAttr(QualType& CurType, const AttributeList &Attr, Sema &S, - VectorType::VectorKind VecKind, - const char *AttrName) { + VectorType::VectorKind VecKind) { + // Target must have NEON + if (!S.Context.getTargetInfo().hasFeature("neon")) { + S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr.getName(); + Attr.setInvalid(); + return; + } // Check the attribute arguments. if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 1; Attr.setInvalid(); return; } // The number of elements must be an ICE. - Expr *numEltsExpr = static_cast<Expr *>(Attr.getArg(0)); + Expr *numEltsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0)); llvm::APSInt numEltsInt(32); if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() || !numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) - << AttrName << numEltsExpr->getSourceRange(); + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) + << Attr.getName() << AANT_ArgumentIntegerConstant + << numEltsExpr->getSourceRange(); Attr.setInvalid(); return; } // Only certain element types are supported for Neon vectors. - const BuiltinType* BTy = CurType->getAs<BuiltinType>(); - if (!BTy || - (VecKind == VectorType::NeonPolyVector && - BTy->getKind() != BuiltinType::SChar && - BTy->getKind() != BuiltinType::Short) || - (BTy->getKind() != BuiltinType::SChar && - BTy->getKind() != BuiltinType::UChar && - BTy->getKind() != BuiltinType::Short && - BTy->getKind() != BuiltinType::UShort && - BTy->getKind() != BuiltinType::Int && - BTy->getKind() != BuiltinType::UInt && - BTy->getKind() != BuiltinType::LongLong && - BTy->getKind() != BuiltinType::ULongLong && - BTy->getKind() != BuiltinType::Float)) { - S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) <<CurType; + llvm::Triple::ArchType Arch = + S.Context.getTargetInfo().getTriple().getArch(); + if (!isPermittedNeonBaseType(CurType, VecKind, + Arch == llvm::Triple::aarch64)) { + S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType; Attr.setInvalid(); return; } + // The total size of the vector must be 64 or 128 bits. unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType)); unsigned numElts = static_cast<unsigned>(numEltsInt.getZExtValue()); @@ -4565,13 +4930,12 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, break; case AttributeList::AT_NeonVectorType: HandleNeonVectorTypeAttr(type, attr, state.getSema(), - VectorType::NeonVector, "neon_vector_type"); + VectorType::NeonVector); attr.setUsedAsTypeAttr(); break; case AttributeList::AT_NeonPolyVectorType: HandleNeonVectorTypeAttr(type, attr, state.getSema(), - VectorType::NeonPolyVector, - "neon_polyvector_type"); + VectorType::NeonPolyVector); attr.setUsedAsTypeAttr(); break; case AttributeList::AT_OpenCLImageAccess: @@ -4580,12 +4944,12 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, break; case AttributeList::AT_Win64: - case AttributeList::AT_Ptr32: - case AttributeList::AT_Ptr64: - // FIXME: Don't ignore these. We have partial handling for them as - // declaration attributes in SemaDeclAttr.cpp; that should be moved here. attr.setUsedAsTypeAttr(); break; + MS_TYPE_ATTRS_CASELIST: + if (!handleMSPointerTypeQualifierAttr(state, attr, type)) + attr.setUsedAsTypeAttr(); + break; case AttributeList::AT_NSReturnsRetained: if (!state.getSema().getLangOpts().ObjCAutoRefCount) @@ -4627,41 +4991,46 @@ bool Sema::RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser){ // Fast path the case where the type is already complete. if (!T->isIncompleteType()) + // FIXME: The definition might not be visible. return false; // Incomplete array types may be completed by the initializer attached to - // their definitions. For static data members of class templates we need to - // instantiate the definition to get this initializer and complete the type. + // their definitions. For static data members of class templates and for + // variable templates, we need to instantiate the definition to get this + // initializer and complete the type. if (T->isIncompleteArrayType()) { if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) { if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { - if (Var->isStaticDataMember() && - Var->getInstantiatedFromStaticDataMember()) { + if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) { + SourceLocation PointOfInstantiation = E->getExprLoc(); - MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); - assert(MSInfo && "Missing member specialization information?"); - if (MSInfo->getTemplateSpecializationKind() - != TSK_ExplicitSpecialization) { + if (MemberSpecializationInfo *MSInfo = + Var->getMemberSpecializationInfo()) { // If we don't already have a point of instantiation, this is it. if (MSInfo->getPointOfInstantiation().isInvalid()) { - MSInfo->setPointOfInstantiation(E->getLocStart()); + MSInfo->setPointOfInstantiation(PointOfInstantiation); // This is a modification of an existing AST node. Notify // listeners. if (ASTMutationListener *L = getASTMutationListener()) L->StaticDataMemberInstantiated(Var); } + } else { + VarTemplateSpecializationDecl *VarSpec = + cast<VarTemplateSpecializationDecl>(Var); + if (VarSpec->getPointOfInstantiation().isInvalid()) + VarSpec->setPointOfInstantiation(PointOfInstantiation); + } - InstantiateStaticDataMemberDefinition(E->getExprLoc(), Var); + InstantiateVariableDefinition(PointOfInstantiation, Var); - // Update the type to the newly instantiated definition's type both - // here and within the expression. - if (VarDecl *Def = Var->getDefinition()) { - DRE->setDecl(Def); - T = Def->getType(); - DRE->setType(T); - E->setType(T); - } + // Update the type to the newly instantiated definition's type both + // here and within the expression. + if (VarDecl *Def = Var->getDefinition()) { + DRE->setDecl(Def); + T = Def->getType(); + DRE->setType(T); + E->setType(T); } // We still go on to try to complete the type independently, as it @@ -4720,6 +5089,20 @@ bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) { /// @c false otherwise. bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, TypeDiagnoser &Diagnoser) { + if (RequireCompleteTypeImpl(Loc, T, Diagnoser)) + return true; + if (const TagType *Tag = T->getAs<TagType>()) { + if (!Tag->getDecl()->isCompleteDefinitionRequired()) { + Tag->getDecl()->setCompleteDefinitionRequired(); + Consumer.HandleTagDeclRequiredDefinition(Tag->getDecl()); + } + } + return false; +} + +/// \brief The implementation of RequireCompleteType +bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, + TypeDiagnoser &Diagnoser) { // FIXME: Add this assertion to make sure we always get instantiation points. // assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType"); // FIXME: Add this assertion to help us flush out problems with @@ -4732,7 +5115,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, NamedDecl *Def = 0; if (!T->isIncompleteType(&Def)) { // If we know about the definition but it is not visible, complain. - if (!Diagnoser.Suppressed && Def && !LookupResult::isVisible(Def)) { + if (!Diagnoser.Suppressed && Def && !LookupResult::isVisible(*this, 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. @@ -4752,6 +5135,14 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, return false; } + // FIXME: If there's an unimported definition of this type in a module (for + // instance, because we forward declared it, then imported the definition), + // import that definition now. + // FIXME: What about other cases where an import extends a redeclaration + // chain for a declaration that can be accessed through a mechanism other + // than name lookup (eg, referenced in a template, or a variable whose type + // could be completed by the module)? + const TagType *Tag = T->getAs<TagType>(); const ObjCInterfaceType *IFace = 0; @@ -4814,6 +5205,12 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, return true; // We have an incomplete type. Produce a diagnostic. + if (Ident___float128 && + T == Context.getTypeDeclType(Context.getFloat128StubType())) { + Diag(Loc, diag::err_typecheck_decl_incomplete_type___float128); + return true; + } + Diagnoser.diagnose(*this, Loc, T); // If the type was a forward declaration of a class/struct/union @@ -4828,6 +5225,11 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, if (IFace && !IFace->getDecl()->isInvalidDecl()) Diag(IFace->getDecl()->getLocation(), diag::note_forward_class); + // If we have external information that we can use to suggest a fix, + // produce a note. + if (ExternalSource) + ExternalSource->MaybeDiagnoseMissingCompleteType(Loc, T); + return true; } diff --git a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp index 2f7701227da6..45067dee9b8d 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp @@ -26,21 +26,67 @@ bool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D, return false; } +static void HandleARMInterruptAttr(Decl *d, + const AttributeList &Attr, Sema &S) { + // Check the attribute arguments. + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) + << 1; + return; + } + + StringRef Str; + SourceLocation ArgLoc; + + if (Attr.getNumArgs() == 0) + Str = ""; + else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc)) + return; + + ARMInterruptAttr::InterruptType Kind; + if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) + << Attr.getName() << Str << ArgLoc; + return; + } + + unsigned Index = Attr.getAttributeSpellingListIndex(); + d->addAttr(::new (S.Context) + ARMInterruptAttr(Attr.getLoc(), S.Context, Kind, Index)); +} + +namespace { + class ARMAttributesSema : public TargetAttributesSema { + public: + ARMAttributesSema() { } + bool ProcessDeclAttribute(Scope *scope, Decl *D, + const AttributeList &Attr, Sema &S) const { + if (Attr.getName()->getName() == "interrupt") { + HandleARMInterruptAttr(D, Attr, S); + return true; + } + return false; + } + }; +} + static void HandleMSP430InterruptAttr(Decl *d, const AttributeList &Attr, Sema &S) { // Check the attribute arguments. if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 1; return; } // FIXME: Check for decl - it should be void ()(void). - Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0)); + Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0)); llvm::APSInt NumParams(32); if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) - << "interrupt" << NumParamsExpr->getSourceRange(); + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) + << Attr.getName() << AANT_ArgumentIntegerConstant + << NumParamsExpr->getSourceRange(); return; } @@ -71,61 +117,13 @@ namespace { }; } -static void HandleMBlazeInterruptHandlerAttr(Decl *d, const AttributeList &Attr, - Sema &S) { - // Check the attribute arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; - return; - } - - // FIXME: Check for decl - it should be void ()(void). - - d->addAttr(::new (S.Context) MBlazeInterruptHandlerAttr(Attr.getLoc(), - S.Context)); - d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context)); -} - -static void HandleMBlazeSaveVolatilesAttr(Decl *d, const AttributeList &Attr, - Sema &S) { - // Check the attribute arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; - return; - } - - // FIXME: Check for decl - it should be void ()(void). - - d->addAttr(::new (S.Context) MBlazeSaveVolatilesAttr(Attr.getLoc(), - S.Context)); - d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context)); -} - - -namespace { - class MBlazeAttributesSema : public TargetAttributesSema { - public: - MBlazeAttributesSema() { } - bool ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr, - Sema &S) const { - if (Attr.getName()->getName() == "interrupt_handler") { - HandleMBlazeInterruptHandlerAttr(D, Attr, S); - return true; - } else if (Attr.getName()->getName() == "save_volatiles") { - HandleMBlazeSaveVolatilesAttr(D, Attr, S); - return true; - } - return false; - } - }; -} - static void HandleX86ForceAlignArgPointerAttr(Decl *D, const AttributeList& Attr, Sema &S) { // Check the attribute arguments. if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 0; return; } @@ -161,6 +159,15 @@ DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range, if (D->hasAttr<DLLImportAttr>()) return NULL; + if (VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (VD->hasDefinition()) { + // dllimport cannot be applied to definitions. + Diag(D->getLocation(), diag::warn_attribute_invalid_on_definition) + << "dllimport"; + return NULL; + } + } + return ::new (Context) DLLImportAttr(Range, Context, AttrSpellingListIndex); } @@ -168,7 +175,8 @@ DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range, static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 0; return; } @@ -214,7 +222,8 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range, static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 0; return; } @@ -270,8 +279,9 @@ namespace { static void HandleMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) { // check the attribute arguments. - if (Attr.hasParameterOrArguments()) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (Attr.getNumArgs()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 0; return; } // Attribute can only be applied to function types. @@ -286,8 +296,9 @@ static void HandleMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) { static void HandleNoMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) { // check the attribute arguments. - if (Attr.hasParameterOrArguments()) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + if (Attr.getNumArgs()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 0; return; } // Attribute can only be applied to function types. @@ -325,10 +336,11 @@ const TargetAttributesSema &Sema::getTargetAttributesSema() const { const llvm::Triple &Triple(Context.getTargetInfo().getTriple()); switch (Triple.getArch()) { + case llvm::Triple::arm: + case llvm::Triple::thumb: + return *(TheTargetAttributesSema = new ARMAttributesSema); case llvm::Triple::msp430: return *(TheTargetAttributesSema = new MSP430AttributesSema); - case llvm::Triple::mblaze: - return *(TheTargetAttributesSema = new MBlazeAttributesSema); case llvm::Triple::x86: case llvm::Triple::x86_64: return *(TheTargetAttributesSema = new X86AttributesSema); diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h index faa47e826eee..f940da4d276d 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h +++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h @@ -24,6 +24,7 @@ #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenMP.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Designator.h" #include "clang/Sema/Lookup.h" @@ -141,7 +142,11 @@ public: /// /// Subclasses may override this function to specify when the transformation /// should rebuild all AST nodes. - bool AlwaysRebuild() { return false; } + /// + /// We must always rebuild all AST nodes when performing variadic template + /// pack expansion, in order to avoid violating the AST invariant that each + /// statement node appears at most once in its containing declaration. + bool AlwaysRebuild() { return SemaRef.ArgumentPackSubstitutionIndex != -1; } /// \brief Returns the location of the entity being transformed, if that /// information was not available elsewhere in the AST. @@ -313,6 +318,16 @@ public: /// \returns the transformed statement. StmtResult TransformStmt(Stmt *S); + /// \brief Transform the given statement. + /// + /// By default, this routine transforms a statement by delegating to the + /// appropriate TransformOMPXXXClause function to transform a specific kind + /// of clause. Subclasses may override this function to transform statements + /// using some other mechanism. + /// + /// \returns the transformed OpenMP clause. + OMPClause *TransformOMPClause(OMPClause *S); + /// \brief Transform the given expression. /// /// By default, this routine transforms an expression by delegating to the @@ -533,8 +548,7 @@ public: CXXRecordDecl *ThisContext, unsigned ThisTypeQuals); - StmtResult - TransformSEHHandler(Stmt *Handler); + StmtResult TransformSEHHandler(Stmt *Handler); QualType TransformTemplateSpecializationType(TypeLocBuilder &TLB, @@ -579,21 +593,37 @@ public: StmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr); ExprResult TransformCXXNamedCastExpr(CXXNamedCastExpr *E); - + + typedef std::pair<ExprResult, QualType> InitCaptureInfoTy; /// \brief Transform the captures and body of a lambda expression. - ExprResult TransformLambdaScope(LambdaExpr *E, CXXMethodDecl *CallOperator); + ExprResult TransformLambdaScope(LambdaExpr *E, CXXMethodDecl *CallOperator, + ArrayRef<InitCaptureInfoTy> InitCaptureExprsAndTypes); + + TemplateParameterList *TransformTemplateParameterList( + TemplateParameterList *TPL) { + return TPL; + } ExprResult TransformAddressOfOperand(Expr *E); ExprResult TransformDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E, bool IsAddressOfOperand); +// FIXME: We use LLVM_ATTRIBUTE_NOINLINE because inlining causes a ridiculous +// amount of stack usage with clang. #define STMT(Node, Parent) \ + LLVM_ATTRIBUTE_NOINLINE \ StmtResult Transform##Node(Node *S); #define EXPR(Node, Parent) \ + LLVM_ATTRIBUTE_NOINLINE \ ExprResult Transform##Node(Node *E); #define ABSTRACT_STMT(Stmt) #include "clang/AST/StmtNodes.inc" +#define OPENMP_CLAUSE(Name, Class) \ + LLVM_ATTRIBUTE_NOINLINE \ + OMPClause *Transform ## Class(Class *S); +#include "clang/Basic/OpenMPKinds.def" + /// \brief Build a new pointer type given its pointee type. /// /// By default, performs semantic analysis when building the pointer type. @@ -767,7 +797,8 @@ public: // Note, IsDependent is always false here: we implicitly convert an 'auto' // which has been deduced to a dependent type into an undeduced 'auto', so // that we'll retry deduction after the transformation. - return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto); + return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto, + /*IsDependent*/ false); } /// \brief Build a new template specialization type. @@ -1163,10 +1194,9 @@ public: /// /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. - StmtResult RebuildDeclStmt(Decl **Decls, unsigned NumDecls, - SourceLocation StartLoc, - SourceLocation EndLoc) { - Sema::DeclGroupPtrTy DG = getSema().BuildDeclaratorGroup(Decls, NumDecls); + StmtResult RebuildDeclStmt(llvm::MutableArrayRef<Decl *> Decls, + SourceLocation StartLoc, SourceLocation EndLoc) { + Sema::DeclGroupPtrTy DG = getSema().BuildDeclaratorGroup(Decls); return getSema().ActOnDeclStmt(DG, StartLoc, EndLoc); } @@ -1256,6 +1286,63 @@ public: return getSema().BuildObjCAtThrowStmt(AtLoc, Operand); } + /// \brief Build a new OpenMP parallel directive. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildOMPParallelDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPParallelDirective(Clauses, AStmt, + StartLoc, EndLoc); + } + + /// \brief Build a new OpenMP 'default' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPDefaultClause(OpenMPDefaultClauseKind Kind, + SourceLocation KindKwLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPDefaultClause(Kind, KindKwLoc, + StartLoc, LParenLoc, EndLoc); + } + + /// \brief Build a new OpenMP 'private' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPPrivateClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, + EndLoc); + } + + /// \brief Build a new OpenMP 'firstprivate' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPFirstprivateClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, + EndLoc); + } + + OMPClause *RebuildOMPSharedClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, + EndLoc); + } + /// \brief Rebuild the operand to an Objective-C \@synchronized statement. /// /// By default, performs semantic analysis to build the new statement. @@ -1333,9 +1420,8 @@ public: /// /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. - StmtResult RebuildCXXTryStmt(SourceLocation TryLoc, - Stmt *TryBlock, - MultiStmtArg Handlers) { + StmtResult RebuildCXXTryStmt(SourceLocation TryLoc, Stmt *TryBlock, + ArrayRef<Stmt *> Handlers) { return getSema().ActOnCXXTryBlock(TryLoc, TryBlock, Handlers); } @@ -1392,22 +1478,18 @@ public: return getSema().FinishCXXForRangeStmt(ForRange, Body); } - StmtResult RebuildSEHTryStmt(bool IsCXXTry, - SourceLocation TryLoc, - Stmt *TryBlock, - Stmt *Handler) { - return getSema().ActOnSEHTryBlock(IsCXXTry,TryLoc,TryBlock,Handler); + StmtResult RebuildSEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, + Stmt *TryBlock, Stmt *Handler) { + return getSema().ActOnSEHTryBlock(IsCXXTry, TryLoc, TryBlock, Handler); } - StmtResult RebuildSEHExceptStmt(SourceLocation Loc, - Expr *FilterExpr, + StmtResult RebuildSEHExceptStmt(SourceLocation Loc, Expr *FilterExpr, Stmt *Block) { - return getSema().ActOnSEHExceptBlock(Loc,FilterExpr,Block); + return getSema().ActOnSEHExceptBlock(Loc, FilterExpr, Block); } - StmtResult RebuildSEHFinallyStmt(SourceLocation Loc, - Stmt *Block) { - return getSema().ActOnSEHFinallyBlock(Loc,Block); + StmtResult RebuildSEHFinallyStmt(SourceLocation Loc, Stmt *Block) { + return getSema().ActOnSEHFinallyBlock(Loc, Block); } /// \brief Build a new expression that references a declaration. @@ -1767,12 +1849,10 @@ public: SourceLocation DefaultLoc, SourceLocation RParenLoc, Expr *ControllingExpr, - TypeSourceInfo **Types, - Expr **Exprs, - unsigned NumAssocs) { + ArrayRef<TypeSourceInfo *> Types, + ArrayRef<Expr *> Exprs) { return getSema().CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc, - ControllingExpr, Types, Exprs, - NumAssocs); + ControllingExpr, Types, Exprs); } /// \brief Build a new overloaded operator call expression. @@ -2485,6 +2565,14 @@ public: return SemaRef.SemaBuiltinShuffleVector(cast<CallExpr>(TheCall.take())); } + /// \brief Build a new convert vector expression. + ExprResult RebuildConvertVectorExpr(SourceLocation BuiltinLoc, + Expr *SrcExpr, TypeSourceInfo *DstTInfo, + SourceLocation RParenLoc) { + return SemaRef.SemaConvertVectorExpr(SrcExpr, DstTInfo, + BuiltinLoc, RParenLoc); + } + /// \brief Build a new template argument pack expansion. /// /// By default, performs semantic analysis to build a new pack expansion @@ -2603,6 +2691,23 @@ StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) { return SemaRef.Owned(S); } +template<typename Derived> +OMPClause *TreeTransform<Derived>::TransformOMPClause(OMPClause *S) { + if (!S) + return S; + + switch (S->getClauseKind()) { + default: break; + // Transform individual clause nodes +#define OPENMP_CLAUSE(Name, Class) \ + case OMPC_ ## Name : \ + return getDerived().Transform ## Class(cast<Class>(S)); +#include "clang/Basic/OpenMPKinds.def" + } + + return S; +} + template<typename Derived> ExprResult TreeTransform<Derived>::TransformExpr(Expr *E) { @@ -2632,12 +2737,19 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init, if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init)) Init = ExprTemp->getSubExpr(); + if (MaterializeTemporaryExpr *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) + Init = MTE->GetTemporaryExpr(); + while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init)) Init = Binder->getSubExpr(); if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init)) Init = ICE->getSubExprAsWritten(); + if (CXXStdInitializerListExpr *ILE = + dyn_cast<CXXStdInitializerListExpr>(Init)) + return TransformInitializer(ILE->getSubExpr(), CXXDirectInit); + // If this is not a direct-initializer, we only need to reconstruct // InitListExprs. Other forms of copy-initialization will be a no-op if // the initializer is already the right type. @@ -2675,7 +2787,7 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init, Construct->getType()); // Build a ParenListExpr to represent anything else. - SourceRange Parens = Construct->getParenRange(); + SourceRange Parens = Construct->getParenOrBraceRange(); return getDerived().RebuildParenListExpr(Parens.getBegin(), NewArgs, Parens.getEnd()); } @@ -3228,8 +3340,8 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First, SourceLocation Ellipsis; Optional<unsigned> OrigNumExpansions; TemplateArgumentLoc Pattern - = In.getPackExpansionPattern(Ellipsis, OrigNumExpansions, - getSema().Context); + = getSema().getTemplateArgumentPackExpansionPattern( + In, Ellipsis, OrigNumExpansions); SmallVector<UnexpandedParameterPack, 2> Unexpanded; getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded); @@ -3421,12 +3533,13 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB, Qs.removeObjCLifetime(); Deduced = SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(), Qs); - Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto()); + Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto(), + AutoTy->isDependentType()); TLB.TypeWasModifiedSafely(Result); } else { // Otherwise, complain about the addition of a qualifier to an // already-qualified type. - SourceRange R = TLB.getTemporaryTypeLoc(Result).getSourceRange(); + SourceRange R = T.getUnqualifiedLoc().getSourceRange(); SemaRef.Diag(R.getBegin(), diag::err_attr_objc_ownership_redundant) << Result << R; @@ -3581,6 +3694,22 @@ QualType TreeTransform<Derived>::TransformComplexType(TypeLocBuilder &TLB, } template<typename Derived> +QualType TreeTransform<Derived>::TransformDecayedType(TypeLocBuilder &TLB, + DecayedTypeLoc TL) { + QualType OriginalType = getDerived().TransformType(TLB, TL.getOriginalLoc()); + if (OriginalType.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + OriginalType != TL.getOriginalLoc().getType()) + Result = SemaRef.Context.getDecayedType(OriginalType); + TLB.push<DecayedTypeLoc>(Result); + // Nothing to set for DecayedTypeLoc. + return Result; +} + +template<typename Derived> QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB, PointerTypeLoc TL) { QualType PointeeType @@ -5584,8 +5713,7 @@ TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) { if (!getDerived().AlwaysRebuild() && !DeclChanged) return SemaRef.Owned(S); - return getDerived().RebuildDeclStmt(Decls.data(), Decls.size(), - S->getStartLoc(), S->getEndLoc()); + return getDerived().RebuildDeclStmt(Decls, S->getStartLoc(), S->getEndLoc()); } template<typename Derived> @@ -5879,23 +6007,19 @@ TreeTransform<Derived>::TransformObjCForCollectionStmt( Body.get()); } - -template<typename Derived> -StmtResult -TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) { +template <typename Derived> +StmtResult TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) { // Transform the exception declaration, if any. VarDecl *Var = 0; - if (S->getExceptionDecl()) { - VarDecl *ExceptionDecl = S->getExceptionDecl(); - TypeSourceInfo *T = getDerived().TransformType( - ExceptionDecl->getTypeSourceInfo()); + if (VarDecl *ExceptionDecl = S->getExceptionDecl()) { + TypeSourceInfo *T = + getDerived().TransformType(ExceptionDecl->getTypeSourceInfo()); if (!T) return StmtError(); - Var = getDerived().RebuildExceptionDecl(ExceptionDecl, T, - ExceptionDecl->getInnerLocStart(), - ExceptionDecl->getLocation(), - ExceptionDecl->getIdentifier()); + Var = getDerived().RebuildExceptionDecl( + ExceptionDecl, T, ExceptionDecl->getInnerLocStart(), + ExceptionDecl->getLocation(), ExceptionDecl->getIdentifier()); if (!Var || Var->isInvalidDecl()) return StmtError(); } @@ -5905,31 +6029,25 @@ TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) { if (Handler.isInvalid()) return StmtError(); - if (!getDerived().AlwaysRebuild() && - !Var && + if (!getDerived().AlwaysRebuild() && !Var && Handler.get() == S->getHandlerBlock()) return SemaRef.Owned(S); - return getDerived().RebuildCXXCatchStmt(S->getCatchLoc(), - Var, - Handler.get()); + return getDerived().RebuildCXXCatchStmt(S->getCatchLoc(), Var, Handler.get()); } -template<typename Derived> -StmtResult -TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) { +template <typename Derived> +StmtResult TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) { // Transform the try block itself. - StmtResult TryBlock - = getDerived().TransformCompoundStmt(S->getTryBlock()); + StmtResult TryBlock = getDerived().TransformCompoundStmt(S->getTryBlock()); if (TryBlock.isInvalid()) return StmtError(); // Transform the handlers. bool HandlerChanged = false; - SmallVector<Stmt*, 8> Handlers; + SmallVector<Stmt *, 8> Handlers; for (unsigned I = 0, N = S->getNumHandlers(); I != N; ++I) { - StmtResult Handler - = getDerived().TransformCXXCatchStmt(S->getHandler(I)); + StmtResult Handler = getDerived().TransformCXXCatchStmt(S->getHandler(I)); if (Handler.isInvalid()) return StmtError(); @@ -5937,8 +6055,7 @@ TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) { Handlers.push_back(Handler.takeAs<Stmt>()); } - if (!getDerived().AlwaysRebuild() && - TryBlock.get() == S->getTryBlock() && + if (!getDerived().AlwaysRebuild() && TryBlock.get() == S->getTryBlock() && !HandlerChanged) return SemaRef.Owned(S); @@ -6110,57 +6227,166 @@ TreeTransform<Derived>::TransformMSPropertyRefExpr(MSPropertyRefExpr *E) { QualifierLoc, E->getMemberLoc()); } -template<typename Derived> -StmtResult -TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) { - StmtResult TryBlock; // = getDerived().TransformCompoundStmt(S->getTryBlock()); - if(TryBlock.isInvalid()) return StmtError(); +template <typename Derived> +StmtResult TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) { + StmtResult TryBlock = getDerived().TransformCompoundStmt(S->getTryBlock()); + if (TryBlock.isInvalid()) + return StmtError(); StmtResult Handler = getDerived().TransformSEHHandler(S->getHandler()); - if(!getDerived().AlwaysRebuild() && - TryBlock.get() == S->getTryBlock() && - Handler.get() == S->getHandler()) + if (Handler.isInvalid()) + return StmtError(); + + if (!getDerived().AlwaysRebuild() && TryBlock.get() == S->getTryBlock() && + Handler.get() == S->getHandler()) return SemaRef.Owned(S); - return getDerived().RebuildSEHTryStmt(S->getIsCXXTry(), - S->getTryLoc(), - TryBlock.take(), - Handler.take()); + return getDerived().RebuildSEHTryStmt(S->getIsCXXTry(), S->getTryLoc(), + TryBlock.take(), Handler.take()); } -template<typename Derived> -StmtResult -TreeTransform<Derived>::TransformSEHFinallyStmt(SEHFinallyStmt *S) { - StmtResult Block; // = getDerived().TransformCompoundStatement(S->getBlock()); - if(Block.isInvalid()) return StmtError(); +template <typename Derived> +StmtResult TreeTransform<Derived>::TransformSEHFinallyStmt(SEHFinallyStmt *S) { + StmtResult Block = getDerived().TransformCompoundStmt(S->getBlock()); + if (Block.isInvalid()) + return StmtError(); - return getDerived().RebuildSEHFinallyStmt(S->getFinallyLoc(), - Block.take()); + return getDerived().RebuildSEHFinallyStmt(S->getFinallyLoc(), Block.take()); } -template<typename Derived> -StmtResult -TreeTransform<Derived>::TransformSEHExceptStmt(SEHExceptStmt *S) { +template <typename Derived> +StmtResult TreeTransform<Derived>::TransformSEHExceptStmt(SEHExceptStmt *S) { ExprResult FilterExpr = getDerived().TransformExpr(S->getFilterExpr()); - if(FilterExpr.isInvalid()) return StmtError(); + if (FilterExpr.isInvalid()) + return StmtError(); - StmtResult Block; // = getDerived().TransformCompoundStatement(S->getBlock()); - if(Block.isInvalid()) return StmtError(); + StmtResult Block = getDerived().TransformCompoundStmt(S->getBlock()); + if (Block.isInvalid()) + return StmtError(); - return getDerived().RebuildSEHExceptStmt(S->getExceptLoc(), - FilterExpr.take(), + return getDerived().RebuildSEHExceptStmt(S->getExceptLoc(), FilterExpr.take(), Block.take()); } -template<typename Derived> -StmtResult -TreeTransform<Derived>::TransformSEHHandler(Stmt *Handler) { - if(isa<SEHFinallyStmt>(Handler)) +template <typename Derived> +StmtResult TreeTransform<Derived>::TransformSEHHandler(Stmt *Handler) { + if (isa<SEHFinallyStmt>(Handler)) return getDerived().TransformSEHFinallyStmt(cast<SEHFinallyStmt>(Handler)); else return getDerived().TransformSEHExceptStmt(cast<SEHExceptStmt>(Handler)); } +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective *D) { + DeclarationNameInfo DirName; + getSema().StartOpenMPDSABlock(OMPD_parallel, DirName, 0); + + // Transform the clauses + llvm::SmallVector<OMPClause *, 16> TClauses; + ArrayRef<OMPClause *> Clauses = D->clauses(); + TClauses.reserve(Clauses.size()); + for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end(); + I != E; ++I) { + if (*I) { + OMPClause *Clause = getDerived().TransformOMPClause(*I); + if (!Clause) { + getSema().EndOpenMPDSABlock(0); + return StmtError(); + } + TClauses.push_back(Clause); + } + else { + TClauses.push_back(0); + } + } + if (!D->getAssociatedStmt()) { + getSema().EndOpenMPDSABlock(0); + return StmtError(); + } + StmtResult AssociatedStmt = + getDerived().TransformStmt(D->getAssociatedStmt()); + if (AssociatedStmt.isInvalid()) { + getSema().EndOpenMPDSABlock(0); + return StmtError(); + } + + StmtResult Res = getDerived().RebuildOMPParallelDirective(TClauses, + AssociatedStmt.take(), + D->getLocStart(), + D->getLocEnd()); + getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + +template<typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPDefaultClause(OMPDefaultClause *C) { + return getDerived().RebuildOMPDefaultClause(C->getDefaultKind(), + C->getDefaultKindKwLoc(), + C->getLocStart(), + C->getLParenLoc(), + C->getLocEnd()); +} + +template<typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) { + llvm::SmallVector<Expr *, 16> Vars; + Vars.reserve(C->varlist_size()); + for (OMPPrivateClause::varlist_iterator I = C->varlist_begin(), + E = C->varlist_end(); + I != E; ++I) { + ExprResult EVar = getDerived().TransformExpr(cast<Expr>(*I)); + if (EVar.isInvalid()) + return 0; + Vars.push_back(EVar.take()); + } + return getDerived().RebuildOMPPrivateClause(Vars, + C->getLocStart(), + C->getLParenLoc(), + C->getLocEnd()); +} + +template<typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPFirstprivateClause( + OMPFirstprivateClause *C) { + llvm::SmallVector<Expr *, 16> Vars; + Vars.reserve(C->varlist_size()); + for (OMPFirstprivateClause::varlist_iterator I = C->varlist_begin(), + E = C->varlist_end(); + I != E; ++I) { + ExprResult EVar = getDerived().TransformExpr(cast<Expr>(*I)); + if (EVar.isInvalid()) + return 0; + Vars.push_back(EVar.take()); + } + return getDerived().RebuildOMPFirstprivateClause(Vars, + C->getLocStart(), + C->getLParenLoc(), + C->getLocEnd()); +} + +template<typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPSharedClause(OMPSharedClause *C) { + llvm::SmallVector<Expr *, 16> Vars; + Vars.reserve(C->varlist_size()); + for (OMPSharedClause::varlist_iterator I = C->varlist_begin(), + E = C->varlist_end(); + I != E; ++I) { + ExprResult EVar = getDerived().TransformExpr(cast<Expr>(*I)); + if (EVar.isInvalid()) + return 0; + Vars.push_back(EVar.take()); + } + return getDerived().RebuildOMPSharedClause(Vars, + C->getLocStart(), + C->getLParenLoc(), + C->getLocEnd()); +} + //===----------------------------------------------------------------------===// // Expression transformation //===----------------------------------------------------------------------===// @@ -6291,9 +6517,8 @@ TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) { E->getDefaultLoc(), E->getRParenLoc(), ControllingExpr.release(), - AssocTypes.data(), - AssocExprs.data(), - E->getNumAssocs()); + AssocTypes, + AssocExprs); } template<typename Derived> @@ -6325,7 +6550,11 @@ TreeTransform<Derived>::TransformAddressOfOperand(Expr *E) { template<typename Derived> ExprResult TreeTransform<Derived>::TransformUnaryOperator(UnaryOperator *E) { - ExprResult SubExpr = TransformAddressOfOperand(E->getSubExpr()); + ExprResult SubExpr; + if (E->getOpcode() == UO_AddrOf) + SubExpr = TransformAddressOfOperand(E->getSubExpr()); + else + SubExpr = TransformExpr(E->getSubExpr()); if (SubExpr.isInvalid()) return ExprError(); @@ -7167,7 +7396,7 @@ TreeTransform<Derived>::TransformCXXFunctionalCastExpr( return SemaRef.Owned(E); return getDerived().RebuildCXXFunctionalCastExpr(Type, - /*FIXME:*/E->getSubExpr()->getLocStart(), + E->getLParenLoc(), SubExpr.get(), E->getRParenLoc()); } @@ -7263,18 +7492,7 @@ TreeTransform<Derived>::TransformCXXNullPtrLiteralExpr( template<typename Derived> ExprResult TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) { - DeclContext *DC = getSema().getFunctionLevelDeclContext(); - QualType T; - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) - T = MD->getThisType(getSema().Context); - else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) { - T = getSema().Context.getPointerType( - getSema().Context.getRecordType(Record)); - } else { - assert(SemaRef.Context.getDiagnostics().hasErrorOccurred() && - "this in the wrong scope?"); - return ExprError(); - } + QualType T = getSema().getCurrentThisType(); if (!getDerived().AlwaysRebuild() && T == E->getType()) { // Make sure that we capture 'this'. @@ -7604,8 +7822,10 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr( // This can happen because of dependent hiding. if (isa<UsingShadowDecl>(*I)) continue; - else + else { + R.clear(); return ExprError(); + } } // Expand using declarations. @@ -7640,8 +7860,10 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr( = cast_or_null<CXXRecordDecl>(getDerived().TransformDecl( Old->getNameLoc(), Old->getNamingClass())); - if (!NamingClass) + if (!NamingClass) { + R.clear(); return ExprError(); + } R.setNamingClass(NamingClass); } @@ -7659,8 +7881,10 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr( if (Old->hasExplicitTemplateArgs() && getDerived().TransformTemplateArguments(Old->getTemplateArgs(), Old->getNumTemplateArgs(), - TransArgs)) + TransArgs)) { + R.clear(); return ExprError(); + } return getDerived().RebuildTemplateIdExpr(SS, TemplateKWLoc, R, Old->requiresADL(), &TransArgs); @@ -7787,6 +8011,19 @@ TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) { if (To.isNull()) return ExprError(); + if (To->containsUnexpandedParameterPack()) { + 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)); } @@ -7885,6 +8122,7 @@ ExprResult TreeTransform<Derived>::TransformDependentScopeDeclRefExpr( DependentScopeDeclRefExpr *E, bool IsAddressOfOperand) { + assert(E->getQualifierLoc()); NestedNameSpecifierLoc QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc()); if (!QualifierLoc) @@ -7976,7 +8214,7 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) { E->isListInitialization(), E->requiresZeroInitialization(), E->getConstructionKind(), - E->getParenRange()); + E->getParenOrBraceRange()); } /// \brief Transform a C++ temporary-binding expression. @@ -8041,57 +8279,157 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr( template<typename Derived> ExprResult TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { - // Transform the type of the lambda parameters and start the definition of - // the lambda itself. - TypeSourceInfo *MethodTy - = TransformType(E->getCallOperator()->getTypeSourceInfo()); - if (!MethodTy) + + // Transform any init-capture expressions before entering the scope of the + // lambda body, because they are not semantically within that scope. + SmallVector<InitCaptureInfoTy, 8> InitCaptureExprsAndTypes; + InitCaptureExprsAndTypes.resize(E->explicit_capture_end() - + E->explicit_capture_begin()); + + for (LambdaExpr::capture_iterator C = E->capture_begin(), + CEnd = E->capture_end(); + C != CEnd; ++C) { + if (!C->isInitCapture()) + continue; + EnterExpressionEvaluationContext EEEC(getSema(), + Sema::PotentiallyEvaluated); + ExprResult NewExprInitResult = getDerived().TransformInitializer( + C->getCapturedVar()->getInit(), + C->getCapturedVar()->getInitStyle() == VarDecl::CallInit); + + if (NewExprInitResult.isInvalid()) + return ExprError(); + Expr *NewExprInit = NewExprInitResult.get(); + + VarDecl *OldVD = C->getCapturedVar(); + QualType NewInitCaptureType = + getSema().performLambdaInitCaptureInitialization(C->getLocation(), + OldVD->getType()->isReferenceType(), OldVD->getIdentifier(), + NewExprInit); + NewExprInitResult = NewExprInit; + InitCaptureExprsAndTypes[C - E->capture_begin()] = + std::make_pair(NewExprInitResult, NewInitCaptureType); + + } + + LambdaScopeInfo *LSI = getSema().PushLambdaScope(); + // Transform the template parameters, and add them to the current + // instantiation scope. The null case is handled correctly. + LSI->GLTemplateParameterList = getDerived().TransformTemplateParameterList( + E->getTemplateParameterList()); + + // Check to see if the TypeSourceInfo of the call operator needs to + // be transformed, and if so do the transformation in the + // CurrentInstantiationScope. + + TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo(); + FunctionProtoTypeLoc OldCallOpFPTL = + OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>(); + TypeSourceInfo *NewCallOpTSI = 0; + + const bool CallOpWasAlreadyTransformed = + getDerived().AlreadyTransformed(OldCallOpTSI->getType()); + + // Use the Old Call Operator's TypeSourceInfo if it is already transformed. + if (CallOpWasAlreadyTransformed) + NewCallOpTSI = OldCallOpTSI; + else { + // Transform the TypeSourceInfo of the Original Lambda's Call Operator. + // The transformation MUST be done in the CurrentInstantiationScope since + // it introduces a mapping of the original to the newly created + // transformed parameters. + + TypeLocBuilder NewCallOpTLBuilder; + QualType NewCallOpType = TransformFunctionProtoType(NewCallOpTLBuilder, + OldCallOpFPTL, + 0, 0); + NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, + NewCallOpType); + } + // Extract the ParmVarDecls from the NewCallOpTSI and add them to + // the vector below - this will be used to synthesize the + // NewCallOperator. Additionally, add the parameters of the untransformed + // lambda call operator to the CurrentInstantiationScope. + SmallVector<ParmVarDecl *, 4> Params; + { + FunctionProtoTypeLoc NewCallOpFPTL = + NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>(); + ParmVarDecl **NewParamDeclArray = NewCallOpFPTL.getParmArray(); + const unsigned NewNumArgs = NewCallOpFPTL.getNumArgs(); + + for (unsigned I = 0; I < NewNumArgs; ++I) { + // If this call operator's type does not require transformation, + // the parameters do not get added to the current instantiation scope, + // - so ADD them! This allows the following to compile when the enclosing + // template is specialized and the entire lambda expression has to be + // transformed. + // template<class T> void foo(T t) { + // auto L = [](auto a) { + // auto M = [](char b) { <-- note: non-generic lambda + // auto N = [](auto c) { + // int x = sizeof(a); + // x = sizeof(b); <-- specifically this line + // x = sizeof(c); + // }; + // }; + // }; + // } + // foo('a') + if (CallOpWasAlreadyTransformed) + getDerived().transformedLocalDecl(NewParamDeclArray[I], + NewParamDeclArray[I]); + // Add to Params array, so these parameters can be used to create + // the newly transformed call operator. + Params.push_back(NewParamDeclArray[I]); + } + } + + if (!NewCallOpTSI) return ExprError(); // Create the local class that will describe the lambda. CXXRecordDecl *Class = getSema().createLambdaClosureType(E->getIntroducerRange(), - MethodTy, - /*KnownDependent=*/false); - getDerived().transformedLocalDecl(E->getLambdaClass(), Class); + NewCallOpTSI, + /*KnownDependent=*/false, + E->getCaptureDefault()); - // Transform lambda parameters. - SmallVector<QualType, 4> ParamTypes; - SmallVector<ParmVarDecl *, 4> Params; - if (getDerived().TransformFunctionTypeParams(E->getLocStart(), - E->getCallOperator()->param_begin(), - E->getCallOperator()->param_size(), - 0, ParamTypes, &Params)) - return ExprError(); + getDerived().transformedLocalDecl(E->getLambdaClass(), Class); // Build the call operator. - CXXMethodDecl *CallOperator + CXXMethodDecl *NewCallOperator = getSema().startLambdaDefinition(Class, E->getIntroducerRange(), - MethodTy, + NewCallOpTSI, E->getCallOperator()->getLocEnd(), Params); - getDerived().transformAttrs(E->getCallOperator(), CallOperator); + LSI->CallOperator = NewCallOperator; + + getDerived().transformAttrs(E->getCallOperator(), NewCallOperator); - return getDerived().TransformLambdaScope(E, CallOperator); + return getDerived().TransformLambdaScope(E, NewCallOperator, + InitCaptureExprsAndTypes); } template<typename Derived> ExprResult TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E, - CXXMethodDecl *CallOperator) { + CXXMethodDecl *CallOperator, + ArrayRef<InitCaptureInfoTy> InitCaptureExprsAndTypes) { + bool Invalid = false; + // Introduce the context of the call operator. Sema::ContextRAII SavedContext(getSema(), CallOperator); + LambdaScopeInfo *const LSI = getSema().getCurLambda(); // Enter the scope of the lambda. - sema::LambdaScopeInfo *LSI - = getSema().enterLambdaScope(CallOperator, E->getIntroducerRange(), + getSema().buildLambdaScope(LSI, CallOperator, E->getIntroducerRange(), E->getCaptureDefault(), + E->getCaptureDefaultLoc(), E->hasExplicitParameters(), E->hasExplicitResultType(), E->isMutable()); // Transform captures. - bool Invalid = false; bool FinishedExplicitCaptures = false; for (LambdaExpr::capture_iterator C = E->capture_begin(), CEnd = E->capture_end(); @@ -8109,6 +8447,32 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E, continue; } + // Rebuild init-captures, including the implied field declaration. + if (C->isInitCapture()) { + + InitCaptureInfoTy InitExprTypePair = + InitCaptureExprsAndTypes[C - E->capture_begin()]; + ExprResult Init = InitExprTypePair.first; + QualType InitQualType = InitExprTypePair.second; + if (Init.isInvalid() || InitQualType.isNull()) { + Invalid = true; + continue; + } + VarDecl *OldVD = C->getCapturedVar(); + VarDecl *NewVD = getSema().createLambdaInitCaptureVarDecl( + OldVD->getLocation(), InitExprTypePair.second, + OldVD->getIdentifier(), Init.get()); + if (!NewVD) + Invalid = true; + else { + getDerived().transformedLocalDecl(OldVD, NewVD); + } + getSema().buildInitCaptureField(LSI, NewVD); + continue; + } + + assert(C->capturesVariable() && "unexpected kind of lambda capture"); + // Determine the capture kind for Sema. Sema::TryCaptureKind Kind = C->isImplicit()? Sema::TryCapture_Implicit @@ -8125,8 +8489,10 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E, C->getLocation(), Unexpanded, ShouldExpand, RetainExpansion, - NumExpansions)) - return ExprError(); + NumExpansions)) { + Invalid = true; + continue; + } if (ShouldExpand) { // The transform has determined that we should perform an expansion; @@ -8521,6 +8887,13 @@ TreeTransform<Derived>::TransformMaterializeTemporaryExpr( template<typename Derived> ExprResult +TreeTransform<Derived>::TransformCXXStdInitializerListExpr( + CXXStdInitializerListExpr *E) { + return getDerived().TransformExpr(E->getSubExpr()); +} + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) { return SemaRef.MaybeBindToTemporary(E); } @@ -8921,6 +9294,27 @@ TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) { template<typename Derived> ExprResult +TreeTransform<Derived>::TransformConvertVectorExpr(ConvertVectorExpr *E) { + ExprResult SrcExpr = getDerived().TransformExpr(E->getSrcExpr()); + if (SrcExpr.isInvalid()) + return ExprError(); + + TypeSourceInfo *Type = getDerived().TransformType(E->getTypeSourceInfo()); + if (!Type) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + Type == E->getTypeSourceInfo() && + SrcExpr.get() == E->getSrcExpr()) + return SemaRef.Owned(E); + + return getDerived().RebuildConvertVectorExpr(E->getBuiltinLoc(), + SrcExpr.get(), Type, + E->getRParenLoc()); +} + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { BlockDecl *oldBlock = E->getBlockDecl(); @@ -8947,15 +9341,6 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { QualType exprResultType = getDerived().TransformType(exprFunctionType->getResultType()); - // Don't allow returning a objc interface by value. - if (exprResultType->isObjCObjectType()) { - getSema().Diag(E->getCaretLocation(), - diag::err_object_cannot_be_passed_returned_by_value) - << 0 << exprResultType; - getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/0); - return ExprError(); - } - QualType functionType = getDerived().RebuildFunctionProtoType(exprResultType, paramTypes, exprFunctionType->getExtProtoInfo()); @@ -9082,7 +9467,7 @@ TreeTransform<Derived>::RebuildArrayType(QualType ElementType, SemaRef.Context.UnsignedIntTy, SemaRef.Context.UnsignedLongTy, SemaRef.Context.UnsignedLongLongTy, SemaRef.Context.UnsignedInt128Ty }; - const unsigned NumTypes = sizeof(Types) / sizeof(QualType); + const unsigned NumTypes = llvm::array_lengthof(Types); QualType SizeType; for (unsigned I = 0; I != NumTypes; ++I) if (Size->getBitWidth() == SemaRef.Context.getIntWidth(Types[I])) { @@ -9198,7 +9583,7 @@ QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(Decl *D) { TypeDecl *Ty; if (isa<UsingDecl>(D)) { UsingDecl *Using = cast<UsingDecl>(D); - assert(Using->isTypeName() && + assert(Using->hasTypename() && "UnresolvedUsingTypenameDecl transformed to non-typename using"); // A valid resolved using typename decl points to exactly one type decl. @@ -9297,7 +9682,7 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS, ParsedType::make(ObjectType), /*EnteringContext=*/false, Template); - return Template.template getAsVal<TemplateName>(); + return Template.get(); } template<typename Derived> diff --git a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.cpp b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.cpp new file mode 100644 index 000000000000..c7d43b704690 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.cpp @@ -0,0 +1,136 @@ +//===--- TypeLocBuilder.cpp - Type Source Info collector ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This files defines TypeLocBuilder, a class for building TypeLocs +// bottom-up. +// +//===----------------------------------------------------------------------===// + +#include "TypeLocBuilder.h" + +using namespace clang; + +void TypeLocBuilder::pushFullCopy(TypeLoc L) { + size_t Size = L.getFullDataSize(); + reserve(Size); + + SmallVector<TypeLoc, 4> TypeLocs; + TypeLoc CurTL = L; + while (CurTL) { + TypeLocs.push_back(CurTL); + CurTL = CurTL.getNextTypeLoc(); + } + + for (unsigned i = 0, e = TypeLocs.size(); i < e; ++i) { + TypeLoc CurTL = TypeLocs[e-i-1]; + switch (CurTL.getTypeLocClass()) { +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ + case TypeLoc::CLASS: { \ + CLASS##TypeLoc NewTL = push<class CLASS##TypeLoc>(CurTL.getType()); \ + memcpy(NewTL.getOpaqueData(), CurTL.getOpaqueData(), NewTL.getLocalDataSize()); \ + break; \ + } +#include "clang/AST/TypeLocNodes.def" + } + } +} + +void TypeLocBuilder::grow(size_t NewCapacity) { + assert(NewCapacity > Capacity); + + // Allocate the new buffer and copy the old data into it. + char *NewBuffer = new char[NewCapacity]; + unsigned NewIndex = Index + NewCapacity - Capacity; + memcpy(&NewBuffer[NewIndex], + &Buffer[Index], + Capacity - Index); + + if (Buffer != InlineBuffer.buffer) + delete[] Buffer; + + Buffer = NewBuffer; + Capacity = NewCapacity; + Index = NewIndex; +} + +TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) { +#ifndef NDEBUG + QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType(); + assert(TLast == LastTy && + "mismatch between last type and new type's inner type"); + LastTy = T; +#endif + + assert(LocalAlignment <= BufferMaxAlignment && "Unexpected alignment"); + + // If we need to grow, grow by a factor of 2. + if (LocalSize > Index) { + size_t RequiredCapacity = Capacity + (LocalSize - Index); + size_t NewCapacity = Capacity * 2; + while (RequiredCapacity > NewCapacity) + NewCapacity *= 2; + grow(NewCapacity); + } + + // Because we're adding elements to the TypeLoc backwards, we have to + // do some extra work to keep everything aligned appropriately. + // FIXME: This algorithm is a absolute mess because every TypeLoc returned + // needs to be valid. Partial TypeLocs are a terrible idea. + // FIXME: 4 and 8 are sufficient at the moment, but it's pretty ugly to + // hardcode them. + if (LocalAlignment == 4) { + if (NumBytesAtAlign8 == 0) { + NumBytesAtAlign4 += LocalSize; + } else { + unsigned Padding = NumBytesAtAlign4 % 8; + if (Padding == 0) { + if (LocalSize % 8 == 0) { + // Everything is set: there's no padding and we don't need to add + // any. + } else { + assert(LocalSize % 8 == 4); + // No existing padding; add in 4 bytes padding + memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4); + Index -= 4; + } + } else { + assert(Padding == 4); + if (LocalSize % 8 == 0) { + // Everything is set: there's 4 bytes padding and we don't need + // to add any. + } else { + assert(LocalSize % 8 == 4); + // There are 4 bytes padding, but we don't need any; remove it. + memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4); + Index += 4; + } + } + NumBytesAtAlign4 += LocalSize; + } + } else if (LocalAlignment == 8) { + if (!NumBytesAtAlign8 && NumBytesAtAlign4 % 8 != 0) { + // No existing padding and misaligned members; add in 4 bytes padding + memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4); + Index -= 4; + } + // Forget about any padding. + NumBytesAtAlign4 = 0; + NumBytesAtAlign8 += LocalSize; + } else { + assert(LocalSize == 0); + } + + Index -= LocalSize; + + assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) && + "incorrect data size provided to CreateTypeSourceInfo!"); + + return getTemporaryTypeLoc(T); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h index f36ec9f3e209..b1e909859b2f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h +++ b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h @@ -39,14 +39,19 @@ class TypeLocBuilder { #endif /// The inline buffer. - char InlineBuffer[InlineCapacity]; + enum { BufferMaxAlignment = llvm::AlignOf<void*>::Alignment }; + llvm::AlignedCharArray<BufferMaxAlignment, InlineCapacity> InlineBuffer; + unsigned NumBytesAtAlign4, NumBytesAtAlign8; public: TypeLocBuilder() - : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) {} + : Buffer(InlineBuffer.buffer), Capacity(InlineCapacity), + Index(InlineCapacity), NumBytesAtAlign4(0), NumBytesAtAlign8(0) + { + } ~TypeLocBuilder() { - if (Buffer != InlineBuffer) + if (Buffer != InlineBuffer.buffer) delete[] Buffer; } @@ -59,23 +64,14 @@ class TypeLocBuilder { /// Pushes a copy of the given TypeLoc onto this builder. The builder /// must be empty for this to work. - void pushFullCopy(TypeLoc L) { - size_t Size = L.getFullDataSize(); - TypeLoc Copy = pushFullUninitializedImpl(L.getType(), Size); - memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size); - } - - /// Pushes uninitialized space for the given type. The builder must - /// be empty. - TypeLoc pushFullUninitialized(QualType T) { - return pushFullUninitializedImpl(T, TypeLoc::getFullDataSizeForType(T)); - } + void pushFullCopy(TypeLoc L); /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs /// previously retrieved from this builder. TypeSpecTypeLoc pushTypeSpec(QualType T) { size_t LocalSize = TypeSpecTypeLoc::LocalDataSize; - return pushImpl(T, LocalSize).castAs<TypeSpecTypeLoc>(); + unsigned LocalAlign = TypeSpecTypeLoc::LocalDataAlignment; + return pushImpl(T, LocalSize, LocalAlign).castAs<TypeSpecTypeLoc>(); } /// Resets this builder to the newly-initialized state. @@ -84,6 +80,7 @@ class TypeLocBuilder { LastTy = QualType(); #endif Index = Capacity; + NumBytesAtAlign4 = NumBytesAtAlign8 = 0; } /// \brief Tell the TypeLocBuilder that the type it is storing has been @@ -97,8 +94,10 @@ class TypeLocBuilder { /// Pushes space for a new TypeLoc of the given type. Invalidates /// any TypeLocs previously retrieved from this builder. template <class TyLocType> TyLocType push(QualType T) { - size_t LocalSize = TypeLoc(T, 0).castAs<TyLocType>().getLocalDataSize(); - return pushImpl(T, LocalSize).castAs<TyLocType>(); + TyLocType Loc = TypeLoc(T, 0).castAs<TyLocType>(); + size_t LocalSize = Loc.getLocalDataSize(); + unsigned LocalAlign = Loc.getLocalDataAlignment(); + return pushImpl(T, LocalSize, LocalAlign).castAs<TyLocType>(); } /// Creates a TypeSourceInfo for the given type. @@ -127,61 +126,12 @@ class TypeLocBuilder { } private: - TypeLoc pushImpl(QualType T, size_t LocalSize) { -#ifndef NDEBUG - QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType(); - assert(TLast == LastTy && - "mismatch between last type and new type's inner type"); - LastTy = T; -#endif - - // If we need to grow, grow by a factor of 2. - if (LocalSize > Index) { - size_t RequiredCapacity = Capacity + (LocalSize - Index); - size_t NewCapacity = Capacity * 2; - while (RequiredCapacity > NewCapacity) - NewCapacity *= 2; - grow(NewCapacity); - } - Index -= LocalSize; - - return getTemporaryTypeLoc(T); - } + TypeLoc pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment); /// Grow to the given capacity. - void grow(size_t NewCapacity) { - assert(NewCapacity > Capacity); - - // Allocate the new buffer and copy the old data into it. - char *NewBuffer = new char[NewCapacity]; - unsigned NewIndex = Index + NewCapacity - Capacity; - memcpy(&NewBuffer[NewIndex], - &Buffer[Index], - Capacity - Index); - - if (Buffer != InlineBuffer) - delete[] Buffer; - - Buffer = NewBuffer; - Capacity = NewCapacity; - Index = NewIndex; - } - - TypeLoc pushFullUninitializedImpl(QualType T, size_t Size) { -#ifndef NDEBUG - assert(LastTy.isNull() && "pushing full on non-empty TypeLocBuilder"); - LastTy = T; -#endif - assert(Index == Capacity && "pushing full on non-empty TypeLocBuilder"); - - reserve(Size); - Index -= Size; - - return getTemporaryTypeLoc(T); - } + void grow(size_t NewCapacity); -public: /// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder /// object. /// |