summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp1265
1 files changed, 820 insertions, 445 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
index 8dda34c..ff8c4da 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
@@ -26,6 +26,8 @@
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "llvm/ADT/SmallBitVector.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
using namespace clang;
using namespace sema;
@@ -42,11 +44,16 @@ clang::getTemplateParamsRange(TemplateParameterList const * const *Ps,
/// of a template and, if so, return that template declaration. Otherwise,
/// returns NULL.
static NamedDecl *isAcceptableTemplateName(ASTContext &Context,
- NamedDecl *Orig) {
+ NamedDecl *Orig,
+ bool AllowFunctionTemplates) {
NamedDecl *D = Orig->getUnderlyingDecl();
- if (isa<TemplateDecl>(D))
+ if (isa<TemplateDecl>(D)) {
+ if (!AllowFunctionTemplates && isa<FunctionTemplateDecl>(D))
+ return 0;
+
return Orig;
+ }
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
// C++ [temp.local]p1:
@@ -76,13 +83,15 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context,
return 0;
}
-void Sema::FilterAcceptableTemplateNames(LookupResult &R) {
+void Sema::FilterAcceptableTemplateNames(LookupResult &R,
+ bool AllowFunctionTemplates) {
// The set of class templates we've already seen.
llvm::SmallPtrSet<ClassTemplateDecl *, 8> ClassTemplates;
LookupResult::Filter filter = R.makeFilter();
while (filter.hasNext()) {
NamedDecl *Orig = filter.next();
- NamedDecl *Repl = isAcceptableTemplateName(Context, Orig);
+ NamedDecl *Repl = isAcceptableTemplateName(Context, Orig,
+ AllowFunctionTemplates);
if (!Repl)
filter.erase();
else if (Repl != Orig) {
@@ -112,9 +121,10 @@ void Sema::FilterAcceptableTemplateNames(LookupResult &R) {
filter.done();
}
-bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R) {
+bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R,
+ bool AllowFunctionTemplates) {
for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I)
- if (isAcceptableTemplateName(Context, *I))
+ if (isAcceptableTemplateName(Context, *I, AllowFunctionTemplates))
return true;
return false;
@@ -128,7 +138,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
bool EnteringContext,
TemplateTy &TemplateResult,
bool &MemberOfUnknownSpecialization) {
- assert(getLangOptions().CPlusPlus && "No template names in C!");
+ assert(getLangOpts().CPlusPlus && "No template names in C!");
DeclarationName TName;
MemberOfUnknownSpecialization = false;
@@ -153,8 +163,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
QualType ObjectType = ObjectTypePtr.get();
- LookupResult R(*this, TName, Name.getSourceRange().getBegin(),
- LookupOrdinaryName);
+ LookupResult R(*this, TName, Name.getLocStart(), LookupOrdinaryName);
LookupTemplateName(R, S, SS, ObjectType, EnteringContext,
MemberOfUnknownSpecialization);
if (R.empty()) return TNK_Non_template;
@@ -249,6 +258,12 @@ void Sema::LookupTemplateName(LookupResult &Found,
isDependent = ObjectType->isDependentType();
assert((isDependent || !ObjectType->isIncompleteType()) &&
"Caller should have completed object type");
+
+ // Template names cannot appear inside an Objective-C class or object type.
+ if (ObjectType->isObjCObjectOrInterfaceType()) {
+ Found.clear();
+ return;
+ }
} else if (SS.isSet()) {
// This nested-name-specifier occurs after another nested-name-specifier,
// so long into the context associated with the prior nested-name-specifier.
@@ -261,13 +276,13 @@ void Sema::LookupTemplateName(LookupResult &Found,
}
bool ObjectTypeSearchedInScope = false;
+ bool AllowFunctionTemplatesInLookup = true;
if (LookupCtx) {
// Perform "qualified" name lookup into the declaration context we
// computed, which is either the type of the base of a member access
// expression or the declaration context associated with a prior
// nested-name-specifier.
LookupQualifiedName(Found, LookupCtx);
-
if (!ObjectType.isNull() && Found.empty()) {
// C++ [basic.lookup.classref]p1:
// In a class member access expression (5.2.5), if the . or -> token is
@@ -280,6 +295,7 @@ void Sema::LookupTemplateName(LookupResult &Found,
// or function template.
if (S) LookupName(Found, S);
ObjectTypeSearchedInScope = true;
+ AllowFunctionTemplatesInLookup = false;
}
} else if (isDependent && (!S || ObjectType.isNull())) {
// We cannot look into a dependent object type or nested nme
@@ -289,23 +305,31 @@ void Sema::LookupTemplateName(LookupResult &Found,
} else {
// Perform unqualified name lookup in the current scope.
LookupName(Found, S);
+
+ if (!ObjectType.isNull())
+ AllowFunctionTemplatesInLookup = false;
}
if (Found.empty() && !isDependent) {
// If we did not find any names, attempt to correct any typos.
DeclarationName Name = Found.getLookupName();
Found.clear();
+ // Simple filter callback that, for keywords, only accepts the C++ *_cast
+ CorrectionCandidateCallback FilterCCC;
+ FilterCCC.WantTypeSpecifiers = false;
+ FilterCCC.WantExpressionKeywords = false;
+ FilterCCC.WantRemainingKeywords = false;
+ FilterCCC.WantCXXNamedCasts = true;
if (TypoCorrection Corrected = CorrectTypo(Found.getLookupNameInfo(),
Found.getLookupKind(), S, &SS,
- LookupCtx, false,
- CTC_CXXCasts)) {
+ FilterCCC, LookupCtx)) {
Found.setLookupName(Corrected.getCorrection());
if (Corrected.getCorrectionDecl())
Found.addDecl(Corrected.getCorrectionDecl());
FilterAcceptableTemplateNames(Found);
if (!Found.empty()) {
- std::string CorrectedStr(Corrected.getAsString(getLangOptions()));
- std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));
+ std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
+ std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
if (LookupCtx)
Diag(Found.getNameLoc(), diag::err_no_member_template_suggest)
<< Name << LookupCtx << CorrectedQuotedStr << SS.getRange()
@@ -323,7 +347,7 @@ void Sema::LookupTemplateName(LookupResult &Found,
}
}
- FilterAcceptableTemplateNames(Found);
+ FilterAcceptableTemplateNames(Found, AllowFunctionTemplatesInLookup);
if (Found.empty()) {
if (isDependent)
MemberOfUnknownSpecialization = true;
@@ -339,7 +363,7 @@ void Sema::LookupTemplateName(LookupResult &Found,
LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(),
LookupOrdinaryName);
LookupName(FoundOuter, S);
- FilterAcceptableTemplateNames(FoundOuter);
+ FilterAcceptableTemplateNames(FoundOuter, /*AllowFunctionTemplates=*/false);
if (FoundOuter.empty()) {
// - if the name is not found, the name found in the class of the
@@ -379,6 +403,7 @@ void Sema::LookupTemplateName(LookupResult &Found,
/// specifier naming a dependent type.
ExprResult
Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
bool isAddressOfOperand,
const TemplateArgumentListInfo *TemplateArgs) {
@@ -398,20 +423,23 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
/*IsArrow*/ true,
/*Op*/ SourceLocation(),
SS.getWithLocInContext(Context),
+ TemplateKWLoc,
FirstQualifierInScope,
NameInfo,
TemplateArgs));
}
- return BuildDependentDeclRefExpr(SS, NameInfo, TemplateArgs);
+ return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs);
}
ExprResult
Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
return Owned(DependentScopeDeclRefExpr::Create(Context,
SS.getWithLocInContext(Context),
+ TemplateKWLoc,
NameInfo,
TemplateArgs));
}
@@ -420,12 +448,12 @@ Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
/// that the template parameter 'PrevDecl' is being shadowed by a new
/// declaration at location Loc. Returns true to indicate that this is
/// an error, and false otherwise.
-bool Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) {
+void Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) {
assert(PrevDecl->isTemplateParameter() && "Not a template parameter");
// Microsoft Visual C++ permits template parameters to be shadowed.
- if (getLangOptions().MicrosoftExt)
- return false;
+ if (getLangOpts().MicrosoftExt)
+ return;
// C++ [temp.local]p4:
// A template-parameter shall not be redeclared within its
@@ -433,7 +461,7 @@ bool Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) {
Diag(Loc, diag::err_template_param_shadow)
<< cast<NamedDecl>(PrevDecl)->getDeclName();
Diag(PrevDecl->getLocation(), diag::note_template_param_here);
- return true;
+ return;
}
/// AdjustDeclIfTemplate - If the given decl happens to be a template, reset
@@ -491,7 +519,6 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
}
llvm_unreachable("Unhandled parsed template argument");
- return TemplateArgumentLoc();
}
/// \brief Translates template arguments as provided by the parser
@@ -528,9 +555,10 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
NamedDecl *PrevDecl = LookupSingleName(S, ParamName, ParamNameLoc,
LookupOrdinaryName,
ForRedeclaration);
- if (PrevDecl && PrevDecl->isTemplateParameter())
- Invalid = Invalid || DiagnoseTemplateParameterShadow(ParamNameLoc,
- PrevDecl);
+ if (PrevDecl && PrevDecl->isTemplateParameter()) {
+ DiagnoseTemplateParameterShadow(ParamNameLoc, PrevDecl);
+ PrevDecl = 0;
+ }
}
SourceLocation Loc = ParamNameLoc;
@@ -615,8 +643,12 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
T->isNullPtrType() ||
// If T is a dependent type, we can't do the check now, so we
// assume that it is well-formed.
- T->isDependentType())
- return T;
+ T->isDependentType()) {
+ // C++ [temp.param]p5: The top-level cv-qualifiers on the template-parameter
+ // are ignored when determining its type.
+ return T.getUnqualifiedType();
+ }
+
// C++ [temp.param]p8:
//
// A non-type template-parameter of type "array of T" or
@@ -652,9 +684,10 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
NamedDecl *PrevDecl = LookupSingleName(S, ParamName, D.getIdentifierLoc(),
LookupOrdinaryName,
ForRedeclaration);
- if (PrevDecl && PrevDecl->isTemplateParameter())
- Invalid = Invalid || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
- PrevDecl);
+ if (PrevDecl && PrevDecl->isTemplateParameter()) {
+ DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+ PrevDecl = 0;
+ }
}
T = CheckNonTypeTemplateParameterType(T, D.getIdentifierLoc());
@@ -666,7 +699,7 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
bool IsParameterPack = D.hasEllipsis();
NonTypeTemplateParmDecl *Param
= NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
- D.getSourceRange().getBegin(),
+ D.getLocStart(),
D.getIdentifierLoc(),
Depth, Position, ParamName, T,
IsParameterPack, TInfo);
@@ -839,7 +872,12 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (SS.isNotEmpty() && !SS.isInvalid()) {
SemanticContext = computeDeclContext(SS, true);
if (!SemanticContext) {
- // FIXME: Produce a reasonable diagnostic here
+ // FIXME: Horrible, horrible hack! We can't currently represent this
+ // in the AST, and historically we have just ignored such friend
+ // class templates, so don't complain here.
+ if (TUK != TUK_Friend)
+ Diag(NameLoc, diag::err_template_qualified_declarator_no_match)
+ << SS.getScopeRep() << SS.getRange();
return true;
}
@@ -853,7 +891,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
ContextRAII SavedContext(*this, SemanticContext);
if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams))
Invalid = true;
- }
+ } else if (TUK != TUK_Friend && TUK != TUK_Reference)
+ diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc);
LookupQualifiedName(Previous, SemanticContext);
} else {
@@ -987,9 +1026,11 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// If the name of the template was qualified, we must be defining the
// template out-of-line.
if (!SS.isInvalid() && !Invalid && !PrevClassTemplate &&
- !(TUK == TUK_Friend && CurContext->isDependentContext()))
+ !(TUK == TUK_Friend && CurContext->isDependentContext())) {
Diag(NameLoc, diag::err_member_def_does_not_match)
<< Name << SemanticContext << SS.getRange();
+ Invalid = true;
+ }
}
CXXRecordDecl *NewClass =
@@ -1003,21 +1044,19 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
NumOuterTemplateParamLists,
OuterTemplateParamLists);
+ // Add alignment attributes if necessary; these attributes are checked when
+ // the ASTContext lays out the structure.
+ AddAlignmentAttributesForRecord(NewClass);
+ AddMsStructLayoutForRecord(NewClass);
+
ClassTemplateDecl *NewTemplate
= ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
DeclarationName(Name), TemplateParams,
NewClass, PrevClassTemplate);
NewClass->setDescribedClassTemplate(NewTemplate);
- if (PrevClassTemplate && PrevClassTemplate->isModulePrivate()) {
+ if (ModulePrivateLoc.isValid())
NewTemplate->setModulePrivate();
- } else if (ModulePrivateLoc.isValid()) {
- if (PrevClassTemplate && !PrevClassTemplate->isModulePrivate())
- diagnoseModulePrivateRedeclaration(NewTemplate, PrevClassTemplate,
- ModulePrivateLoc);
- else
- NewTemplate->setModulePrivate();
- }
// Build the type for the class template declaration now.
QualType T = NewTemplate->getInjectedClassNameSpecialization();
@@ -1032,7 +1071,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
PrevClassTemplate->setMemberSpecialization();
// Set the access specifier.
- if (!Invalid && TUK != TUK_Friend)
+ if (!Invalid && TUK != TUK_Friend && NewTemplate->getDeclContext()->isRecord())
SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS);
// Set the lexical context of these templates
@@ -1059,7 +1098,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Friend templates are visible in fairly strange ways.
if (!CurContext->isDependentContext()) {
DeclContext *DC = SemanticContext->getRedeclContext();
- DC->makeDeclVisibleInContext(NewTemplate, /* Recoverable = */ false);
+ DC->makeDeclVisibleInContext(NewTemplate);
if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
PushOnScopeChains(NewTemplate, EnclosingScope,
/* AddToContext = */ false);
@@ -1103,10 +1142,10 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S,
// template-argument, that declaration shall be a definition and shall be
// the only declaration of the function template in the translation unit.
// (C++98/03 doesn't have this wording; see DR226).
- if (!S.getLangOptions().CPlusPlus0x)
- S.Diag(ParamLoc,
- diag::ext_template_parameter_default_in_function_template)
- << DefArgRange;
+ S.Diag(ParamLoc, S.getLangOpts().CPlusPlus0x ?
+ diag::warn_cxx98_compat_template_parameter_default_in_function_template
+ : diag::ext_template_parameter_default_in_function_template)
+ << DefArgRange;
return false;
case Sema::TPC_ClassTemplateMember:
@@ -1131,7 +1170,7 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S,
// declaration (and it is a definition). Strange!
}
- return false;
+ llvm_unreachable("Invalid TemplateParamListContext!");
}
/// \brief Check for unexpanded parameter packs within the template parameters
@@ -1195,9 +1234,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
bool SawDefaultArgument = false;
SourceLocation PreviousDefaultArgLoc;
- bool SawParameterPack = false;
- SourceLocation ParameterPackLoc;
-
// Dummy initialization to avoid warnings.
TemplateParameterList::iterator OldParam = NewParams->end();
if (OldParams)
@@ -1212,18 +1248,11 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
SourceLocation OldDefaultLoc;
SourceLocation NewDefaultLoc;
- // Variables used to diagnose missing default arguments
+ // Variable used to diagnose missing default arguments
bool MissingDefaultArg = false;
- // C++0x [temp.param]p11:
- // If a template parameter of a primary class template or alias template
- // is a template parameter pack, it shall be the last template parameter.
- if (SawParameterPack &&
- (TPC == TPC_ClassTemplate || TPC == TPC_TypeAliasTemplate)) {
- Diag(ParameterPackLoc,
- diag::err_template_param_pack_must_be_last_template_parameter);
- Invalid = true;
- }
+ // Variable used to diagnose non-final parameter packs
+ bool SawParameterPack = false;
if (TemplateTypeParmDecl *NewTypeParm
= dyn_cast<TemplateTypeParmDecl>(*NewParam)) {
@@ -1243,7 +1272,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
assert(!NewTypeParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!");
SawParameterPack = true;
- ParameterPackLoc = NewTypeParm->getLocation();
} else if (OldTypeParm && OldTypeParm->hasDefaultArgument() &&
NewTypeParm->hasDefaultArgument()) {
OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc();
@@ -1288,7 +1316,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
assert(!NewNonTypeParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!");
SawParameterPack = true;
- ParameterPackLoc = NewNonTypeParm->getLocation();
} else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() &&
NewNonTypeParm->hasDefaultArgument()) {
OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc();
@@ -1313,16 +1340,16 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
} else if (SawDefaultArgument)
MissingDefaultArg = true;
} else {
- // Check the presence of a default argument here.
TemplateTemplateParmDecl *NewTemplateParm
= cast<TemplateTemplateParmDecl>(*NewParam);
// Check for unexpanded parameter packs, recursively.
- if (DiagnoseUnexpandedParameterPacks(*this, NewTemplateParm)) {
+ if (::DiagnoseUnexpandedParameterPacks(*this, NewTemplateParm)) {
Invalid = true;
continue;
}
+ // Check the presence of a default argument here.
if (NewTemplateParm->hasDefaultArgument() &&
DiagnoseDefaultTemplateArgument(*this, TPC,
NewTemplateParm->getLocation(),
@@ -1336,7 +1363,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
assert(!NewTemplateParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!");
SawParameterPack = true;
- ParameterPackLoc = NewTemplateParm->getLocation();
} else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() &&
NewTemplateParm->hasDefaultArgument()) {
OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation();
@@ -1363,6 +1389,16 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
MissingDefaultArg = true;
}
+ // C++0x [temp.param]p11:
+ // If a template parameter of a primary class template or alias template
+ // is a template parameter pack, it shall be the last template parameter.
+ if (SawParameterPack && (NewParam + 1) != NewParamEnd &&
+ (TPC == TPC_ClassTemplate || TPC == TPC_TypeAliasTemplate)) {
+ Diag((*NewParam)->getLocation(),
+ diag::err_template_param_pack_must_be_last_template_parameter);
+ Invalid = true;
+ }
+
if (RedundantDefaultArg) {
// C++ [temp.param]p12:
// A template-parameter shall not be given default arguments
@@ -1878,7 +1914,6 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) {
}
}
-
QualType Sema::CheckTemplateIdType(TemplateName Name,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs) {
@@ -1910,18 +1945,17 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// Check that the template argument list is well-formed for this
// template.
SmallVector<TemplateArgument, 4> Converted;
+ bool ExpansionIntoFixedList = false;
if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs,
- false, Converted))
+ false, Converted, &ExpansionIntoFixedList))
return QualType();
- assert((Converted.size() == Template->getTemplateParameters()->size()) &&
- "Converted template argument list is too short!");
-
QualType CanonType;
bool InstantiationDependent = false;
- if (TypeAliasTemplateDecl *AliasTemplate
- = dyn_cast<TypeAliasTemplateDecl>(Template)) {
+ TypeAliasTemplateDecl *AliasTemplate = 0;
+ if (!ExpansionIntoFixedList &&
+ (AliasTemplate = dyn_cast<TypeAliasTemplateDecl>(Template))) {
// Find the canonical type for this type alias template specialization.
TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl();
if (Pattern->isInvalidDecl())
@@ -2037,11 +2071,12 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
}
TypeResult
-Sema::ActOnTemplateIdType(CXXScopeSpec &SS,
+Sema::ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
TemplateTy TemplateD, SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation RAngleLoc) {
+ SourceLocation RAngleLoc,
+ bool IsCtorOrDtorName) {
if (SS.isInvalid())
return true;
@@ -2052,20 +2087,21 @@ Sema::ActOnTemplateIdType(CXXScopeSpec &SS,
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
- QualType T = Context.getDependentTemplateSpecializationType(ETK_None,
- DTN->getQualifier(),
- DTN->getIdentifier(),
- TemplateArgs);
-
- // Build type-source information.
+ QualType T
+ = Context.getDependentTemplateSpecializationType(ETK_None,
+ DTN->getQualifier(),
+ DTN->getIdentifier(),
+ TemplateArgs);
+ // Build type-source information.
TypeLocBuilder TLB;
DependentTemplateSpecializationTypeLoc SpecTL
= TLB.push<DependentTemplateSpecializationTypeLoc>(T);
- SpecTL.setKeywordLoc(SourceLocation());
- SpecTL.setNameLoc(TemplateLoc);
+ SpecTL.setElaboratedKeywordLoc(SourceLocation());
+ SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
+ SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
+ SpecTL.setTemplateNameLoc(TemplateLoc);
SpecTL.setLAngleLoc(LAngleLoc);
SpecTL.setRAngleLoc(RAngleLoc);
- SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I)
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
@@ -2078,20 +2114,24 @@ Sema::ActOnTemplateIdType(CXXScopeSpec &SS,
return true;
// Build type-source information.
- TypeLocBuilder TLB;
+ TypeLocBuilder TLB;
TemplateSpecializationTypeLoc SpecTL
= TLB.push<TemplateSpecializationTypeLoc>(Result);
+ SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
SpecTL.setTemplateNameLoc(TemplateLoc);
SpecTL.setLAngleLoc(LAngleLoc);
SpecTL.setRAngleLoc(RAngleLoc);
for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i)
SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
- if (SS.isNotEmpty()) {
+ // NOTE: avoid constructing an ElaboratedTypeLoc if this is a
+ // constructor or destructor name (in such a case, the scope specifier
+ // will be attached to the enclosing Decl or Expr node).
+ if (SS.isNotEmpty() && !IsCtorOrDtorName) {
// Create an elaborated-type-specifier containing the nested-name-specifier.
Result = Context.getElaboratedType(ETK_None, SS.getScopeRep(), Result);
ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result);
- ElabTL.setKeywordLoc(SourceLocation());
+ ElabTL.setElaboratedKeywordLoc(SourceLocation());
ElabTL.setQualifierLoc(SS.getWithLocInContext(Context));
}
@@ -2102,7 +2142,8 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
TypeSpecifierType TagSpec,
SourceLocation TagLoc,
CXXScopeSpec &SS,
- TemplateTy TemplateD,
+ SourceLocation TemplateKWLoc,
+ TemplateTy TemplateD,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
@@ -2127,12 +2168,13 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
// Build type-source information.
TypeLocBuilder TLB;
DependentTemplateSpecializationTypeLoc SpecTL
- = TLB.push<DependentTemplateSpecializationTypeLoc>(T);
- SpecTL.setKeywordLoc(TagLoc);
- SpecTL.setNameLoc(TemplateLoc);
+ = TLB.push<DependentTemplateSpecializationTypeLoc>(T);
+ SpecTL.setElaboratedKeywordLoc(TagLoc);
+ SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
+ SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
+ SpecTL.setTemplateNameLoc(TemplateLoc);
SpecTL.setLAngleLoc(LAngleLoc);
SpecTL.setRAngleLoc(RAngleLoc);
- SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I)
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
@@ -2167,11 +2209,12 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
Diag(D->getLocation(), diag::note_previous_use);
}
}
-
+
// Provide source-location information for the template specialization.
TypeLocBuilder TLB;
TemplateSpecializationTypeLoc SpecTL
= TLB.push<TemplateSpecializationTypeLoc>(Result);
+ SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
SpecTL.setTemplateNameLoc(TemplateLoc);
SpecTL.setLAngleLoc(LAngleLoc);
SpecTL.setRAngleLoc(RAngleLoc);
@@ -2179,18 +2222,19 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
// Construct an elaborated type containing the nested-name-specifier (if any)
- // and keyword.
+ // and tag keyword.
Result = Context.getElaboratedType(Keyword, SS.getScopeRep(), Result);
ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result);
- ElabTL.setKeywordLoc(TagLoc);
+ ElabTL.setElaboratedKeywordLoc(TagLoc);
ElabTL.setQualifierLoc(SS.getWithLocInContext(Context));
return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
}
ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
LookupResult &R,
bool RequiresADL,
- const TemplateArgumentListInfo &TemplateArgs) {
+ const TemplateArgumentListInfo *TemplateArgs) {
// FIXME: Can we do any checking at this point? I guess we could check the
// template arguments that we have against the template name, if the template
// name refers to a single template. That's not a terribly common case,
@@ -2211,6 +2255,7 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
UnresolvedLookupExpr *ULE
= UnresolvedLookupExpr::Create(Context, R.getNamingClass(),
SS.getWithLocInContext(Context),
+ TemplateKWLoc,
R.getLookupNameInfo(),
RequiresADL, TemplateArgs,
R.begin(), R.end());
@@ -2221,13 +2266,15 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
// We actually only call this from template instantiation.
ExprResult
Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
- const TemplateArgumentListInfo &TemplateArgs) {
+ const TemplateArgumentListInfo *TemplateArgs) {
+ assert(TemplateArgs || TemplateKWLoc.isValid());
DeclContext *DC;
if (!(DC = computeDeclContext(SS, false)) ||
DC->isDependentContext() ||
RequireCompleteDeclContext(SS, DC))
- return BuildDependentDeclRefExpr(SS, NameInfo, &TemplateArgs);
+ return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs);
bool MemberOfUnknownSpecialization;
LookupResult R(*this, NameInfo, LookupOrdinaryName);
@@ -2251,7 +2298,7 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
return ExprError();
}
- return BuildTemplateIdExpr(SS, R, /* ADL */ false, TemplateArgs);
+ return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/ false, TemplateArgs);
}
/// \brief Form a dependent template name.
@@ -2262,15 +2309,17 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
/// SS will be "MetaFun::", \p TemplateKWLoc contains the location
/// of the "template" keyword, and "apply" is the \p Name.
TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
- SourceLocation TemplateKWLoc,
CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
UnqualifiedId &Name,
ParsedType ObjectType,
bool EnteringContext,
TemplateTy &Result) {
- if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent() &&
- !getLangOptions().CPlusPlus0x)
- Diag(TemplateKWLoc, diag::ext_template_outside_of_template)
+ if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent())
+ Diag(TemplateKWLoc,
+ getLangOpts().CPlusPlus0x ?
+ diag::warn_cxx98_compat_template_outside_of_template :
+ diag::ext_template_outside_of_template)
<< FixItHint::CreateRemoval(TemplateKWLoc);
DeclContext *LookupCtx = 0;
@@ -2305,7 +2354,7 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases())) {
// This is a dependent template. Handle it below.
} else if (TNK == TNK_Non_template) {
- Diag(Name.getSourceRange().getBegin(),
+ Diag(Name.getLocStart(),
diag::err_template_kw_refers_to_non_template)
<< GetNameFromUnqualifiedId(Name).getName()
<< Name.getSourceRange()
@@ -2339,7 +2388,7 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
break;
}
- Diag(Name.getSourceRange().getBegin(),
+ Diag(Name.getLocStart(),
diag::err_template_kw_refers_to_non_template)
<< GetNameFromUnqualifiedId(Name).getName()
<< Name.getSourceRange()
@@ -2391,7 +2440,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
// Objective-C ARC:
// If an explicitly-specified template argument type is a lifetime type
// with no lifetime qualifier, the __strong lifetime qualifier is inferred.
- if (getLangOptions().ObjCAutoRefCount &&
+ if (getLangOpts().ObjCAutoRefCount &&
ArgType->isObjCLifetimeType() &&
!ArgType.getObjCLifetime()) {
Qualifiers Qs;
@@ -2729,9 +2778,14 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
CXXScopeSpec SS;
SS.Adopt(Arg.getTemplateQualifierLoc());
+ // FIXME: the template-template arg was a DependentTemplateName,
+ // so it was provided with a template keyword. However, its source
+ // location is not stored in the template argument structure.
+ SourceLocation TemplateKWLoc;
ExprResult E = Owned(DependentScopeDeclRefExpr::Create(Context,
SS.getWithLocInContext(Context),
- NameInfo));
+ TemplateKWLoc,
+ NameInfo, 0));
// If we parsed the template argument as a pack expansion, create a
// pack expansion expression.
@@ -2782,7 +2836,6 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
case TemplateArgument::Pack:
llvm_unreachable("Caller must expand template argument packs");
- break;
}
return false;
@@ -2828,33 +2881,55 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
// We have a template template parameter but the template
// argument does not refer to a template.
Diag(Arg.getLocation(), diag::err_template_arg_must_be_template)
- << getLangOptions().CPlusPlus0x;
+ << getLangOpts().CPlusPlus0x;
return true;
case TemplateArgument::Declaration:
- llvm_unreachable(
- "Declaration argument with template template parameter");
- break;
+ llvm_unreachable("Declaration argument with template template parameter");
case TemplateArgument::Integral:
- llvm_unreachable(
- "Integral argument with template template parameter");
- break;
+ llvm_unreachable("Integral argument with template template parameter");
case TemplateArgument::Pack:
llvm_unreachable("Caller must expand template argument packs");
- break;
}
return false;
}
+/// \brief Diagnose an arity mismatch in the
+static bool diagnoseArityMismatch(Sema &S, TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ TemplateArgumentListInfo &TemplateArgs) {
+ TemplateParameterList *Params = Template->getTemplateParameters();
+ unsigned NumParams = Params->size();
+ unsigned NumArgs = TemplateArgs.size();
+
+ SourceRange Range;
+ if (NumArgs > NumParams)
+ Range = SourceRange(TemplateArgs[NumParams].getLocation(),
+ TemplateArgs.getRAngleLoc());
+ S.Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
+ << (NumArgs > NumParams)
+ << (isa<ClassTemplateDecl>(Template)? 0 :
+ isa<FunctionTemplateDecl>(Template)? 1 :
+ isa<TemplateTemplateParmDecl>(Template)? 2 : 3)
+ << Template << Range;
+ S.Diag(Template->getLocation(), diag::note_template_decl_here)
+ << Params->getSourceRange();
+ return true;
+}
+
/// \brief Check that the given template argument list is well-formed
/// for specializing the given template.
bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs,
bool PartialTemplateArgs,
- SmallVectorImpl<TemplateArgument> &Converted) {
+ SmallVectorImpl<TemplateArgument> &Converted,
+ bool *ExpansionIntoFixedList) {
+ if (ExpansionIntoFixedList)
+ *ExpansionIntoFixedList = false;
+
TemplateParameterList *Params = Template->getTemplateParameters();
unsigned NumParams = Params->size();
unsigned NumArgs = TemplateArgs.size();
@@ -2864,27 +2939,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
bool HasParameterPack =
NumParams > 0 && Params->getParam(NumParams - 1)->isTemplateParameterPack();
-
- if ((NumArgs > NumParams && !HasParameterPack) ||
- (NumArgs < Params->getMinRequiredArguments() &&
- !PartialTemplateArgs)) {
- // FIXME: point at either the first arg beyond what we can handle,
- // or the '>', depending on whether we have too many or too few
- // arguments.
- SourceRange Range;
- if (NumArgs > NumParams)
- Range = SourceRange(TemplateArgs[NumParams].getLocation(), RAngleLoc);
- Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
- << (NumArgs > NumParams)
- << (isa<ClassTemplateDecl>(Template)? 0 :
- isa<FunctionTemplateDecl>(Template)? 1 :
- isa<TemplateTemplateParmDecl>(Template)? 2 : 3)
- << Template << Range;
- Diag(Template->getLocation(), diag::note_template_decl_here)
- << Params->getSourceRange();
- Invalid = true;
- }
-
+
// C++ [temp.arg]p1:
// [...] The type and form of each template-argument specified in
// a template-id shall match the type and form specified for the
@@ -2896,10 +2951,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
ParamEnd = Params->end();
unsigned ArgIdx = 0;
LocalInstantiationScope InstScope(*this, true);
+ bool SawPackExpansion = false;
while (Param != ParamEnd) {
if (ArgIdx < NumArgs) {
// If we have an expanded parameter pack, make sure we don't have too
// many arguments.
+ // FIXME: This really should fall out from the normal arity checking.
if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
if (NTTP->isExpandedParameterPack() &&
@@ -2933,6 +2990,15 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// Move to the next template parameter.
++Param;
}
+
+ // If this template argument is a pack expansion, record that fact
+ // and break out; we can't actually check any more.
+ if (TemplateArgs[ArgIdx].getArgument().isPackExpansion()) {
+ SawPackExpansion = true;
+ ++ArgIdx;
+ break;
+ }
+
++ArgIdx;
continue;
}
@@ -2952,7 +3018,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if ((*Param)->isTemplateParameterPack())
break;
- // We have a default template argument that we will use.
+ // Check whether we have a default argument.
TemplateArgumentLoc Arg;
// Retrieve the default template argument from the template
@@ -2961,10 +3027,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// (when the template parameter was part of a nested template) into
// the default argument.
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
- if (!TTP->hasDefaultArgument()) {
- assert(Invalid && "Missing default argument");
- break;
- }
+ if (!TTP->hasDefaultArgument())
+ return diagnoseArityMismatch(*this, Template, TemplateLoc,
+ TemplateArgs);
TypeSourceInfo *ArgType = SubstDefaultTemplateArgument(*this,
Template,
@@ -2979,10 +3044,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
ArgType);
} else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
- if (!NTTP->hasDefaultArgument()) {
- assert(Invalid && "Missing default argument");
- break;
- }
+ if (!NTTP->hasDefaultArgument())
+ return diagnoseArityMismatch(*this, Template, TemplateLoc,
+ TemplateArgs);
ExprResult E = SubstDefaultTemplateArgument(*this, Template,
TemplateLoc,
@@ -2998,10 +3062,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
TemplateTemplateParmDecl *TempParm
= cast<TemplateTemplateParmDecl>(*Param);
- if (!TempParm->hasDefaultArgument()) {
- assert(Invalid && "Missing default argument");
- break;
- }
+ if (!TempParm->hasDefaultArgument())
+ return diagnoseArityMismatch(*this, Template, TemplateLoc,
+ TemplateArgs);
NestedNameSpecifierLoc QualifierLoc;
TemplateName Name = SubstDefaultTemplateArgument(*this, Template,
@@ -3039,12 +3102,71 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
++ArgIdx;
}
+ // If we saw a pack expansion, then directly convert the remaining arguments,
+ // because we don't know what parameters they'll match up with.
+ if (SawPackExpansion) {
+ bool AddToArgumentPack
+ = Param != ParamEnd && (*Param)->isTemplateParameterPack();
+ while (ArgIdx < NumArgs) {
+ if (AddToArgumentPack)
+ ArgumentPack.push_back(TemplateArgs[ArgIdx].getArgument());
+ else
+ Converted.push_back(TemplateArgs[ArgIdx].getArgument());
+ ++ArgIdx;
+ }
+
+ // Push the argument pack onto the list of converted arguments.
+ if (AddToArgumentPack) {
+ if (ArgumentPack.empty())
+ Converted.push_back(TemplateArgument(0, 0));
+ else {
+ Converted.push_back(
+ TemplateArgument::CreatePackCopy(Context,
+ ArgumentPack.data(),
+ ArgumentPack.size()));
+ ArgumentPack.clear();
+ }
+ } else if (ExpansionIntoFixedList) {
+ // We have expanded a pack into a fixed list.
+ *ExpansionIntoFixedList = true;
+ }
+
+ return Invalid;
+ }
+
+ // If we have any leftover arguments, then there were too many arguments.
+ // Complain and fail.
+ if (ArgIdx < NumArgs)
+ return diagnoseArityMismatch(*this, Template, TemplateLoc, TemplateArgs);
+
+ // If we have an expanded parameter pack, make sure we don't have too
+ // many arguments.
+ // FIXME: This really should fall out from the normal arity checking.
+ if (Param != ParamEnd) {
+ if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
+ if (NTTP->isExpandedParameterPack() &&
+ ArgumentPack.size() < NTTP->getNumExpansionTypes()) {
+ Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
+ << false
+ << (isa<ClassTemplateDecl>(Template)? 0 :
+ isa<FunctionTemplateDecl>(Template)? 1 :
+ isa<TemplateTemplateParmDecl>(Template)? 2 : 3)
+ << Template;
+ Diag(Template->getLocation(), diag::note_template_decl_here)
+ << Params->getSourceRange();
+ return true;
+ }
+ }
+ }
+
// Form argument packs for each of the parameter packs remaining.
while (Param != ParamEnd) {
// If we're checking a partial list of template arguments, don't fill
// in arguments for non-template parameter packs.
-
if ((*Param)->isTemplateParameterPack()) {
+ if (!HasParameterPack)
+ return true;
if (ArgumentPack.empty())
Converted.push_back(TemplateArgument(0, 0));
else {
@@ -3053,7 +3175,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
ArgumentPack.size()));
ArgumentPack.clear();
}
- }
+ } else if (!PartialTemplateArgs)
+ return diagnoseArityMismatch(*this, Template, TemplateLoc, TemplateArgs);
++Param;
}
@@ -3261,13 +3384,19 @@ bool UnnamedLocalNoLinkageFinder::VisitAtomicType(const AtomicType* T) {
bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) {
if (Tag->getDeclContext()->isFunctionOrMethod()) {
- S.Diag(SR.getBegin(), diag::ext_template_arg_local_type)
+ S.Diag(SR.getBegin(),
+ S.getLangOpts().CPlusPlus0x ?
+ diag::warn_cxx98_compat_template_arg_local_type :
+ diag::ext_template_arg_local_type)
<< S.Context.getTypeDeclType(Tag) << SR;
return true;
}
if (!Tag->getDeclName() && !Tag->getTypedefNameForAnonDecl()) {
- S.Diag(SR.getBegin(), diag::ext_template_arg_unnamed_type) << SR;
+ S.Diag(SR.getBegin(),
+ S.getLangOpts().CPlusPlus0x ?
+ diag::warn_cxx98_compat_template_arg_unnamed_type :
+ diag::ext_template_arg_unnamed_type) << SR;
S.Diag(Tag->getLocation(), diag::note_template_unnamed_type_here);
return true;
}
@@ -3291,7 +3420,7 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier(
case NestedNameSpecifier::TypeSpecWithTemplate:
return Visit(QualType(NNS->getAsType(), 0));
}
- return false;
+ llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
}
@@ -3317,9 +3446,14 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
// compounded from any of these types shall not be used as a
// template-argument for a template type-parameter.
//
- // C++0x allows these, and even in C++03 we allow them as an extension with
+ // C++11 allows these, and even in C++03 we allow them as an extension with
// a warning.
- if (!LangOpts.CPlusPlus0x && Arg->hasUnnamedOrLocalType()) {
+ if (LangOpts.CPlusPlus0x ?
+ Diags.getDiagnosticLevel(diag::warn_cxx98_compat_template_arg_unnamed_type,
+ SR.getBegin()) != DiagnosticsEngine::Ignored ||
+ Diags.getDiagnosticLevel(diag::warn_cxx98_compat_template_arg_local_type,
+ SR.getBegin()) != DiagnosticsEngine::Ignored :
+ Arg->hasUnnamedOrLocalType()) {
UnnamedLocalNoLinkageFinder Finder(*this, SR);
(void)Finder.Visit(Context.getCanonicalType(Arg));
}
@@ -3327,6 +3461,99 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
return false;
}
+enum NullPointerValueKind {
+ NPV_NotNullPointer,
+ NPV_NullPointer,
+ NPV_Error
+};
+
+/// \brief Determine whether the given template argument is a null pointer
+/// value of the appropriate type.
+static NullPointerValueKind
+isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
+ QualType ParamType, Expr *Arg) {
+ if (Arg->isValueDependent() || Arg->isTypeDependent())
+ return NPV_NotNullPointer;
+
+ if (!S.getLangOpts().CPlusPlus0x)
+ return NPV_NotNullPointer;
+
+ // Determine whether we have a constant expression.
+ ExprResult ArgRV = S.DefaultFunctionArrayConversion(Arg);
+ if (ArgRV.isInvalid())
+ return NPV_Error;
+ Arg = ArgRV.take();
+
+ Expr::EvalResult EvalResult;
+ llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+ EvalResult.Diag = &Notes;
+ if (!Arg->EvaluateAsRValue(EvalResult, S.Context) ||
+ EvalResult.HasSideEffects) {
+ SourceLocation DiagLoc = Arg->getExprLoc();
+
+ // If our only note is the usual "invalid subexpression" note, just point
+ // the caret at its location rather than producing an essentially
+ // redundant note.
+ if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
+ diag::note_invalid_subexpr_in_const_expr) {
+ DiagLoc = Notes[0].first;
+ Notes.clear();
+ }
+
+ S.Diag(DiagLoc, diag::err_template_arg_not_address_constant)
+ << Arg->getType() << Arg->getSourceRange();
+ for (unsigned I = 0, N = Notes.size(); I != N; ++I)
+ S.Diag(Notes[I].first, Notes[I].second);
+
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return NPV_Error;
+ }
+
+ // C++11 [temp.arg.nontype]p1:
+ // - an address constant expression of type std::nullptr_t
+ if (Arg->getType()->isNullPtrType())
+ return NPV_NullPointer;
+
+ // - a constant expression that evaluates to a null pointer value (4.10); or
+ // - a constant expression that evaluates to a null member pointer value
+ // (4.11); or
+ if ((EvalResult.Val.isLValue() && !EvalResult.Val.getLValueBase()) ||
+ (EvalResult.Val.isMemberPointer() &&
+ !EvalResult.Val.getMemberPointerDecl())) {
+ // If our expression has an appropriate type, we've succeeded.
+ bool ObjCLifetimeConversion;
+ if (S.Context.hasSameUnqualifiedType(Arg->getType(), ParamType) ||
+ S.IsQualificationConversion(Arg->getType(), ParamType, false,
+ ObjCLifetimeConversion))
+ return NPV_NullPointer;
+
+ // The types didn't match, but we know we got a null pointer; complain,
+ // then recover as if the types were correct.
+ S.Diag(Arg->getExprLoc(), diag::err_template_arg_wrongtype_null_constant)
+ << Arg->getType() << ParamType << Arg->getSourceRange();
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return NPV_NullPointer;
+ }
+
+ // If we don't have a null pointer value, but we do have a NULL pointer
+ // constant, suggest a cast to the appropriate type.
+ if (Arg->isNullPointerConstant(S.Context, Expr::NPC_NeverValueDependent)) {
+ std::string Code = "static_cast<" + ParamType.getAsString() + ">(";
+ S.Diag(Arg->getExprLoc(), diag::err_template_arg_untyped_null_constant)
+ << ParamType
+ << FixItHint::CreateInsertion(Arg->getLocStart(), Code)
+ << FixItHint::CreateInsertion(S.PP.getLocForEndOfToken(Arg->getLocEnd()),
+ ")");
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return NPV_NullPointer;
+ }
+
+ // FIXME: If we ever want to support general, address-constant expressions
+ // as non-type template arguments, we should return the ExprResult here to
+ // be interpreted by the caller.
+ return NPV_NotNullPointer;
+}
+
/// \brief Checks whether the given template argument is the address
/// of an object or function according to C++ [temp.arg.nontype]p1.
static bool
@@ -3339,6 +3566,21 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
Expr *Arg = ArgIn;
QualType ArgType = Arg->getType();
+ // If our parameter has pointer type, check for a null template value.
+ if (ParamType->isPointerType() || ParamType->isNullPtrType()) {
+ switch (isNullPointerValueTemplateArgument(S, Param, ParamType, Arg)) {
+ case NPV_NullPointer:
+ Converted = TemplateArgument((Decl *)0);
+ return false;
+
+ case NPV_Error:
+ return true;
+
+ case NPV_NotNullPointer:
+ break;
+ }
+ }
+
// See through any implicit casts we added to fix the type.
Arg = Arg->IgnoreImpCasts();
@@ -3358,9 +3600,11 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
// See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
bool ExtraParens = false;
while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
- if (!Invalid && !ExtraParens && !S.getLangOptions().CPlusPlus0x) {
- S.Diag(Arg->getSourceRange().getBegin(),
- diag::ext_template_arg_extra_parens)
+ if (!Invalid && !ExtraParens) {
+ S.Diag(Arg->getLocStart(),
+ S.getLangOpts().CPlusPlus0x ?
+ diag::warn_cxx98_compat_template_arg_extra_parens :
+ diag::ext_template_arg_extra_parens)
<< Arg->getSourceRange();
ExtraParens = true;
}
@@ -3382,7 +3626,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
}
}
- if (S.getLangOptions().MicrosoftExt && isa<CXXUuidofExpr>(Arg)) {
+ if (S.getLangOpts().MicrosoftExt && isa<CXXUuidofExpr>(Arg)) {
Converted = TemplateArgument(ArgIn);
return false;
}
@@ -3391,62 +3635,78 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
Arg = subst->getReplacement()->IgnoreImpCasts();
- DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg);
- if (!DRE) {
- S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
- << Arg->getSourceRange();
- S.Diag(Param->getLocation(), diag::note_template_param_here);
- return true;
- }
-
// Stop checking the precise nature of the argument if it is value dependent,
// it should be checked when instantiated.
if (Arg->isValueDependent()) {
Converted = TemplateArgument(ArgIn);
return false;
}
+
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg);
+ if (!DRE) {
+ S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
+ << Arg->getSourceRange();
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
if (!isa<ValueDecl>(DRE->getDecl())) {
- S.Diag(Arg->getSourceRange().getBegin(),
+ S.Diag(Arg->getLocStart(),
diag::err_template_arg_not_object_or_func_form)
<< Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
- NamedDecl *Entity = 0;
+ NamedDecl *Entity = DRE->getDecl();
// Cannot refer to non-static data members
- if (FieldDecl *Field = dyn_cast<FieldDecl>(DRE->getDecl())) {
- S.Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_field)
+ if (FieldDecl *Field = dyn_cast<FieldDecl>(Entity)) {
+ S.Diag(Arg->getLocStart(), diag::err_template_arg_field)
<< Field << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
// Cannot refer to non-static member functions
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(DRE->getDecl()))
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Entity)) {
if (!Method->isStatic()) {
- S.Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_method)
+ S.Diag(Arg->getLocStart(), diag::err_template_arg_method)
<< Method << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
+ }
- // Functions must have external linkage.
- if (FunctionDecl *Func = dyn_cast<FunctionDecl>(DRE->getDecl())) {
- if (!isExternalLinkage(Func->getLinkage())) {
- S.Diag(Arg->getSourceRange().getBegin(),
- diag::err_template_arg_function_not_extern)
- << Func << Arg->getSourceRange();
- S.Diag(Func->getLocation(), diag::note_template_arg_internal_object)
- << true;
- return true;
- }
+ FunctionDecl *Func = dyn_cast<FunctionDecl>(Entity);
+ VarDecl *Var = dyn_cast<VarDecl>(Entity);
+
+ // A non-type template argument must refer to an object or function.
+ if (!Func && !Var) {
+ // We found something, but we don't know specifically what it is.
+ S.Diag(Arg->getLocStart(), diag::err_template_arg_not_object_or_func)
+ << Arg->getSourceRange();
+ S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here);
+ return true;
+ }
- // Okay: we've named a function with external linkage.
- Entity = Func;
+ // Address / reference template args must have external linkage in C++98.
+ if (Entity->getLinkage() == InternalLinkage) {
+ S.Diag(Arg->getLocStart(), S.getLangOpts().CPlusPlus0x ?
+ diag::warn_cxx98_compat_template_arg_object_internal :
+ diag::ext_template_arg_object_internal)
+ << !Func << Entity << Arg->getSourceRange();
+ S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)
+ << !Func;
+ } else if (Entity->getLinkage() == NoLinkage) {
+ S.Diag(Arg->getLocStart(), diag::err_template_arg_object_no_linkage)
+ << !Func << Entity << Arg->getSourceRange();
+ S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)
+ << !Func;
+ return true;
+ }
+ if (Func) {
// If the template parameter has pointer type, the function decays.
if (ParamType->isPointerType() && !AddressTaken)
ArgType = S.Context.getPointerType(Func->getType());
@@ -3469,27 +3729,24 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
ArgType = Func->getType();
}
- } else if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
- if (!isExternalLinkage(Var->getLinkage())) {
- S.Diag(Arg->getSourceRange().getBegin(),
- diag::err_template_arg_object_not_extern)
- << Var << Arg->getSourceRange();
- S.Diag(Var->getLocation(), diag::note_template_arg_internal_object)
- << true;
- return true;
- }
-
+ } else {
// A value of reference type is not an object.
if (Var->getType()->isReferenceType()) {
- S.Diag(Arg->getSourceRange().getBegin(),
+ S.Diag(Arg->getLocStart(),
diag::err_template_arg_reference_var)
<< Var->getType() << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
- // Okay: we've named an object with external linkage
- Entity = Var;
+ // A template argument must have static storage duration.
+ // FIXME: Ensure this works for thread_local as well as __thread.
+ if (Var->isThreadSpecified()) {
+ S.Diag(Arg->getLocStart(), diag::err_template_arg_thread_local)
+ << Arg->getSourceRange();
+ S.Diag(Var->getLocation(), diag::note_template_arg_refers_here);
+ return true;
+ }
// If the template parameter has pointer type, we must have taken
// the address of this object.
@@ -3536,13 +3793,6 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
S.Diag(Param->getLocation(), diag::note_template_param_here);
}
}
- } else {
- // We found something else, but we don't know specifically what it is.
- S.Diag(Arg->getSourceRange().getBegin(),
- diag::err_template_arg_not_object_or_func)
- << Arg->getSourceRange();
- S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here);
- return true;
}
bool ObjCLifetimeConversion;
@@ -3568,7 +3818,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
unsigned ArgQuals = ArgType.getCVRQualifiers();
if ((ParamQuals | ArgQuals) != ParamQuals) {
- S.Diag(Arg->getSourceRange().getBegin(),
+ S.Diag(Arg->getLocStart(),
diag::err_template_arg_ref_bind_ignores_quals)
<< ParamType << Arg->getType()
<< Arg->getSourceRange();
@@ -3597,16 +3847,47 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
// Create the template argument.
Converted = TemplateArgument(Entity->getCanonicalDecl());
- S.MarkDeclarationReferenced(Arg->getLocStart(), Entity);
+ S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity);
return false;
}
/// \brief Checks whether the given template argument is a pointer to
/// member constant according to C++ [temp.arg.nontype]p1.
-bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg,
- TemplateArgument &Converted) {
+static bool CheckTemplateArgumentPointerToMember(Sema &S,
+ NonTypeTemplateParmDecl *Param,
+ QualType ParamType,
+ Expr *&ResultArg,
+ TemplateArgument &Converted) {
bool Invalid = false;
+ // Check for a null pointer value.
+ Expr *Arg = ResultArg;
+ switch (isNullPointerValueTemplateArgument(S, Param, ParamType, Arg)) {
+ case NPV_Error:
+ return true;
+ case NPV_NullPointer:
+ Converted = TemplateArgument((Decl *)0);
+ return false;
+ case NPV_NotNullPointer:
+ break;
+ }
+
+ bool ObjCLifetimeConversion;
+ if (S.IsQualificationConversion(Arg->getType(),
+ ParamType.getNonReferenceType(),
+ false, ObjCLifetimeConversion)) {
+ Arg = S.ImpCastExprToType(Arg, ParamType, CK_NoOp,
+ Arg->getValueKind()).take();
+ ResultArg = Arg;
+ } else if (!S.Context.hasSameUnqualifiedType(Arg->getType(),
+ ParamType.getNonReferenceType())) {
+ // We can't perform this conversion.
+ S.Diag(Arg->getLocStart(), diag::err_template_arg_not_convertible)
+ << Arg->getType() << ParamType << Arg->getSourceRange();
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+
// See through any implicit casts we added to fix the type.
while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
Arg = Cast->getSubExpr();
@@ -3623,9 +3904,11 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg,
// See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
bool ExtraParens = false;
while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
- if (!Invalid && !ExtraParens && !getLangOptions().CPlusPlus0x) {
- Diag(Arg->getSourceRange().getBegin(),
- diag::ext_template_arg_extra_parens)
+ if (!Invalid && !ExtraParens) {
+ S.Diag(Arg->getLocStart(),
+ S.getLangOpts().CPlusPlus0x ?
+ diag::warn_cxx98_compat_template_arg_extra_parens :
+ diag::ext_template_arg_extra_parens)
<< Arg->getSourceRange();
ExtraParens = true;
}
@@ -3651,7 +3934,7 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg,
if (VD->getType()->isMemberPointerType()) {
if (isa<NonTypeTemplateParmDecl>(VD) ||
(isa<VarDecl>(VD) &&
- Context.getCanonicalType(VD->getType()).isConstQualified())) {
+ S.Context.getCanonicalType(VD->getType()).isConstQualified())) {
if (Arg->isTypeDependent() || Arg->isValueDependent())
Converted = TemplateArgument(Arg);
else
@@ -3665,8 +3948,8 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg,
}
if (!DRE)
- return Diag(Arg->getSourceRange().getBegin(),
- diag::err_template_arg_not_pointer_to_member_form)
+ return S.Diag(Arg->getLocStart(),
+ diag::err_template_arg_not_pointer_to_member_form)
<< Arg->getSourceRange();
if (isa<FieldDecl>(DRE->getDecl()) || isa<CXXMethodDecl>(DRE->getDecl())) {
@@ -3684,11 +3967,10 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg,
}
// We found something else, but we don't know specifically what it is.
- Diag(Arg->getSourceRange().getBegin(),
- diag::err_template_arg_not_pointer_to_member_form)
- << Arg->getSourceRange();
- Diag(DRE->getDecl()->getLocation(),
- diag::note_template_arg_refers_here);
+ S.Diag(Arg->getLocStart(),
+ diag::err_template_arg_not_pointer_to_member_form)
+ << Arg->getSourceRange();
+ S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here);
return true;
}
@@ -3704,7 +3986,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
QualType InstantiatedParamType, Expr *Arg,
TemplateArgument &Converted,
CheckTemplateArgumentKind CTAK) {
- SourceLocation StartLoc = Arg->getSourceRange().getBegin();
+ SourceLocation StartLoc = Arg->getLocStart();
// If either the parameter has a dependent type or the argument is
// type-dependent, there's nothing we can check now.
@@ -3720,13 +4002,77 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// template-argument cannot be converted to the type of the
// corresponding template-parameter then the program is
// ill-formed.
- //
- // -- for a non-type template-parameter of integral or
- // enumeration type, integral promotions (4.5) and integral
- // conversions (4.7) are applied.
QualType ParamType = InstantiatedParamType;
- QualType ArgType = Arg->getType();
if (ParamType->isIntegralOrEnumerationType()) {
+ // C++11:
+ // -- for a non-type template-parameter of integral or
+ // enumeration type, conversions permitted in a converted
+ // constant expression are applied.
+ //
+ // C++98:
+ // -- for a non-type template-parameter of integral or
+ // enumeration type, integral promotions (4.5) and integral
+ // conversions (4.7) are applied.
+
+ if (CTAK == CTAK_Deduced &&
+ !Context.hasSameUnqualifiedType(ParamType, Arg->getType())) {
+ // C++ [temp.deduct.type]p17:
+ // If, in the declaration of a function template with a non-type
+ // template-parameter, the non-type template-parameter is used
+ // in an expression in the function parameter-list and, if the
+ // corresponding template-argument is deduced, the
+ // template-argument type shall match the type of the
+ // template-parameter exactly, except that a template-argument
+ // deduced from an array bound may be of any integral type.
+ Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch)
+ << Arg->getType().getUnqualifiedType()
+ << ParamType.getUnqualifiedType();
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return ExprError();
+ }
+
+ if (getLangOpts().CPlusPlus0x) {
+ // We can't check arbitrary value-dependent arguments.
+ // FIXME: If there's no viable conversion to the template parameter type,
+ // we should be able to diagnose that prior to instantiation.
+ if (Arg->isValueDependent()) {
+ Converted = TemplateArgument(Arg);
+ return Owned(Arg);
+ }
+
+ // C++ [temp.arg.nontype]p1:
+ // A template-argument for a non-type, non-template template-parameter
+ // shall be one of:
+ //
+ // -- for a non-type template-parameter of integral or enumeration
+ // type, a converted constant expression of the type of the
+ // template-parameter; or
+ llvm::APSInt Value;
+ ExprResult ArgResult =
+ CheckConvertedConstantExpression(Arg, ParamType, Value,
+ CCEK_TemplateArg);
+ if (ArgResult.isInvalid())
+ return ExprError();
+
+ // Widen the argument value to sizeof(parameter type). This is almost
+ // always a no-op, except when the parameter type is bool. In
+ // that case, this may extend the argument from 1 bit to 8 bits.
+ QualType IntegerType = ParamType;
+ if (const EnumType *Enum = IntegerType->getAs<EnumType>())
+ IntegerType = Enum->getDecl()->getIntegerType();
+ Value = Value.extOrTrunc(Context.getTypeSize(IntegerType));
+
+ Converted = TemplateArgument(Value, Context.getCanonicalType(ParamType));
+ return ArgResult;
+ }
+
+ ExprResult ArgResult = DefaultLvalueConversion(Arg);
+ if (ArgResult.isInvalid())
+ return ExprError();
+ Arg = ArgResult.take();
+
+ QualType ArgType = Arg->getType();
+
// C++ [temp.arg.nontype]p1:
// A template-argument for a non-type, non-template
// template-parameter shall be one of:
@@ -3737,16 +4083,16 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
SourceLocation NonConstantLoc;
llvm::APSInt Value;
if (!ArgType->isIntegralOrEnumerationType()) {
- Diag(Arg->getSourceRange().getBegin(),
+ Diag(Arg->getLocStart(),
diag::err_template_arg_not_integral_or_enumeral)
<< ArgType << Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
return ExprError();
- } else if (!Arg->isValueDependent() &&
- !Arg->isIntegerConstantExpr(Value, Context, &NonConstantLoc)) {
- Diag(NonConstantLoc, diag::err_template_arg_not_ice)
- << ArgType << Arg->getSourceRange();
- return ExprError();
+ } else if (!Arg->isValueDependent()) {
+ Arg = VerifyIntegerConstantExpression(Arg, &Value,
+ PDiag(diag::err_template_arg_not_ice) << ArgType, false).take();
+ if (!Arg)
+ return ExprError();
}
// From here on out, all we care about are the unqualified forms
@@ -3757,19 +4103,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// Try to convert the argument to the parameter's type.
if (Context.hasSameType(ParamType, ArgType)) {
// Okay: no conversion necessary
- } else if (CTAK == CTAK_Deduced) {
- // C++ [temp.deduct.type]p17:
- // If, in the declaration of a function template with a non-type
- // template-parameter, the non-type template- parameter is used
- // in an expression in the function parameter-list and, if the
- // corresponding template-argument is deduced, the
- // template-argument type shall match the type of the
- // template-parameter exactly, except that a template-argument
- // deduced from an array bound may be of any integral type.
- Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch)
- << ArgType << ParamType;
- Diag(Param->getLocation(), diag::note_template_param_here);
- return ExprError();
} else if (ParamType->isBooleanType()) {
// This is an integral-to-boolean conversion.
Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean).take();
@@ -3779,7 +4112,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralCast).take();
} else {
// We can't perform this conversion.
- Diag(Arg->getSourceRange().getBegin(),
+ Diag(Arg->getLocStart(),
diag::err_template_arg_not_convertible)
<< Arg->getType() << InstantiatedParamType << Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
@@ -3820,7 +4153,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// Complain if an unsigned parameter received a negative value.
if (IntegerType->isUnsignedIntegerOrEnumerationType()
&& (OldValue.isSigned() && OldValue.isNegative())) {
- Diag(Arg->getSourceRange().getBegin(), diag::warn_template_arg_negative)
+ Diag(Arg->getLocStart(), diag::warn_template_arg_negative)
<< OldValue.toString(10) << Value.toString(10) << Param->getType()
<< Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
@@ -3835,7 +4168,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
else
RequiredBits = OldValue.getMinSignedBits();
if (RequiredBits > AllowedBits) {
- Diag(Arg->getSourceRange().getBegin(),
+ Diag(Arg->getLocStart(),
diag::warn_template_arg_too_large)
<< OldValue.toString(10) << Value.toString(10) << Param->getType()
<< Arg->getSourceRange();
@@ -3850,25 +4183,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return Owned(Arg);
}
+ QualType ArgType = Arg->getType();
DeclAccessPair FoundResult; // temporary for ResolveOverloadedFunction
- // C++0x [temp.arg.nontype]p5 bullets 2, 4 and 6 permit conversion
- // from a template argument of type std::nullptr_t to a non-type
- // template parameter of type pointer to object, pointer to
- // function, or pointer-to-member, respectively.
- if (ArgType->isNullPtrType()) {
- if (ParamType->isPointerType() || ParamType->isMemberPointerType()) {
- Converted = TemplateArgument((NamedDecl *)0);
- return Owned(Arg);
- }
-
- if (ParamType->isNullPtrType()) {
- llvm::APSInt Zero(Context.getTypeSize(Context.NullPtrTy), true);
- Converted = TemplateArgument(Zero, Context.NullPtrTy);
- return Owned(Arg);
- }
- }
-
// Handle pointer-to-function, reference-to-function, and
// pointer-to-member-function all in (roughly) the same way.
if (// -- For a non-type template-parameter of type pointer to
@@ -3897,7 +4214,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType,
true,
FoundResult)) {
- if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
+ if (DiagnoseUseOfDecl(Fn, Arg->getLocStart()))
return ExprError();
Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
@@ -3914,22 +4231,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return Owned(Arg);
}
- bool ObjCLifetimeConversion;
- if (IsQualificationConversion(ArgType, ParamType.getNonReferenceType(),
- false, ObjCLifetimeConversion)) {
- Arg = ImpCastExprToType(Arg, ParamType, CK_NoOp,
- Arg->getValueKind()).take();
- } else if (!Context.hasSameUnqualifiedType(ArgType,
- ParamType.getNonReferenceType())) {
- // We can't perform this conversion.
- Diag(Arg->getSourceRange().getBegin(),
- diag::err_template_arg_not_convertible)
- << Arg->getType() << InstantiatedParamType << Arg->getSourceRange();
- Diag(Param->getLocation(), diag::note_template_param_here);
- return ExprError();
- }
-
- if (CheckTemplateArgumentPointerToMember(Arg, Converted))
+ if (CheckTemplateArgumentPointerToMember(*this, Param, ParamType, Arg,
+ Converted))
return ExprError();
return Owned(Arg);
}
@@ -3964,7 +4267,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
ParamRefType->getPointeeType(),
true,
FoundResult)) {
- if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
+ if (DiagnoseUseOfDecl(Fn, Arg->getLocStart()))
return ExprError();
Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
@@ -3980,27 +4283,35 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return Owned(Arg);
}
+ // Deal with parameters of type std::nullptr_t.
+ if (ParamType->isNullPtrType()) {
+ if (Arg->isTypeDependent() || Arg->isValueDependent()) {
+ Converted = TemplateArgument(Arg);
+ return Owned(Arg);
+ }
+
+ switch (isNullPointerValueTemplateArgument(*this, Param, ParamType, Arg)) {
+ case NPV_NotNullPointer:
+ Diag(Arg->getExprLoc(), diag::err_template_arg_not_convertible)
+ << Arg->getType() << ParamType;
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return ExprError();
+
+ case NPV_Error:
+ return ExprError();
+
+ case NPV_NullPointer:
+ Converted = TemplateArgument((Decl *)0);
+ return Owned(Arg);;
+ }
+ }
+
// -- For a non-type template-parameter of type pointer to data
// member, qualification conversions (4.4) are applied.
assert(ParamType->isMemberPointerType() && "Only pointers to members remain");
- bool ObjCLifetimeConversion;
- if (Context.hasSameUnqualifiedType(ParamType, ArgType)) {
- // Types match exactly: nothing more to do here.
- } else if (IsQualificationConversion(ArgType, ParamType, false,
- ObjCLifetimeConversion)) {
- Arg = ImpCastExprToType(Arg, ParamType, CK_NoOp,
- Arg->getValueKind()).take();
- } else {
- // We can't perform this conversion.
- Diag(Arg->getSourceRange().getBegin(),
- diag::err_template_arg_not_convertible)
- << Arg->getType() << InstantiatedParamType << Arg->getSourceRange();
- Diag(Param->getLocation(), diag::note_template_param_here);
- return ExprError();
- }
-
- if (CheckTemplateArgumentPointerToMember(Arg, Converted))
+ if (CheckTemplateArgumentPointerToMember(*this, Param, ParamType, Arg,
+ Converted))
return ExprError();
return Owned(Arg);
}
@@ -4059,6 +4370,18 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
SourceLocation Loc) {
assert(Arg.getKind() == TemplateArgument::Declaration &&
"Only declaration template arguments permitted here");
+
+ // For a NULL non-type template argument, return nullptr casted to the
+ // parameter's type.
+ if (!Arg.getAsDecl()) {
+ return ImpCastExprToType(
+ new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc),
+ ParamType,
+ ParamType->getAs<MemberPointerType>()
+ ? CK_NullToMemberPointer
+ : CK_NullToPointer);
+ }
+
ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
if (VD->getDeclContext()->isRecord() &&
@@ -4426,6 +4749,9 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
/// false. Otherwise, issues a diagnostic and returns true.
bool
Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
+ if (!S)
+ return false;
+
// Find the nearest enclosing declaration scope.
while ((S->getFlags() & Scope::DeclScope) == 0 ||
(S->getFlags() & Scope::TemplateParamScope) != 0)
@@ -4453,7 +4779,7 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
/// \brief Determine what kind of template specialization the given declaration
/// is.
-static TemplateSpecializationKind getTemplateSpecializationKind(NamedDecl *D) {
+static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D) {
if (!D)
return TSK_Undeclared;
@@ -4509,8 +4835,11 @@ static bool CheckTemplateSpecializationScope(Sema &S,
EntityKind = 4;
else if (isa<RecordDecl>(Specialized))
EntityKind = 5;
+ else if (isa<EnumDecl>(Specialized) && S.getLangOpts().CPlusPlus0x)
+ EntityKind = 6;
else {
- S.Diag(Loc, diag::err_template_spec_unknown_kind);
+ S.Diag(Loc, diag::err_template_spec_unknown_kind)
+ << S.getLangOpts().CPlusPlus0x;
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
return true;
}
@@ -4535,7 +4864,7 @@ static bool CheckTemplateSpecializationScope(Sema &S,
}
if (S.CurContext->isRecord() && !IsPartialSpecialization) {
- if (S.getLangOptions().MicrosoftExt) {
+ if (S.getLangOpts().MicrosoftExt) {
// Do not warn for class scope explicit specialization during
// instantiation, warning was already emitted during pattern
// semantic analysis.
@@ -4549,12 +4878,21 @@ static bool CheckTemplateSpecializationScope(Sema &S,
}
}
+ if (S.CurContext->isRecord() &&
+ !S.CurContext->Equals(Specialized->getDeclContext())) {
+ // Make sure that we're specializing in the right record context.
+ // Otherwise, things can go horribly wrong.
+ S.Diag(Loc, diag::err_template_spec_decl_class_scope)
+ << Specialized;
+ return true;
+ }
+
// C++ [temp.class.spec]p6:
// A class template partial specialization may be declared or redeclared
// in any namespace scope in which its definition may be defined (14.5.1
// and 14.5.2).
bool ComplainedAboutScope = false;
- DeclContext *SpecializedContext
+ DeclContext *SpecializedContext
= Specialized->getDeclContext()->getEnclosingNamespaceContext();
DeclContext *DC = S.CurContext->getEnclosingNamespaceContext();
if ((!PrevDecl ||
@@ -4571,24 +4909,28 @@ static bool CheckTemplateSpecializationScope(Sema &S,
// C++0x [temp.expl.spec]p2:
// An explicit specialization shall be declared in a namespace enclosing
// the specialized template.
- if (!DC->InEnclosingNamespaceSetOf(SpecializedContext) &&
- !(S.getLangOptions().CPlusPlus0x && DC->Encloses(SpecializedContext))) {
- bool IsCPlusPlus0xExtension
- = !S.getLangOptions().CPlusPlus0x && DC->Encloses(SpecializedContext);
- if (isa<TranslationUnitDecl>(SpecializedContext))
- S.Diag(Loc, IsCPlusPlus0xExtension
- ? diag::ext_template_spec_decl_out_of_scope_global
- : diag::err_template_spec_decl_out_of_scope_global)
+ if (!DC->InEnclosingNamespaceSetOf(SpecializedContext)) {
+ bool IsCPlusPlus0xExtension = DC->Encloses(SpecializedContext);
+ if (isa<TranslationUnitDecl>(SpecializedContext)) {
+ assert(!IsCPlusPlus0xExtension &&
+ "DC encloses TU but isn't in enclosing namespace set");
+ S.Diag(Loc, diag::err_template_spec_decl_out_of_scope_global)
<< EntityKind << Specialized;
- else if (isa<NamespaceDecl>(SpecializedContext))
- S.Diag(Loc, IsCPlusPlus0xExtension
- ? diag::ext_template_spec_decl_out_of_scope
- : diag::err_template_spec_decl_out_of_scope)
- << EntityKind << Specialized
- << cast<NamedDecl>(SpecializedContext);
+ } else if (isa<NamespaceDecl>(SpecializedContext)) {
+ int Diag;
+ if (!IsCPlusPlus0xExtension)
+ Diag = diag::err_template_spec_decl_out_of_scope;
+ else if (!S.getLangOpts().CPlusPlus0x)
+ Diag = diag::ext_template_spec_decl_out_of_scope;
+ else
+ Diag = diag::warn_cxx98_compat_template_spec_decl_out_of_scope;
+ S.Diag(Loc, Diag)
+ << EntityKind << Specialized << cast<NamedDecl>(SpecializedContext);
+ }
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
- ComplainedAboutScope = true;
+ ComplainedAboutScope =
+ !(IsCPlusPlus0xExtension && S.getLangOpts().CPlusPlus0x);
}
}
@@ -4718,23 +5060,6 @@ static bool CheckClassTemplatePartialSpecializationArgs(Sema &S,
return false;
}
-/// \brief Retrieve the previous declaration of the given declaration.
-static NamedDecl *getPreviousDecl(NamedDecl *ND) {
- if (VarDecl *VD = dyn_cast<VarDecl>(ND))
- return VD->getPreviousDeclaration();
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
- return FD->getPreviousDeclaration();
- if (TagDecl *TD = dyn_cast<TagDecl>(ND))
- return TD->getPreviousDeclaration();
- if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(ND))
- return TD->getPreviousDeclaration();
- if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
- return FTD->getPreviousDeclaration();
- if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(ND))
- return CTD->getPreviousDeclaration();
- return 0;
-}
-
DeclResult
Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
TagUseKind TUK,
@@ -4875,9 +5200,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
TemplateArgs, false, Converted))
return true;
- assert((Converted.size() == ClassTemplate->getTemplateParameters()->size()) &&
- "Converted template argument list is too short!");
-
// Find the class template (partial) specialization declaration that
// corresponds to these arguments.
if (isPartialSpecialization) {
@@ -5005,17 +5327,13 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// partial specialization are deducible from the template
// arguments. If not, this class template partial specialization
// will never be used.
- SmallVector<bool, 8> DeducibleParams;
- DeducibleParams.resize(TemplateParams->size());
+ llvm::SmallBitVector DeducibleParams(TemplateParams->size());
MarkUsedTemplateParameters(Partial->getTemplateArgs(), true,
TemplateParams->getDepth(),
DeducibleParams);
- unsigned NumNonDeducible = 0;
- for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I)
- if (!DeducibleParams[I])
- ++NumNonDeducible;
- if (NumNonDeducible) {
+ if (!DeducibleParams.all()) {
+ unsigned NumNonDeducible = DeducibleParams.size()-DeducibleParams.count();
Diag(TemplateNameLoc, diag::warn_partial_specs_not_deducible)
<< (NumNonDeducible > 1)
<< SourceRange(TemplateNameLoc, RAngleLoc);
@@ -5065,7 +5383,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// use occurs; no diagnostic is required.
if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) {
bool Okay = false;
- for (NamedDecl *Prev = PrevDecl; Prev; Prev = getPreviousDecl(Prev)) {
+ for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
// Is there any previous explicit specialization declaration?
if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) {
Okay = true;
@@ -5174,7 +5492,7 @@ Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
Scope *ParentScope = FnBodyScope->getParent();
- D.setFunctionDefinition(true);
+ D.setFunctionDefinitionKind(FDK_Definition);
Decl *DP = HandleDeclarator(ParentScope, D,
move(TemplateParameterLists));
if (FunctionTemplateDecl *FunctionTemplate
@@ -5189,6 +5507,7 @@ Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
/// \brief Strips various properties off an implicit instantiation
/// that has just been explicitly specialized.
static void StripImplicitInstantiation(NamedDecl *D) {
+ // FIXME: "make check" is clean if the call to dropAttrs() is commented out.
D->dropAttrs();
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
@@ -5196,6 +5515,23 @@ static void StripImplicitInstantiation(NamedDecl *D) {
}
}
+/// \brief Compute the diagnostic location for an explicit instantiation
+// declaration or definition.
+static SourceLocation DiagLocForExplicitInstantiation(
+ NamedDecl* D, SourceLocation PointOfInstantiation) {
+ // Explicit instantiations following a specialization have no effect and
+ // hence no PointOfInstantiation. In that case, walk decl backwards
+ // until a valid name loc is found.
+ SourceLocation PrevDiagLoc = PointOfInstantiation;
+ for (Decl *Prev = D; Prev && !PrevDiagLoc.isValid();
+ Prev = Prev->getPreviousDecl()) {
+ PrevDiagLoc = Prev->getLocation();
+ }
+ assert(PrevDiagLoc.isValid() &&
+ "Explicit instantiation without point of instantiation?");
+ return PrevDiagLoc;
+}
+
/// \brief Diagnose cases where we have an explicit template specialization
/// before/after an explicit template instantiation, producing diagnostics
/// for those cases where they are required and determining whether the
@@ -5262,7 +5598,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
// before the first use of that specialization that would cause an
// implicit instantiation to take place, in every translation unit in
// which such a use occurs; no diagnostic is required.
- for (NamedDecl *Prev = PrevDecl; Prev; Prev = getPreviousDecl(Prev)) {
+ for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
// Is there any previous explicit specialization declaration?
if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization)
return false;
@@ -5275,7 +5611,6 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
return true;
}
- break;
case TSK_ExplicitInstantiationDeclaration:
switch (PrevTSK) {
@@ -5306,14 +5641,15 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
// translation unit, the definition shall follow the declaration.
Diag(NewLoc,
diag::err_explicit_instantiation_declaration_after_definition);
- Diag(PrevPointOfInstantiation,
+
+ // Explicit instantiations following a specialization have no effect and
+ // hence no PrevPointOfInstantiation. In that case, walk decl backwards
+ // until a valid name loc is found.
+ Diag(DiagLocForExplicitInstantiation(PrevDecl, PrevPointOfInstantiation),
diag::note_explicit_instantiation_definition_here);
- assert(PrevPointOfInstantiation.isValid() &&
- "Explicit instantiation without point of instantiation?");
HasNoEffect = true;
return false;
}
- break;
case TSK_ExplicitInstantiationDefinition:
switch (PrevTSK) {
@@ -5333,18 +5669,32 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
// In C++98/03 mode, we only give an extension warning here, because it
// is not harmful to try to explicitly instantiate something that
// has been explicitly specialized.
- if (!getLangOptions().CPlusPlus0x) {
- Diag(NewLoc, diag::ext_explicit_instantiation_after_specialization)
- << PrevDecl;
- Diag(PrevDecl->getLocation(),
- diag::note_previous_template_specialization);
- }
+ Diag(NewLoc, getLangOpts().CPlusPlus0x ?
+ diag::warn_cxx98_compat_explicit_instantiation_after_specialization :
+ diag::ext_explicit_instantiation_after_specialization)
+ << PrevDecl;
+ Diag(PrevDecl->getLocation(),
+ diag::note_previous_template_specialization);
HasNoEffect = true;
return false;
case TSK_ExplicitInstantiationDeclaration:
// We're explicity instantiating a definition for something for which we
// were previously asked to suppress instantiations. That's fine.
+
+ // C++0x [temp.explicit]p4:
+ // For a given set of template parameters, if an explicit instantiation
+ // of a template appears after a declaration of an explicit
+ // specialization for that template, the explicit instantiation has no
+ // effect.
+ for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
+ // Is there any previous explicit specialization declaration?
+ if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) {
+ HasNoEffect = true;
+ break;
+ }
+ }
+
return false;
case TSK_ExplicitInstantiationDefinition:
@@ -5354,12 +5704,11 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
// in a program,
Diag(NewLoc, diag::err_explicit_instantiation_duplicate)
<< PrevDecl;
- Diag(PrevPointOfInstantiation,
+ Diag(DiagLocForExplicitInstantiation(PrevDecl, PrevPointOfInstantiation),
diag::note_previous_explicit_instantiation);
HasNoEffect = true;
return false;
}
- break;
}
llvm_unreachable("Missing specialization/instantiation case?");
@@ -5486,8 +5835,13 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
// Note: do not overwrite location info if previous template
// specialization kind was explicit.
TemplateSpecializationKind TSK = SpecInfo->getTemplateSpecializationKind();
- if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation)
+ if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation) {
Specialization->setLocation(FD->getLocation());
+ // C++11 [dcl.constexpr]p1: An explicit specialization of a constexpr
+ // function can differ from the template declaration with respect to
+ // the constexpr specifier.
+ Specialization->setConstexpr(FD->isConstexpr());
+ }
// FIXME: Check if the prior specialization has a point of instantiation.
// If so, we have run afoul of .
@@ -5601,6 +5955,14 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass();
MSInfo = PrevRecord->getMemberSpecializationInfo();
}
+ } else if (isa<EnumDecl>(Member)) {
+ EnumDecl *PrevEnum;
+ if (Previous.isSingleResult() &&
+ (PrevEnum = dyn_cast<EnumDecl>(Previous.getFoundDecl()))) {
+ Instantiation = PrevEnum;
+ InstantiatedFrom = PrevEnum->getInstantiatedFromMemberEnum();
+ MSInfo = PrevEnum->getMemberSpecializationInfo();
+ }
}
if (!Instantiation) {
@@ -5639,7 +6001,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
// C++ [temp.expl.spec]p6:
// If a template, a member template or the member of a class template is
- // explicitly specialized then that spe- cialization shall be declared
+ // explicitly specialized then that specialization shall be declared
// before the first use of that specialization that would cause an implicit
// instantiation to take place, in every translation unit in which such a
// use occurs; no diagnostic is required.
@@ -5691,8 +6053,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
cast<VarDecl>(InstantiatedFrom),
TSK_ExplicitSpecialization);
MarkUnusedFileScopedDecl(InstantiationVar);
- } else {
- assert(isa<CXXRecordDecl>(Member) && "Only member classes remain");
+ } else if (isa<CXXRecordDecl>(Member)) {
CXXRecordDecl *InstantiationClass = cast<CXXRecordDecl>(Instantiation);
if (InstantiationClass->getTemplateSpecializationKind() ==
TSK_ImplicitInstantiation) {
@@ -5704,6 +6065,18 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass(
cast<CXXRecordDecl>(InstantiatedFrom),
TSK_ExplicitSpecialization);
+ } else {
+ assert(isa<EnumDecl>(Member) && "Only member enums remain");
+ EnumDecl *InstantiationEnum = cast<EnumDecl>(Instantiation);
+ if (InstantiationEnum->getTemplateSpecializationKind() ==
+ TSK_ImplicitInstantiation) {
+ InstantiationEnum->setTemplateSpecializationKind(
+ TSK_ExplicitSpecialization);
+ InstantiationEnum->setLocation(Member->getLocation());
+ }
+
+ cast<EnumDecl>(Member)->setInstantiationOfMemberEnum(
+ cast<EnumDecl>(InstantiatedFrom), TSK_ExplicitSpecialization);
}
// Save the caller the trouble of having to figure out which declaration
@@ -5728,45 +6101,41 @@ static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
return true;
}
- // C++0x [temp.explicit]p2:
+ // C++11 [temp.explicit]p3:
// An explicit instantiation shall appear in an enclosing namespace of its
- // template.
+ // template. If the name declared in the explicit instantiation is an
+ // unqualified name, the explicit instantiation shall appear in the
+ // namespace where its template is declared or, if that namespace is inline
+ // (7.3.1), any namespace from its enclosing namespace set.
//
// This is DR275, which we do not retroactively apply to C++98/03.
- if (S.getLangOptions().CPlusPlus0x &&
- !CurContext->Encloses(OrigContext)) {
- if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(OrigContext))
+ if (WasQualifiedName) {
+ if (CurContext->Encloses(OrigContext))
+ return false;
+ } else {
+ if (CurContext->InEnclosingNamespaceSetOf(OrigContext))
+ return false;
+ }
+
+ if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(OrigContext)) {
+ if (WasQualifiedName)
S.Diag(InstLoc,
- S.getLangOptions().CPlusPlus0x?
- diag::err_explicit_instantiation_out_of_scope
- : diag::warn_explicit_instantiation_out_of_scope_0x)
+ S.getLangOpts().CPlusPlus0x?
+ diag::err_explicit_instantiation_out_of_scope :
+ diag::warn_explicit_instantiation_out_of_scope_0x)
<< D << NS;
else
S.Diag(InstLoc,
- S.getLangOptions().CPlusPlus0x?
- diag::err_explicit_instantiation_must_be_global
- : diag::warn_explicit_instantiation_out_of_scope_0x)
- << D;
- S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
- return false;
- }
-
- // C++0x [temp.explicit]p2:
- // If the name declared in the explicit instantiation is an unqualified
- // name, the explicit instantiation shall appear in the namespace where
- // its template is declared or, if that namespace is inline (7.3.1), any
- // namespace from its enclosing namespace set.
- if (WasQualifiedName)
- return false;
-
- if (CurContext->InEnclosingNamespaceSetOf(OrigContext))
- return false;
-
- S.Diag(InstLoc,
- S.getLangOptions().CPlusPlus0x?
- diag::err_explicit_instantiation_unqualified_wrong_namespace
- : diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x)
- << D << OrigContext;
+ S.getLangOpts().CPlusPlus0x?
+ diag::err_explicit_instantiation_unqualified_wrong_namespace :
+ diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x)
+ << D << NS;
+ } else
+ S.Diag(InstLoc,
+ S.getLangOpts().CPlusPlus0x?
+ diag::err_explicit_instantiation_must_be_global :
+ diag::warn_explicit_instantiation_must_be_global_0x)
+ << D;
S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
return false;
}
@@ -5776,7 +6145,7 @@ static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
if (!SS.isSet())
return false;
- // C++0x [temp.explicit]p2:
+ // C++11 [temp.explicit]p3:
// If the explicit instantiation is for a member function, a member class
// or a static data member of a class template specialization, the name of
// the class template specialization in the qualified-id for the member
@@ -5847,9 +6216,6 @@ Sema::ActOnExplicitInstantiation(Scope *S,
TemplateArgs, false, Converted))
return true;
- assert((Converted.size() == ClassTemplate->getTemplateParameters()->size()) &&
- "Converted template argument list is too short!");
-
// Find the class template specialization declaration that
// corresponds to these arguments.
void *InsertPos = 0;
@@ -5932,6 +6298,9 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Specialization->setExternLoc(ExternLoc);
Specialization->setTemplateKeywordLoc(TemplateLoc);
+ if (Attr)
+ ProcessDeclAttributeList(S, Specialization, Attr);
+
// Add the explicit instantiation into its lexical context. However,
// since explicit instantiations are never found by name lookup, we
// just put it into the declaration context directly.
@@ -6000,7 +6369,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
KWLoc, SS, Name, NameLoc, Attr, AS_none,
/*ModulePrivateLoc=*/SourceLocation(),
MultiTemplateParamsArg(*this, 0, 0),
- Owned, IsDependent, false, false,
+ Owned, IsDependent, SourceLocation(), false,
TypeResult());
assert(!IsDependent && "explicit instantiation of dependent name not yet handled");
@@ -6008,11 +6377,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
return true;
TagDecl *Tag = cast<TagDecl>(TagD);
- if (Tag->isEnum()) {
- Diag(TemplateLoc, diag::err_explicit_instantiation_enum)
- << Context.getTypeDeclType(Tag);
- return true;
- }
+ assert(!Tag->isEnum() && "shouldn't see enumerations here");
if (Tag->isInvalidDecl())
return true;
@@ -6053,7 +6418,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// Verify that it is okay to explicitly instantiate here.
CXXRecordDecl *PrevDecl
- = cast_or_null<CXXRecordDecl>(Record->getPreviousDeclaration());
+ = cast_or_null<CXXRecordDecl>(Record->getPreviousDecl());
if (!PrevDecl && Record->getDefinition())
PrevDecl = Record;
if (PrevDecl) {
@@ -6120,7 +6485,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
DeclarationName Name = NameInfo.getName();
if (!Name) {
if (!D.isInvalidType())
- Diag(D.getDeclSpec().getSourceRange().getBegin(),
+ Diag(D.getDeclSpec().getLocStart(),
diag::err_explicit_instantiation_requires_name)
<< D.getDeclSpec().getSourceRange()
<< D.getSourceRange();
@@ -6161,9 +6526,11 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// inline or constexpr specifiers.
// Presumably, this also applies to member functions of class templates as
// well.
- if (D.getDeclSpec().isInlineSpecified() && getLangOptions().CPlusPlus0x)
+ if (D.getDeclSpec().isInlineSpecified())
Diag(D.getDeclSpec().getInlineSpecLoc(),
- diag::err_explicit_instantiation_inline)
+ getLangOpts().CPlusPlus0x ?
+ diag::err_explicit_instantiation_inline :
+ diag::warn_explicit_instantiation_inline_0x)
<< FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
if (D.getDeclSpec().isConstexprSpecified())
// FIXME: Add a fix-it to remove the 'constexpr' and add a 'const' if one is
@@ -6326,7 +6693,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
return true;
}
- FunctionDecl *PrevDecl = Specialization->getPreviousDeclaration();
+ FunctionDecl *PrevDecl = Specialization->getPreviousDecl();
if (!PrevDecl && Specialization->isThisDeclarationADefinition())
PrevDecl = Specialization;
@@ -6346,6 +6713,9 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
}
Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
+ AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
+ if (Attr)
+ ProcessDeclAttributeList(S, Specialization, Attr);
if (TSK == TSK_ExplicitInstantiationDefinition)
InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization);
@@ -6402,7 +6772,7 @@ Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Create type-source location information for this type.
TypeLocBuilder TLB;
DependentNameTypeLoc TL = TLB.push<DependentNameTypeLoc>(Result);
- TL.setKeywordLoc(TagLoc);
+ TL.setElaboratedKeywordLoc(TagLoc);
TL.setQualifierLoc(SS.getWithLocInContext(Context));
TL.setNameLoc(NameLoc);
return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
@@ -6415,9 +6785,11 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
if (SS.isInvalid())
return true;
- if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() &&
- !getLangOptions().CPlusPlus0x)
- Diag(TypenameLoc, diag::ext_typename_outside_of_template)
+ if (TypenameLoc.isValid() && S && !S->getTemplateParamParent())
+ Diag(TypenameLoc,
+ getLangOpts().CPlusPlus0x ?
+ diag::warn_cxx98_compat_typename_outside_of_template :
+ diag::ext_typename_outside_of_template)
<< FixItHint::CreateRemoval(TypenameLoc);
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
@@ -6429,12 +6801,12 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
if (isa<DependentNameType>(T)) {
DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
- TL.setKeywordLoc(TypenameLoc);
+ TL.setElaboratedKeywordLoc(TypenameLoc);
TL.setQualifierLoc(QualifierLoc);
TL.setNameLoc(IdLoc);
} else {
ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc());
- TL.setKeywordLoc(TypenameLoc);
+ TL.setElaboratedKeywordLoc(TypenameLoc);
TL.setQualifierLoc(QualifierLoc);
cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(IdLoc);
}
@@ -6443,18 +6815,21 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
}
TypeResult
-Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
- const CXXScopeSpec &SS,
- SourceLocation TemplateLoc,
+Sema::ActOnTypenameType(Scope *S,
+ SourceLocation TypenameLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
TemplateTy TemplateIn,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
SourceLocation RAngleLoc) {
- if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() &&
- !getLangOptions().CPlusPlus0x)
- Diag(TypenameLoc, diag::ext_typename_outside_of_template)
- << FixItHint::CreateRemoval(TypenameLoc);
+ if (TypenameLoc.isValid() && S && !S->getTemplateParamParent())
+ Diag(TypenameLoc,
+ getLangOpts().CPlusPlus0x ?
+ diag::warn_cxx98_compat_typename_outside_of_template :
+ diag::ext_typename_outside_of_template)
+ << FixItHint::CreateRemoval(TypenameLoc);
// Translate the parser's template argument list in our AST format.
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
@@ -6475,11 +6850,12 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
TypeLocBuilder Builder;
DependentTemplateSpecializationTypeLoc SpecTL
= Builder.push<DependentTemplateSpecializationTypeLoc>(T);
+ SpecTL.setElaboratedKeywordLoc(TypenameLoc);
+ SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
+ SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
+ SpecTL.setTemplateNameLoc(TemplateNameLoc);
SpecTL.setLAngleLoc(LAngleLoc);
SpecTL.setRAngleLoc(RAngleLoc);
- SpecTL.setKeywordLoc(TypenameLoc);
- SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
- SpecTL.setNameLoc(TemplateNameLoc);
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
@@ -6489,22 +6865,20 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
if (T.isNull())
return true;
- // Provide source-location information for the template specialization
- // type.
+ // Provide source-location information for the template specialization type.
TypeLocBuilder Builder;
- TemplateSpecializationTypeLoc SpecTL
+ TemplateSpecializationTypeLoc SpecTL
= Builder.push<TemplateSpecializationTypeLoc>(T);
-
- // FIXME: No place to set the location of the 'template' keyword!
+ SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
+ SpecTL.setTemplateNameLoc(TemplateNameLoc);
SpecTL.setLAngleLoc(LAngleLoc);
SpecTL.setRAngleLoc(RAngleLoc);
- SpecTL.setTemplateNameLoc(TemplateNameLoc);
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
T = Context.getElaboratedType(ETK_Typename, SS.getScopeRep(), T);
ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T);
- TL.setKeywordLoc(TypenameLoc);
+ TL.setElaboratedKeywordLoc(TypenameLoc);
TL.setQualifierLoc(SS.getWithLocInContext(Context));
TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T);
@@ -6588,10 +6962,6 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
Referenced = Result.getFoundDecl();
break;
-
- llvm_unreachable("unresolved using decl in non-dependent context");
- return QualType();
-
case LookupResult::FoundOverloaded:
DiagID = diag::err_typename_nested_not_type;
Referenced = *Result.begin();
@@ -6650,6 +7020,11 @@ namespace {
this->Loc = Loc;
this->Entity = Entity;
}
+
+ ExprResult TransformLambdaExpr(LambdaExpr *E) {
+ // Lambdas never need to be transformed.
+ return E;
+ }
};
}
@@ -6762,7 +7137,7 @@ std::string
Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
const TemplateArgument *Args,
unsigned NumArgs) {
- llvm::SmallString<128> Str;
+ SmallString<128> Str;
llvm::raw_svector_ostream Out(Str);
if (!Params || Params->size() == 0 || NumArgs == 0)
OpenPOWER on IntegriCloud