diff options
author | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
commit | 9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch) | |
tree | c978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/tools/clang/lib/Sema | |
parent | 03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff) | |
download | FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz |
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports
all of the features in the current working draft of the upcoming C++
standard, provisionally named C++1y.
The code generator's performance is greatly increased, and the loop
auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The
PowerPC backend has made several major improvements to code generation
quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ
backends have all seen major feature work.
Release notes for llvm and clang can be found here:
<http://llvm.org/releases/3.4/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html>
MFC 262121 (by emaste):
Update lldb for clang/llvm 3.4 import
This commit largely restores the lldb source to the upstream r196259
snapshot with the addition of threaded inferior support and a few bug
fixes.
Specific upstream lldb revisions restored include:
SVN git
181387 779e6ac
181703 7bef4e2
182099 b31044e
182650 f2dcf35
182683 0d91b80
183862 15c1774
183929 99447a6
184177 0b2934b
184948 4dc3761
184954 007e7bc
186990 eebd175
Sponsored by: DARPA, AFRL
MFC 262186 (by emaste):
Fix mismerge in r262121
A break statement was lost in the merge. The error had no functional
impact, but restore it to reduce the diff against upstream.
MFC 262303:
Pull in r197521 from upstream clang trunk (by rdivacky):
Use the integrated assembler by default on FreeBSD/ppc and ppc64.
Requested by: jhibbits
MFC 262611:
Pull in r196874 from upstream llvm trunk:
Fix a crash that occurs when PWD is invalid.
MCJIT needs to be able to run in hostile environments, even when PWD
is invalid. There's no need to crash MCJIT in this case.
The obvious fix is to simply leave MCContext's CompilationDir empty
when PWD can't be determined. This way, MCJIT clients,
and other clients that link with LLVM don't need a valid working directory.
If we do want to guarantee valid CompilationDir, that should be done
only for clients of getCompilationDir(). This is as simple as checking
for an empty string.
The only current use of getCompilationDir is EmitGenDwarfInfo, which
won't conceivably run with an invalid working dir. However, in the
purely hypothetically and untestable case that this happens, the
AT_comp_dir will be omitted from the compilation_unit DIE.
This should help fix assertions occurring with ports-mgmt/tinderbox,
when it is using jails, and sometimes invalidates clang's current
working directory.
Reported by: decke
MFC 262809:
Pull in r203007 from upstream clang trunk:
Don't produce an alias between destructors with different calling conventions.
Fixes pr19007.
(Please note that is an LLVM PR identifier, not a FreeBSD one.)
This should fix Firefox and/or libxul crashes (due to problems with
regparm/stdcall calling conventions) on i386.
Reported by: multiple users on freebsd-current
PR: bin/187103
MFC 263048:
Repair recognition of "CC" as an alias for the C++ compiler, since it
was silently broken by upstream for a Windows-specific use-case.
Apparently some versions of CMake still rely on this archaic feature...
Reported by: rakuco
MFC 263049:
Garbage collect the old way of adding the libstdc++ include directories
in clang's InitHeaderSearch.cpp. This has been superseded by David
Chisnall's commit in r255321.
Moreover, if libc++ is used, the libstdc++ include directories should
not be in the search path at all. These directories are now only used
if you pass -stdlib=libstdc++.
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 1295339..93e3ecf 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 9ac4c63..c980772 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 3b3ab2c..c2f1615 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 d44c1fb..6e354b9 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 5f92cff..d3de173 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 d85624b..ad7627a 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 2f48bec..8b3493e 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 e718be2..4d01fb0 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 3ef1fde..61dc157 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 e12bbde0..8f9ab32 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 01ac8f7..554a114 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 eb11a57..ba00b71 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 7b5f4f0..0530a04 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 fd2ce17..7a1b36b 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 fd7cfeb..328ce70 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 4e5e4b2..3e58386 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 e6a131a..6b3400a 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 f33e7bc..f44fb32 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 1a5f482..3e8f324 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 a9179fd..e1f65f4 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 27032a9..07e4657 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 545ac27..f6accb1 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 cf77896..cc8eace 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 2a845ba..32b56bc 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 a632f02..034c1b6 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 c7ba3cc..a7d5b65 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 9ab3b2d..919c6ad 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 91f0881..d9d9cec 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 c815d4f..c63caf4 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 529ba12..802f2b7 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 054d557..af74f0d 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 248665a..9bd8678 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 fce95be..9169032 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 b9695cc..28603da 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 8efc7a0..8d66ff6 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 7ef04e9..8904f37 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 d1428c5..5c28e3b 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 db885ae..78aa7f8 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 5ce4012..aa7459d 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 2f77012..45067de 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 faa47e8..f940da4 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 0000000..c7d43b7 --- /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 f36ec9f..b1e9098 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. /// |