aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/DeclTemplate.h17
-rw-r--r--include/clang/AST/TemplateBase.h100
-rw-r--r--include/clang/AST/TypeLoc.h4
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td4
-rw-r--r--include/clang/Parse/Action.h2
-rw-r--r--include/clang/Parse/Parser.h1
-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
-rw-r--r--test/SemaTemplate/temp_arg_nontype.cpp3
-rw-r--r--test/SemaTemplate/temp_arg_template.cpp7
23 files changed, 502 insertions, 257 deletions
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index f1a27933a1..14f666005c 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -699,13 +699,13 @@ class TemplateTemplateParmDecl
: public TemplateDecl, protected TemplateParmPosition {
/// \brief The default template argument, if any.
- Expr *DefaultArgument;
+ TemplateArgumentLoc DefaultArgument;
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
unsigned D, unsigned P,
IdentifierInfo *Id, TemplateParameterList *Params)
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
- TemplateParmPosition(D, P), DefaultArgument(0)
+ TemplateParmPosition(D, P), DefaultArgument()
{ }
public:
@@ -720,16 +720,17 @@ public:
/// \brief Determine whether this template parameter has a default
/// argument.
- bool hasDefaultArgument() const { return DefaultArgument; }
+ bool hasDefaultArgument() const {
+ return !DefaultArgument.getArgument().isNull();
+ }
/// \brief Retrieve the default argument, if any.
- Expr *getDefaultArgument() const { return DefaultArgument; }
-
- /// \brief Retrieve the location of the default argument, if any.
- SourceLocation getDefaultArgumentLoc() const;
+ const TemplateArgumentLoc &getDefaultArgument() const {
+ return DefaultArgument;
+ }
/// \brief Set the default argument for this template parameter.
- void setDefaultArgument(Expr *DefArg) {
+ void setDefaultArgument(const TemplateArgumentLoc &DefArg) {
DefaultArgument = DefArg;
}
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index bb14c62d77..6db095872b 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/APSInt.h"
#include "llvm/Support/ErrorHandling.h"
#include "clang/AST/Type.h"
+#include "clang/AST/TemplateName.h"
namespace llvm {
class FoldingSetNodeID;
@@ -48,21 +49,27 @@ class TemplateArgument {
public:
/// \brief The type of template argument we're storing.
enum ArgKind {
+ /// \brief Represents an empty template argument, e.g., one that has not
+ /// been deduced.
Null = 0,
/// The template argument is a type. Its value is stored in the
/// TypeOrValue field.
- Type = 1,
- /// The template argument is a declaration
- Declaration = 2,
- /// The template argument is an integral value stored in an llvm::APSInt.
- Integral = 3,
+ Type,
+ /// The template argument is a declaration that was provided for a pointer
+ /// or reference non-type template parameter.
+ Declaration,
+ /// The template argument is an integral value stored in an llvm::APSInt
+ /// that was provided for an integral non-type template parameter.
+ Integral,
+ /// The template argument is a template name that was provided for a
+ /// template template parameter.
+ Template,
/// The template argument is a value- or type-dependent expression
/// stored in an Expr*.
- Expression = 4,
-
+ Expression,
/// The template argument is actually a parameter pack. Arguments are stored
/// in the Args struct.
- Pack = 5
+ Pack
} Kind;
/// \brief Construct an empty, invalid template argument.
@@ -82,12 +89,21 @@ public:
}
/// \brief Construct an integral constant template argument.
- TemplateArgument(const llvm::APSInt &Value, QualType Type)
- : Kind(Integral) {
+ TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) {
new (Integer.Value) llvm::APSInt(Value);
Integer.Type = Type.getAsOpaquePtr();
}
+ /// \brief Construct a template argument that is a template.
+ ///
+ /// This form of template argument is generally used for template template
+ /// parameters. However, the template name could be a dependent template
+ /// name that ends up being instantiated to a function template whose address
+ /// is taken.
+ TemplateArgument(TemplateName Name) : Kind(Template) {
+ TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer());
+ }
+
/// \brief Construct a template argument that is an expression.
///
/// This form of template argument only occurs in template argument
@@ -172,6 +188,15 @@ public:
return reinterpret_cast<Decl *>(TypeOrValue);
}
+ /// \brief Retrieve the template argument as a template name.
+ TemplateName getAsTemplate() const {
+ if (Kind != Template)
+ return TemplateName();
+
+ return TemplateName::getFromVoidPointer(
+ reinterpret_cast<void *> (TypeOrValue));
+ }
+
/// \brief Retrieve the template argument as an integral value.
llvm::APSInt *getAsIntegral() {
if (Kind != Integral)
@@ -242,13 +267,18 @@ private:
union {
Expr *Expression;
DeclaratorInfo *Declarator;
+ struct {
+ unsigned QualifierRange[2];
+ unsigned TemplateNameLoc;
+ } Template;
};
#ifndef NDEBUG
enum Kind {
K_None,
K_DeclaratorInfo,
- K_Expression
+ K_Expression,
+ K_Template
} Kind;
#endif
@@ -273,6 +303,17 @@ public:
, Kind(K_Expression)
#endif
{}
+
+ TemplateArgumentLocInfo(SourceRange QualifierRange,
+ SourceLocation TemplateNameLoc)
+#ifndef NDEBUG
+ : Kind(K_Template)
+#endif
+ {
+ Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding();
+ Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding();
+ Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
+ }
DeclaratorInfo *getAsDeclaratorInfo() const {
assert(Kind == K_DeclaratorInfo);
@@ -284,6 +325,18 @@ public:
return Expression;
}
+ SourceRange getTemplateQualifierRange() const {
+ assert(Kind == K_Template);
+ return SourceRange(
+ SourceLocation::getFromRawEncoding(Template.QualifierRange[0]),
+ SourceLocation::getFromRawEncoding(Template.QualifierRange[1]));
+ }
+
+ SourceLocation getTemplateNameLoc() const {
+ assert(Kind == K_Template);
+ return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
+ }
+
#ifndef NDEBUG
void validateForArgument(const TemplateArgument &Arg) {
switch (Arg.getKind()) {
@@ -294,6 +347,9 @@ public:
case TemplateArgument::Declaration:
assert(Kind == K_Expression);
break;
+ case TemplateArgument::Template:
+ assert(Kind == K_Template);
+ break;
case TemplateArgument::Integral:
case TemplateArgument::Pack:
assert(Kind == K_None);
@@ -329,8 +385,18 @@ public:
assert(Argument.getKind() == TemplateArgument::Expression);
}
- /// \brief - Fetches the start location of the argument.
+ TemplateArgumentLoc(const TemplateArgument &Argument,
+ SourceRange QualifierRange,
+ SourceLocation TemplateNameLoc)
+ : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) {
+ assert(Argument.getKind() == TemplateArgument::Template);
+ }
+
+ /// \brief - Fetches the primary location of the argument.
SourceLocation getLocation() const {
+ if (Argument.getKind() == TemplateArgument::Template)
+ return getTemplateNameLoc();
+
return getSourceRange().getBegin();
}
@@ -359,6 +425,16 @@ public:
assert(Argument.getKind() == TemplateArgument::Declaration);
return LocInfo.getAsExpr();
}
+
+ SourceRange getTemplateQualifierRange() const {
+ assert(Argument.getKind() == TemplateArgument::Template);
+ return LocInfo.getTemplateQualifierRange();
+ }
+
+ SourceLocation getTemplateNameLoc() const {
+ assert(Argument.getKind() == TemplateArgument::Template);
+ return LocInfo.getTemplateNameLoc();
+ }
};
}
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index da7857822e..a06b9b82d0 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -919,6 +919,10 @@ public:
Info = TemplateArgumentLocInfo((DeclaratorInfo*) 0);
break;
+ case TemplateArgument::Template:
+ Info = TemplateArgumentLocInfo(SourceRange(), SourceLocation());
+ break;
+
case TemplateArgument::Integral:
case TemplateArgument::Pack:
case TemplateArgument::Null:
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 036d887865..28c46cd2d7 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -289,6 +289,10 @@ def err_explicit_spec_non_template : Error<
def err_variadic_templates : Error<
"variadic templates are only allowed in C++0x">;
+def err_default_template_template_parameter_not_template : Error<
+ "default template argument for a template template parameter must be a class "
+ "template">;
+
// C++ declarations
def err_friend_decl_defines_class : Error<
"cannot define a type in a friend declaration">;
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 4886970c74..ceeb9c40e5 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -1577,7 +1577,7 @@ public:
/// parameter.
virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
SourceLocation EqualLoc,
- ExprArg Default) {
+ const ParsedTemplateArgument &Default) {
}
/// ActOnTemplateParameterList - Called when a complete template
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index dd939a98bf..548d746859 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1371,6 +1371,7 @@ private:
bool AllowTypeAnnotation = true);
void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0);
bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
+ ParsedTemplateArgument ParseTemplateTemplateArgument();
ParsedTemplateArgument ParseTemplateArgument();
DeclPtrTy ParseExplicitInstantiation(SourceLocation ExternLoc,
SourceLocation TemplateLoc,
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();
+}
+
+///