summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
committerdim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
commit9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch)
treec978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
parent03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff)
downloadFreeBSD-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/SemaTemplate.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp1386
1 files changed, 1021 insertions, 365 deletions
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;
OpenPOWER on IntegriCloud