aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ASTContext.cpp4
-rw-r--r--lib/AST/DeclTemplate.cpp7
-rw-r--r--lib/AST/StmtProfile.cpp4
-rw-r--r--lib/AST/TemplateBase.cpp13
-rw-r--r--lib/AST/Type.cpp3
-rw-r--r--lib/AST/TypePrinter.cpp5
-rw-r--r--lib/Frontend/PCHReader.cpp8
-rw-r--r--lib/Frontend/PCHWriter.cpp6
-rw-r--r--lib/Parse/ParseTemplate.cpp163
-rw-r--r--lib/Sema/Sema.h7
-rw-r--r--lib/Sema/SemaLookup.cpp9
-rw-r--r--lib/Sema/SemaTemplate.cpp292
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp69
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp12
-rw-r--r--lib/Sema/TreeTransform.h19
15 files changed, 392 insertions, 229 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index bb3559b50f..b5d9cac9fa 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2357,12 +2357,14 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) {
return Arg;
case TemplateArgument::Expression:
- // FIXME: Build canonical expression?
return Arg;
case TemplateArgument::Declaration:
return TemplateArgument(Arg.getAsDecl()->getCanonicalDecl());
+ case TemplateArgument::Template:
+ return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()));
+
case TemplateArgument::Integral:
return TemplateArgument(*Arg.getAsIntegral(),
getCanonicalType(Arg.getIntegralType()));
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 9ebc91afe1..0c14714812 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -220,7 +220,7 @@ QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) {
TemplateArgs.push_back(TemplateArgument(E));
} else {
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
- TemplateArgs.push_back(TemplateArgument(TTP));
+ TemplateArgs.push_back(TemplateArgument(TemplateName(TTP)));
}
}
@@ -285,11 +285,6 @@ TemplateTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params);
}
-SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
- return DefaultArgument? DefaultArgument->getSourceRange().getBegin()
- : SourceLocation();
-}
-
//===----------------------------------------------------------------------===//
// TemplateArgumentListBuilder Implementation
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 02e0c74bb6..4458c2b9cd 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -695,6 +695,10 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
VisitType(Arg.getAsType());
break;
+ case TemplateArgument::Template:
+ VisitTemplateName(Arg.getAsTemplate());
+ break;
+
case TemplateArgument::Declaration:
VisitDecl(Arg.getAsDecl());
break;
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 94e1ca1e06..18a574c89c 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -58,6 +58,10 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
break;
+ case Template:
+ ID.AddPointer(getAsTemplate().getAsVoidPointer());
+ break;
+
case Integral:
getAsIntegral()->Profile(ID);
getIntegralType().Profile(ID);
@@ -82,10 +86,19 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
switch (Argument.getKind()) {
case TemplateArgument::Expression:
return getSourceExpression()->getSourceRange();
+
case TemplateArgument::Declaration:
return getSourceDeclExpression()->getSourceRange();
+
case TemplateArgument::Type:
return getSourceDeclaratorInfo()->getTypeLoc().getFullSourceRange();
+
+ case TemplateArgument::Template:
+ if (getTemplateQualifierRange().isValid())
+ return SourceRange(getTemplateQualifierRange().getBegin(),
+ getTemplateNameLoc());
+ return SourceRange(getTemplateNameLoc());
+
case TemplateArgument::Integral:
case TemplateArgument::Pack:
case TemplateArgument::Null:
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 844589fd3e..5ecc33cd8f 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -807,6 +807,9 @@ static bool isDependent(const TemplateArgument &Arg) {
case TemplateArgument::Type:
return Arg.getAsType()->isDependentType();
+ case TemplateArgument::Template:
+ return Arg.getAsTemplate().isDependent();
+
case TemplateArgument::Declaration:
case TemplateArgument::Integral:
// Never dependent
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 807f7d86c5..ed12006211 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -576,6 +576,11 @@ static void PrintTemplateArgument(std::string &Buffer,
Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString();
break;
+ case TemplateArgument::Template: {
+ llvm::raw_string_ostream s(Buffer);
+ Arg.getAsTemplate().print(s, Policy);
+ }
+
case TemplateArgument::Integral:
Buffer = Arg.getAsIntegral()->toString(10, true);
break;
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 5cee9884ce..394d35891d 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -2185,6 +2185,14 @@ PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
return ReadDeclExpr();
case TemplateArgument::Type:
return GetDeclaratorInfo(Record, Index);
+ case TemplateArgument::Template: {
+ SourceLocation
+ QualStart = SourceLocation::getFromRawEncoding(Record[Index++]),
+ QualEnd = SourceLocation::getFromRawEncoding(Record[Index++]),
+ TemplateNameLoc = SourceLocation::getFromRawEncoding(Record[Index++]);
+ return TemplateArgumentLocInfo(SourceRange(QualStart, QualEnd),
+ TemplateNameLoc);
+ }
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 82922a93b5..2dcb8b0cee 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -2122,6 +2122,12 @@ void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
case TemplateArgument::Type:
AddDeclaratorInfo(Arg.getLocInfo().getAsDeclaratorInfo(), Record);
break;
+ case TemplateArgument::Template:
+ Record.push_back(
+ Arg.getTemplateQualifierRange().getBegin().getRawEncoding());
+ Record.push_back(Arg.getTemplateQualifierRange().getEnd().getRawEncoding());
+ Record.push_back(Arg.getTemplateNameLoc().getRawEncoding());
+ break;
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index cf7d511697..b5063ee44b 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -485,12 +485,17 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
// Get the a default value, if given.
if (Tok.is(tok::equal)) {
SourceLocation EqualLoc = ConsumeToken();
- OwningExprResult DefaultExpr = ParseCXXIdExpression();
- if (DefaultExpr.isInvalid())
+ ParsedTemplateArgument Default = ParseTemplateTemplateArgument();
+ if (Default.isInvalid()) {
+ Diag(Tok.getLocation(),
+ diag::err_default_template_template_parameter_not_template);
+ static tok::TokenKind EndToks[] = {
+ tok::comma, tok::greater, tok::greatergreater
+ };
+ SkipUntil(EndToks, 3, true, true);
return Param;
- else if (Param)
- Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc,
- move(DefaultExpr));
+ } else if (Param)
+ Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc, Default);
}
return Param;
@@ -808,33 +813,16 @@ static bool isEndOfTemplateArgument(Token Tok) {
Tok.is(tok::greatergreater);
}
-/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
-///
-/// template-argument: [C++ 14.2]
-/// constant-expression
-/// type-id
-/// id-expression
-ParsedTemplateArgument Parser::ParseTemplateArgument() {
- // C++ [temp.arg]p2:
- // In a template-argument, an ambiguity between a type-id and an
- // expression is resolved to a type-id, regardless of the form of
- // the corresponding template-parameter.
- //
- // Therefore, we initially try to parse a type-id.
- if (isCXXTypeId(TypeIdAsTemplateArgument)) {
- SourceLocation Loc = Tok.getLocation();
- TypeResult TypeArg = ParseTypeName();
- if (TypeArg.isInvalid())
- return ParsedTemplateArgument();
-
- return ParsedTemplateArgument(ParsedTemplateArgument::Type, TypeArg.get(),
- Loc);
- }
+/// \brief Parse a C++ template template argument.
+ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
+ if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) &&
+ !Tok.is(tok::annot_cxxscope))
+ return ParsedTemplateArgument();
// C++0x [temp.arg.template]p1:
// A template-argument for a template template-parameter shall be the name
// of a class template or a template alias, expressed as id-expression.
- //
+ //
// We perform some tentative parsing at this point, to determine whether
// we have an id-expression that refers to a class template or template
// alias. The grammar we tentatively parse is:
@@ -843,63 +831,92 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
//
// followed by a token that terminates a template argument, such as ',',
// '>', or (in some cases) '>>'.
- if (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
- Tok.is(tok::annot_cxxscope)) {
- TentativeParsingAction TPA(*this);
- CXXScopeSpec SS; // nested-name-specifier, if present
- ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0,
- /*EnteringContext=*/false);
-
- if (SS.isSet() && Tok.is(tok::kw_template)) {
- // Parse the optional 'template' keyword following the
- // nested-name-specifier.
- SourceLocation TemplateLoc = ConsumeToken();
-
- if (Tok.is(tok::identifier)) {
- // We appear to have a dependent template name.
- UnqualifiedId Name;
- Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
- ConsumeToken(); // the identifier
-
- // If the next token signals the end of a template argument,
- // then we have a dependent template name that could be a template
- // template argument.
- if (isEndOfTemplateArgument(Tok)) {
- TemplateTy Template
- = Actions.ActOnDependentTemplateName(TemplateLoc, SS, Name,
- /*ObjectType=*/0);
- if (Template.get()) {
- TPA.Commit();
- return ParsedTemplateArgument(SS, Template, Name.StartLocation);
- }
- }
- }
- } else if (Tok.is(tok::identifier)) {
- // We may have a (non-dependent) template name.
- TemplateTy Template;
+ TentativeParsingAction TPA(*this);
+ CXXScopeSpec SS; // nested-name-specifier, if present
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0,
+ /*EnteringContext=*/false);
+
+ if (SS.isSet() && Tok.is(tok::kw_template)) {
+ // Parse the optional 'template' keyword following the
+ // nested-name-specifier.
+ SourceLocation TemplateLoc = ConsumeToken();
+
+ if (Tok.is(tok::identifier)) {
+ // We appear to have a dependent template name.
UnqualifiedId Name;
Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken(); // the identifier
-
+
+ // If the next token signals the end of a template argument,
+ // then we have a dependent template name that could be a template
+ // template argument.
if (isEndOfTemplateArgument(Tok)) {
- TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, Name,
- /*ObjectType=*/0,
- /*EnteringContext=*/false,
- Template);
- if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
- // We have an id-expression that refers to a class template or
- // (C++0x) template alias.
+ TemplateTy Template
+ = Actions.ActOnDependentTemplateName(TemplateLoc, SS, Name,
+ /*ObjectType=*/0);
+ if (Template.get()) {
TPA.Commit();
return ParsedTemplateArgument(SS, Template, Name.StartLocation);
}
}
+ }
+ } else if (Tok.is(tok::identifier)) {
+ // We may have a (non-dependent) template name.
+ TemplateTy Template;
+ UnqualifiedId Name;
+ Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ ConsumeToken(); // the identifier
+
+ if (isEndOfTemplateArgument(Tok)) {
+ TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, Name,
+ /*ObjectType=*/0,
+ /*EnteringContext=*/false,
+ Template);
+ if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
+ // We have an id-expression that refers to a class template or
+ // (C++0x) template alias.
+ TPA.Commit();
+ return ParsedTemplateArgument(SS, Template, Name.StartLocation);
+ }
}
+ }
+
+ // We don't have a template template argument; revert everything we have
+ // tentatively parsed.
+ TPA.Revert();
+
+ return ParsedTemplateArgument();
+}
+
+/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
+///
+/// template-argument: [C++ 14.2]
+/// constant-expression
+/// type-id
+/// id-expression
+ParsedTemplateArgument Parser::ParseTemplateArgument() {
+ // C++ [temp.arg]p2:
+ // In a template-argument, an ambiguity between a type-id and an
+ // expression is resolved to a type-id, regardless of the form of
+ // the corresponding template-parameter.
+ //
+ // Therefore, we initially try to parse a type-id.
+ if (isCXXTypeId(TypeIdAsTemplateArgument)) {
+ SourceLocation Loc = Tok.getLocation();
+ TypeResult TypeArg = ParseTypeName();
+ if (TypeArg.isInvalid())
+ return ParsedTemplateArgument();
- // We don't have a template template argument; revert everything we have
- // tentatively parsed.
- TPA.Revert();
+ return ParsedTemplateArgument(ParsedTemplateArgument::Type, TypeArg.get(),
+ Loc);
}
+ // Try to parse a template template argument.
+ ParsedTemplateArgument TemplateTemplateArgument
+ = ParseTemplateTemplateArgument();
+ if (!TemplateTemplateArgument.isInvalid())
+ return TemplateTemplateArgument;
+
// Parse a non-type template argument.
SourceLocation Loc = Tok.getLocation();
OwningExprResult ExprArg = ParseConstantExpression();
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 90f580618a..6c88995a1b 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -2446,7 +2446,7 @@ public:
unsigned Position);
virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
SourceLocation EqualLoc,
- ExprArg Default);
+ const ParsedTemplateArgument &Default);
virtual TemplateParamsTy *
ActOnTemplateParameterList(unsigned Depth,
@@ -2606,13 +2606,14 @@ public:
bool CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
QualType InstantiatedParamType, Expr *&Arg,
TemplateArgument &Converted);
- bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, DeclRefExpr *Arg);
+ bool CheckTemplateArgument(TemplateTemplateParmDecl *Param,
+ const TemplateArgumentLoc &Arg);
bool TemplateParameterListsAreEqual(TemplateParameterList *New,
TemplateParameterList *Old,
bool Complain,
bool IsTemplateTemplateParm = false,
SourceLocation TemplateArgLoc
- = SourceLocation());
+ = SourceLocation());
bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams);
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 13a66aaca0..4f261383ad 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1219,12 +1219,13 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg,
AssociatedClasses);
break;
- case TemplateArgument::Declaration:
+ case TemplateArgument::Template: {
// [...] the namespaces in which any template template arguments are
// defined; and the classes in which any member templates used as
// template template arguments are defined.
+ TemplateName Template = Arg.getAsTemplate();
if (ClassTemplateDecl *ClassTemplate
- = dyn_cast<ClassTemplateDecl>(Arg.getAsDecl())) {
+ = dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) {
DeclContext *Ctx = ClassTemplate->getDeclContext();
if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
AssociatedClasses.insert(EnclosingClass);
@@ -1234,7 +1235,9 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg,
CollectNamespace(AssociatedNamespaces, Ctx);
}
break;
-
+ }
+
+ case TemplateArgument::Declaration:
case TemplateArgument::Integral:
case TemplateArgument::Expression:
// [Note: non-type template arguments do not contribute to the set of
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 32a6d6c243..ce2ffc1ac1 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -284,6 +284,46 @@ TemplateDecl *Sema::AdjustDeclIfTemplate(DeclPtrTy &D) {
return 0;
}
+static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
+ const ParsedTemplateArgument &Arg) {
+
+ switch (Arg.getKind()) {
+ case ParsedTemplateArgument::Type: {
+ DeclaratorInfo *DI;
+ QualType T = SemaRef.GetTypeFromParser(Arg.getAsType(), &DI);
+ if (!DI)
+ DI = SemaRef.Context.getTrivialDeclaratorInfo(T, Arg.getLocation());
+ return TemplateArgumentLoc(TemplateArgument(T), DI);
+ }
+
+ case ParsedTemplateArgument::NonType: {
+ Expr *E = static_cast<Expr *>(Arg.getAsExpr());
+ return TemplateArgumentLoc(TemplateArgument(E), E);
+ }
+
+ case ParsedTemplateArgument::Template: {
+ TemplateName Template
+ = TemplateName::getFromVoidPointer(Arg.getAsTemplate().get());
+ return TemplateArgumentLoc(TemplateArgument(Template),
+ Arg.getScopeSpec().getRange(),
+ Arg.getLocation());
+ }
+ }
+
+ llvm::llvm_unreachable("Unhandled parsed template argument");
+ return TemplateArgumentLoc();
+}
+
+/// \brief Translates template arguments as provided by the parser
+/// into template arguments used by semantic analysis.
+void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
+ llvm::SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {
+ TemplateArgs.reserve(TemplateArgsIn.size());
+
+ for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I)
+ TemplateArgs.push_back(translateTemplateArgument(*this, TemplateArgsIn[I]));
+}
+
/// ActOnTypeParameter - Called when a C++ template type parameter
/// (e.g., "typename T") has been parsed. Typename specifies whether
/// the keyword "typename" was used to declare the type parameter
@@ -518,34 +558,22 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S,
/// parameter.
void Sema::ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParamD,
SourceLocation EqualLoc,
- ExprArg DefaultE) {
+ const ParsedTemplateArgument &Default) {
TemplateTemplateParmDecl *TemplateParm
= cast<TemplateTemplateParmDecl>(TemplateParamD.getAs<Decl>());
-
- // Since a template-template parameter's default argument is an
- // id-expression, it must be a DeclRefExpr.
- DeclRefExpr *Default
- = cast<DeclRefExpr>(static_cast<Expr *>(DefaultE.get()));
-
+
// C++ [temp.param]p14:
// A template-parameter shall not be used in its own default argument.
// FIXME: Implement this check! Needs a recursive walk over the types.
// Check the well-formedness of the template argument.
- if (!isa<TemplateDecl>(Default->getDecl())) {
- Diag(Default->getSourceRange().getBegin(),
- diag::err_template_arg_must_be_template)
- << Default->getSourceRange();
- TemplateParm->setInvalidDecl();
- return;
- }
- if (CheckTemplateArgument(TemplateParm, Default)) {
+ TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default);
+ if (CheckTemplateArgument(TemplateParm, DefaultArg)) {
TemplateParm->setInvalidDecl();
return;
}
- DefaultE.release();
- TemplateParm->setDefaultArgument(Default);
+ TemplateParm->setDefaultArgument(DefaultArg);
}
/// ActOnTemplateParameterList - Builds a TemplateParameterList that
@@ -924,8 +952,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
= OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : 0;
if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() &&
NewTemplateParm->hasDefaultArgument()) {
- OldDefaultLoc = OldTemplateParm->getDefaultArgumentLoc();
- NewDefaultLoc = NewTemplateParm->getDefaultArgumentLoc();
+ OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation();
+ NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation();
SawDefaultArgument = true;
RedundantDefaultArg = true;
PreviousDefaultArgLoc = NewDefaultLoc;
@@ -937,10 +965,12 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// that points to a previous template template parameter.
NewTemplateParm->setDefaultArgument(
OldTemplateParm->getDefaultArgument());
- PreviousDefaultArgLoc = OldTemplateParm->getDefaultArgumentLoc();
+ PreviousDefaultArgLoc
+ = OldTemplateParm->getDefaultArgument().getLocation();
} else if (NewTemplateParm->hasDefaultArgument()) {
SawDefaultArgument = true;
- PreviousDefaultArgLoc = NewTemplateParm->getDefaultArgumentLoc();
+ PreviousDefaultArgLoc
+ = NewTemplateParm->getDefaultArgument().getLocation();
} else if (SawDefaultArgument)
MissingDefaultArg = true;
}
@@ -1119,50 +1149,6 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
return ParamLists[NumParamLists - 1];
}
-/// \brief Translates template arguments as provided by the parser
-/// into template arguments used by semantic analysis.
-void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
- llvm::SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {
- TemplateArgs.reserve(TemplateArgsIn.size());
-
- for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I) {
- const ParsedTemplateArgument &Arg = TemplateArgsIn[I];
- switch (Arg.getKind()) {
- case ParsedTemplateArgument::Type: {
- DeclaratorInfo *DI;
- QualType T = Sema::GetTypeFromParser(Arg.getAsType(), &DI);
- if (!DI) DI = Context.getTrivialDeclaratorInfo(T, Arg.getLocation());
- TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(T), DI));
- break;
- }
-
- case ParsedTemplateArgument::NonType: {
- Expr *E = static_cast<Expr *>(Arg.getAsExpr());
- TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(E), E));
- break;
- }
-
- case ParsedTemplateArgument::Template: {
- TemplateName Template
- = TemplateName::getFromVoidPointer(Arg.getAsTemplate().get());
-
- // FIXME: This is an egregious hack. We turn a nicely-parsed template name
- // into a DeclRefExpr, because that's how we previously parsed template
- // template parameters. This will disappear as part of the upcoming
- // implementation of template template parameters.
- const CXXScopeSpec &SS = Arg.getScopeSpec();
- Expr *E = DeclRefExpr::Create(Context,
- (NestedNameSpecifier *)SS.getScopeRep(),
- SS.getRange(),
- Template.getAsTemplateDecl(),
- Arg.getLocation(),
- Context.DependentTy, false, false);
- TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(E), E));
- }
- }
- }
-}
-
QualType Sema::CheckTemplateIdType(TemplateName Name,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
@@ -1538,7 +1524,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
/// \param RAngleLoc the location of the right angle bracket ('>') that
/// terminates the template-id.
///
-/// \param Param the template template parameter whose default we are
+/// \param Param the non-type template parameter whose default we are
/// substituting into.
///
/// \param Converted the list of template arguments provided for template
@@ -1566,6 +1552,52 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
return SemaRef.SubstExpr(Param->getDefaultArgument(), AllTemplateArgs);
}
+/// \brief Substitute template arguments into the default template argument for
+/// the given template template parameter.
+///
+/// \param SemaRef the semantic analysis object for which we are performing
+/// the substitution.
+///
+/// \param Template the template that we are synthesizing template arguments
+/// for.
+///
+/// \param TemplateLoc the location of the template name that started the
+/// template-id we are checking.
+///
+/// \param RAngleLoc the location of the right angle bracket ('>') that
+/// terminates the template-id.
+///
+/// \param Param the template template parameter whose default we are
+/// substituting into.
+///
+/// \param Converted the list of template arguments provided for template
+/// parameters that precede \p Param in the template parameter list.
+///
+/// \returns the substituted template argument, or NULL if an error occurred.
+static TemplateName
+SubstDefaultTemplateArgument(Sema &SemaRef,
+ TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc,
+ TemplateTemplateParmDecl *Param,
+ TemplateArgumentListBuilder &Converted) {
+ TemplateArgumentList TemplateArgs(SemaRef.Context, Converted,
+ /*TakeArgs=*/false);
+
+ MultiLevelTemplateArgumentList AllTemplateArgs
+ = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
+
+ Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
+ Template, Converted.getFlatArguments(),
+ Converted.flatSize(),
+ SourceRange(TemplateLoc, RAngleLoc));
+
+ return SemaRef.SubstTemplateName(
+ Param->getDefaultArgument().getArgument().getAsTemplate(),
+ Param->getDefaultArgument().getTemplateNameLoc(),
+ AllTemplateArgs);
+}
+
/// \brief Check that the given template argument list is well-formed
/// for specializing the given template.
bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
@@ -1666,9 +1698,17 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (!TempParm->hasDefaultArgument())
break;
- // FIXME: Subst default argument
- Arg = TemplateArgumentLoc(TemplateArgument(TempParm->getDefaultArgument()),
- TempParm->getDefaultArgument());
+ TemplateName Name = SubstDefaultTemplateArgument(*this, Template,
+ TemplateLoc,
+ RAngleLoc,
+ TempParm,
+ Converted);
+ if (Name.isNull())
+ return true;
+
+ Arg = TemplateArgumentLoc(TemplateArgument(Name),
+ TempParm->getDefaultArgument().getTemplateQualifierRange(),
+ TempParm->getDefaultArgument().getTemplateNameLoc());
}
} else {
// Retrieve the template argument produced by the user.
@@ -1743,6 +1783,41 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
Converted.Append(Arg.getArgument());
break;
+ case TemplateArgument::Template:
+ // We were given a template template argument. It may not be ill-formed;
+ // see below.
+ if (DependentTemplateName *DTN
+ = Arg.getArgument().getAsTemplate().getAsDependentTemplateName()) {
+ // We have a template argument such as \c T::template X, which we
+ // parsed as a template template argument. However, since we now
+ // know that we need a non-type template argument, convert this
+ // template name into an expression.
+ Expr *E = new (Context) UnresolvedDeclRefExpr(DTN->getIdentifier(),
+ Context.DependentTy,
+ Arg.getTemplateNameLoc(),
+ Arg.getTemplateQualifierRange(),
+ DTN->getQualifier(),
+ /*isAddressOfOperand=*/false);
+
+ TemplateArgument Result;
+ if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
+ Invalid = true;
+ else
+ Converted.Append(Result);
+
+ break;
+ }
+
+ // We have a template argument that actually does refer to a class
+ // template, template alias, or template template parameter, and
+ // therefore cannot be a non-type template argument.
+ Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr)
+ << Arg.getSourceRange();
+
+ Diag((*Param)->getLocation(), diag::note_template_param_here);
+ Invalid = true;
+ break;
+
case TemplateArgument::Type: {
// We have a non-type template parameter but the template
// argument is a type.
@@ -1780,38 +1855,28 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
assert(false && "Should never see a NULL template argument here");
break;
- case TemplateArgument::Expression: {
- Expr *ArgExpr = Arg.getArgument().getAsExpr();
- if (ArgExpr && isa<DeclRefExpr>(ArgExpr) &&
- isa<TemplateDecl>(cast<DeclRefExpr>(ArgExpr)->getDecl())) {
- if (CheckTemplateArgument(TempParm, cast<DeclRefExpr>(ArgExpr)))
- Invalid = true;
-
- // Add the converted template argument.
- Decl *D
- = cast<DeclRefExpr>(ArgExpr)->getDecl()->getCanonicalDecl();
- Converted.Append(TemplateArgument(D));
- continue;
- }
- }
- // fall through
-
- case TemplateArgument::Type: {
+ case TemplateArgument::Template:
+ if (CheckTemplateArgument(TempParm, Arg))
+ Invalid = true;
+ else
+ Converted.Append(Arg.getArgument());
+ break;
+
+ case TemplateArgument::Expression:
+ case TemplateArgument::Type:
// 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);
Invalid = true;
break;
- }
case TemplateArgument::Declaration:
- // We've already checked this template argument, so just copy
- // it to the list of converted arguments.
- Converted.Append(Arg.getArgument());
+ llvm::llvm_unreachable(
+ "Declaration argument with template template parameter");
break;
-
case TemplateArgument::Integral:
- assert(false && "Integral argument with template template parameter");
+ llvm::llvm_unreachable(
+ "Integral argument with template template parameter");
break;
case TemplateArgument::Pack:
@@ -2357,9 +2422,14 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
/// This routine implements the semantics of C++ [temp.arg.template].
/// It returns true if an error occurred, and false otherwise.
bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
- DeclRefExpr *Arg) {