[cfe-commits] r86777 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Parse/ lib/AST/ lib/Frontend/ lib/Parse/ lib/Sema/ test/SemaTemplate/
Douglas Gregor
dgregor at apple.com
Tue Nov 10 17:00:40 PST 2009
Author: dgregor
Date: Tue Nov 10 19:00:40 2009
New Revision: 86777
URL: http://llvm.org/viewvc/llvm-project?rev=86777&view=rev
Log:
Introduce a new representation for template template
parameters. Rather than storing them as either declarations (for the
non-dependent case) or expressions (for the dependent case), we now
(always) store them as TemplateNames.
The primary change here is to add a new kind of TemplateArgument,
which stores a TemplateName. However, making that change ripples to
every switch on a TemplateArgument's kind, also affecting
TemplateArgumentLocInfo/TemplateArgumentLoc, default template
arguments for template template parameters, type-checking of template
template arguments, etc.
This change is light on testing. It should fix several pre-existing
problems with template template parameters, such as:
- the inability to use dependent template names as template template
arguments
- template template parameter default arguments cannot be
instantiation
However, there are enough pieces missing that more implementation is
required before we can adequately test template template parameters.
Modified:
cfe/trunk/include/clang/AST/DeclTemplate.h
cfe/trunk/include/clang/AST/TemplateBase.h
cfe/trunk/include/clang/AST/TypeLoc.h
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/DeclTemplate.cpp
cfe/trunk/lib/AST/StmtProfile.cpp
cfe/trunk/lib/AST/TemplateBase.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/AST/TypePrinter.cpp
cfe/trunk/lib/Frontend/PCHReader.cpp
cfe/trunk/lib/Frontend/PCHWriter.cpp
cfe/trunk/lib/Parse/ParseTemplate.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaLookup.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp
cfe/trunk/test/SemaTemplate/temp_arg_template.cpp
Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Tue Nov 10 19:00:40 2009
@@ -699,13 +699,13 @@
: 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 @@
/// \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;
}
Modified: cfe/trunk/include/clang/AST/TemplateBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TemplateBase.h?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TemplateBase.h (original)
+++ cfe/trunk/include/clang/AST/TemplateBase.h Tue Nov 10 19:00:40 2009
@@ -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 @@
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 @@
}
/// \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 @@
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 @@
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 @@
, 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 @@
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 @@
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 @@
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 @@
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();
+ }
};
}
Modified: cfe/trunk/include/clang/AST/TypeLoc.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeLoc.h (original)
+++ cfe/trunk/include/clang/AST/TypeLoc.h Tue Nov 10 19:00:40 2009
@@ -919,6 +919,10 @@
Info = TemplateArgumentLocInfo((DeclaratorInfo*) 0);
break;
+ case TemplateArgument::Template:
+ Info = TemplateArgumentLocInfo(SourceRange(), SourceLocation());
+ break;
+
case TemplateArgument::Integral:
case TemplateArgument::Pack:
case TemplateArgument::Null:
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Tue Nov 10 19:00:40 2009
@@ -289,6 +289,10 @@
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">;
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Tue Nov 10 19:00:40 2009
@@ -1577,7 +1577,7 @@
/// parameter.
virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
SourceLocation EqualLoc,
- ExprArg Default) {
+ const ParsedTemplateArgument &Default) {
}
/// ActOnTemplateParameterList - Called when a complete template
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Nov 10 19:00:40 2009
@@ -1371,6 +1371,7 @@
bool AllowTypeAnnotation = true);
void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0);
bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
+ ParsedTemplateArgument ParseTemplateTemplateArgument();
ParsedTemplateArgument ParseTemplateArgument();
DeclPtrTy ParseExplicitInstantiation(SourceLocation ExternLoc,
SourceLocation TemplateLoc,
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Nov 10 19:00:40 2009
@@ -2357,12 +2357,14 @@
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()));
Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Tue Nov 10 19:00:40 2009
@@ -220,7 +220,7 @@
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 @@
return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params);
}
-SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
- return DefaultArgument? DefaultArgument->getSourceRange().getBegin()
- : SourceLocation();
-}
-
//===----------------------------------------------------------------------===//
// TemplateArgumentListBuilder Implementation
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Tue Nov 10 19:00:40 2009
@@ -695,6 +695,10 @@
VisitType(Arg.getAsType());
break;
+ case TemplateArgument::Template:
+ VisitTemplateName(Arg.getAsTemplate());
+ break;
+
case TemplateArgument::Declaration:
VisitDecl(Arg.getAsDecl());
break;
Modified: cfe/trunk/lib/AST/TemplateBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TemplateBase.cpp?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TemplateBase.cpp (original)
+++ cfe/trunk/lib/AST/TemplateBase.cpp Tue Nov 10 19:00:40 2009
@@ -58,6 +58,10 @@
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 @@
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:
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Tue Nov 10 19:00:40 2009
@@ -807,6 +807,9 @@
case TemplateArgument::Type:
return Arg.getAsType()->isDependentType();
+ case TemplateArgument::Template:
+ return Arg.getAsTemplate().isDependent();
+
case TemplateArgument::Declaration:
case TemplateArgument::Integral:
// Never dependent
Modified: cfe/trunk/lib/AST/TypePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)
+++ cfe/trunk/lib/AST/TypePrinter.cpp Tue Nov 10 19:00:40 2009
@@ -576,6 +576,11 @@
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;
Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Tue Nov 10 19:00:40 2009
@@ -2185,6 +2185,14 @@
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:
Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Tue Nov 10 19:00:40 2009
@@ -2122,6 +2122,12 @@
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:
Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Tue Nov 10 19:00:40 2009
@@ -485,12 +485,17 @@
// 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 @@
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 @@
//
// 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();
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Nov 10 19:00:40 2009
@@ -2446,7 +2446,7 @@
unsigned Position);
virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
SourceLocation EqualLoc,
- ExprArg Default);
+ const ParsedTemplateArgument &Default);
virtual TemplateParamsTy *
ActOnTemplateParameterList(unsigned Depth,
@@ -2606,13 +2606,14 @@
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);
Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Tue Nov 10 19:00:40 2009
@@ -1219,12 +1219,13 @@
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 @@
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
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Nov 10 19:00:40 2009
@@ -284,6 +284,46 @@
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 @@
/// 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 @@
= 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 @@
// 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 @@
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 @@
/// \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 @@
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 @@
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 @@
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 @@
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 @@
/// 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) {
- assert(isa<TemplateDecl>(Arg->getDecl()) && "Only template decls allowed");
- TemplateDecl *Template = cast<TemplateDecl>(Arg->getDecl());
+ const TemplateArgumentLoc &Arg) {
+ TemplateName Name = Arg.getArgument().getAsTemplate();
+ TemplateDecl *Template = Name.getAsTemplateDecl();
+ if (!Template) {
+ // Any dependent template name is fine.
+ assert(Name.isDependent() && "Non-dependent template isn't a declaration?");
+ return false;
+ }
// C++ [temp.arg.template]p1:
// A template-argument for a template template-parameter shall be
@@ -2376,7 +2446,7 @@
!isa<TemplateTemplateParmDecl>(Template)) {
assert(isa<FunctionTemplateDecl>(Template) &&
"Only function templates are possible here");
- Diag(Arg->getLocStart(), diag::err_template_arg_not_class_template);
+ Diag(Arg.getLocation(), diag::err_template_arg_not_class_template);
Diag(Template->getLocation(), diag::note_template_arg_refers_here_func)
<< Template;
}
@@ -2384,7 +2454,7 @@
return !TemplateParameterListsAreEqual(Template->getTemplateParameters(),
Param->getTemplateParameters(),
true, true,
- Arg->getSourceRange().getBegin());
+ Arg.getLocation());
}
/// \brief Determine whether the given template parameter lists are
@@ -2735,16 +2805,9 @@
} else if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(
TemplateParams->getParam(I))) {
- // FIXME: We should settle on either Declaration storage or
- // Expression storage for template template parameters.
+ TemplateName Name = ArgList[I].getAsTemplate();
TemplateTemplateParmDecl *ArgDecl
- = dyn_cast_or_null<TemplateTemplateParmDecl>(
- ArgList[I].getAsDecl());
- if (!ArgDecl)
- if (DeclRefExpr *DRE
- = dyn_cast_or_null<DeclRefExpr>(ArgList[I].getAsExpr()))
- ArgDecl = dyn_cast<TemplateTemplateParmDecl>(DRE->getDecl());
-
+ = dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl());
if (!ArgDecl ||
ArgDecl->getIndex() != TTP->getIndex() ||
ArgDecl->getDepth() != TTP->getDepth())
@@ -2871,12 +2934,11 @@
}
} else {
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param);
- if (Expr *DefArg = TTP->getDefaultArgument()) {
- Diag(TTP->getDefaultArgumentLoc(),
+ if (TTP->hasDefaultArgument()) {
+ Diag(TTP->getDefaultArgument().getLocation(),
diag::err_default_arg_in_partial_spec)
- << DefArg->getSourceRange();
- TTP->setDefaultArgument(0);
- DefArg->Destroy(Context);
+ << TTP->getDefaultArgument().getSourceRange();
+ TTP->setDefaultArgument(TemplateArgumentLoc());
}
}
}
@@ -4580,6 +4642,14 @@
break;
}
+ case TemplateArgument::Template: {
+ std::string Str;
+ llvm::raw_string_ostream OS(Str);
+ Args[I].getAsTemplate().print(OS, Context.PrintingPolicy);
+ Result += OS.str();
+ break;
+ }
+
case TemplateArgument::Integral: {
Result += Args[I].getAsIntegral()->toString(10);
break;
Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Tue Nov 10 19:00:40 2009
@@ -785,13 +785,32 @@
break;
case TemplateArgument::Type:
- assert(Arg.getKind() == TemplateArgument::Type && "Type/value mismatch");
- return DeduceTemplateArguments(Context, TemplateParams, Param.getAsType(),
- Arg.getAsType(), Info, Deduced, 0);
-
+ if (Arg.getKind() == TemplateArgument::Type)
+ return DeduceTemplateArguments(Context, TemplateParams, Param.getAsType(),
+ Arg.getAsType(), Info, Deduced, 0);
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
+
+ case TemplateArgument::Template:
+#if 0
+ // FIXME: We need template argument deduction for template template
+ // parameters.
+ if (Arg.getKind() == TemplateArgument::Template)
+ return DeduceTemplateArguments(Context, TemplateParams,
+ Param.getAsTemplate(),
+ Arg.getAsTemplate(), Info, Deduced, 0);
+#endif
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
+
case TemplateArgument::Declaration:
- // FIXME: Implement this check
- assert(false && "Unimplemented template argument deduction case");
+ if (Arg.getKind() == TemplateArgument::Declaration &&
+ Param.getAsDecl()->getCanonicalDecl() ==
+ Arg.getAsDecl()->getCanonicalDecl())
+ return Sema::TDK_Success;
+
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
@@ -885,13 +904,21 @@
return X.getAsDecl()->getCanonicalDecl() ==
Y.getAsDecl()->getCanonicalDecl();
+ case TemplateArgument::Template:
+ return Context.getCanonicalTemplateName(X.getAsTemplate())
+ .getAsVoidPointer() ==
+ Context.getCanonicalTemplateName(Y.getAsTemplate())
+ .getAsVoidPointer();
+
case TemplateArgument::Integral:
return *X.getAsIntegral() == *Y.getAsIntegral();
- case TemplateArgument::Expression:
- // FIXME: We assume that all expressions are distinct, but we should
- // really check their canonical forms.
- return false;
+ case TemplateArgument::Expression: {
+ llvm::FoldingSetNodeID XID, YID;
+ X.getAsExpr()->Profile(XID, Context, true);
+ Y.getAsExpr()->Profile(YID, Context, true);
+ return XID == YID;
+ }
case TemplateArgument::Pack:
if (X.pack_size() != Y.pack_size())
@@ -1030,15 +1057,6 @@
Info.FirstArg = Partial->getTemplateArgs()[I];
return TDK_SubstitutionFailure;
}
- } else if (TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(Param)) {
- // FIXME: template template arguments should really resolve to decls
- DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InstExpr);
- if (!DRE || CheckTemplateArgument(TTP, DRE)) {
- Info.Param = makeTemplateParameter(Param);
- Info.FirstArg = Partial->getTemplateArgs()[I];
- return TDK_SubstitutionFailure;
- }
}
}
@@ -2153,6 +2171,9 @@
return;
}
+ if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName())
+ MarkUsedTemplateParameters(SemaRef, QTN->getQualifier(), OnlyDeduced,
+ Depth, Used);
if (DependentTemplateName *DTN = Name.getAsDependentTemplateName())
MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced,
Depth, Used);
@@ -2309,6 +2330,7 @@
switch (TemplateArg.getKind()) {
case TemplateArgument::Null:
case TemplateArgument::Integral:
+ case TemplateArgument::Declaration:
break;
case TemplateArgument::Type:
@@ -2316,12 +2338,9 @@
Depth, Used);
break;
- case TemplateArgument::Declaration:
- if (TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(TemplateArg.getAsDecl())) {
- if (TTP->getDepth() == Depth)
- Used[TTP->getIndex()] = true;
- }
+ case TemplateArgument::Template:
+ MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsTemplate(),
+ OnlyDeduced, Depth, Used);
break;
case TemplateArgument::Expression:
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Nov 10 19:00:40 2009
@@ -452,10 +452,11 @@
if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
- assert(TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsDecl() &&
+ TemplateName Template
+ = TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsTemplate();
+ assert(!Template.isNull() && Template.getAsTemplateDecl() &&
"Wrong kind of template template argument");
- return cast<TemplateDecl>(TemplateArgs(TTP->getDepth(),
- TTP->getPosition()).getAsDecl());
+ return Template.getAsTemplateDecl();
}
// If the corresponding template argument is NULL or non-existent, it's
@@ -466,9 +467,8 @@
TTP->getPosition()))
return D;
- // FIXME: Implement depth reduction of template template parameters
- assert(false &&
- "Reducing depth of template template parameters is not yet implemented");
+ // Fall through to find the instantiated declaration for this template
+ // template parameter.
}
return SemaRef.FindInstantiatedDecl(cast<NamedDecl>(D), TemplateArgs);
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Nov 10 19:00:40 2009
@@ -1957,6 +1957,10 @@
break;
+ case TemplateArgument::Template:
+ Output = TemplateArgumentLoc(Arg, SourceRange(), Loc);
+ break;
+
case TemplateArgument::Expression:
Output = TemplateArgumentLoc(Arg, Arg.getAsExpr());
break;
@@ -1997,7 +2001,7 @@
DeclarationName Name;
if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl()))
Name = ND->getDeclName();
- TemporaryBase Rebase(*this, SourceLocation(), Name);
+ TemporaryBase Rebase(*this, Input.getLocation(), Name);
Decl *D = getDerived().TransformDecl(Arg.getAsDecl());
if (!D) return true;
@@ -2018,6 +2022,19 @@
return false;
}
+ case TemplateArgument::Template: {
+ TemporaryBase Rebase(*this, Input.getLocation(), DeclarationName());
+ TemplateName Template
+ = getDerived().TransformTemplateName(Arg.getAsTemplate());
+ if (Template.isNull())
+ return true;
+
+ Output = TemplateArgumentLoc(TemplateArgument(Template),
+ Input.getTemplateQualifierRange(),
+ Input.getTemplateNameLoc());
+ return false;
+ }
+
case TemplateArgument::Expression: {
// Template argument expressions are not potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(getSema(),
Modified: cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp Tue Nov 10 19:00:40 2009
@@ -10,8 +10,7 @@
A<1 >> 2> *a3; // expected-warning{{use of right-shift operator ('>>') in template argument will require parentheses in C++0x}}
// C++ [temp.arg.nontype]p5:
-A<A> *a4; // expected-error{{must have an integral or enumeration type}} \
- // FIXME: the error message above is a bit lame
+A<A> *a4; // expected-error{{must be an expression}}
enum E { Enumerator = 17 };
A<E> *a5; // expected-error{{template argument for non-type template parameter must be an expression}}
Modified: cfe/trunk/test/SemaTemplate/temp_arg_template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_template.cpp?rev=86777&r1=86776&r2=86777&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_arg_template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_arg_template.cpp Tue Nov 10 19:00:40 2009
@@ -26,12 +26,9 @@
C<Y> *a7;
C<Ylong> *a8; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
-template<typename T> void f(int); // expected-note{{function template}}
+template<typename T> void f(int);
-// FIXME: we're right to provide an error message, but it should say
-// that we need a class template. We won't get this right until name
-// lookup of 'f' returns a TemplateDecl.
-A<f> *a9; // expected-error{{template argument does not refer to}}
+A<f> *a9; // expected-error{{must be a class template}}
// FIXME: The code below is ill-formed, because of the evil digraph '<:'.
// We should provide a much better error message than we currently do.
More information about the cfe-commits
mailing list