[cfe-commits] r107354 - in /cfe/trunk: include/clang/Parse/Action.h include/clang/Parse/Template.h lib/Parse/ParseTemplate.cpp lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp
Douglas Gregor
dgregor at apple.com
Wed Jun 30 17:00:45 PDT 2010
Author: dgregor
Date: Wed Jun 30 19:00:45 2010
New Revision: 107354
URL: http://llvm.org/viewvc/llvm-project?rev=107354&view=rev
Log:
Implement C++ DR481, which clarifies that the scope of template
parameters starts at the end of the template-parameter rather than at
the point where the template parameter name is encounted. For example,
given:
typedef unsigned char T;
template<typename T = T> struct X0 { };
The "T" in the default argument refers to the typedef of "unsigned
char", rather than referring to the newly-introduced template type
parameter 'T'.
Addresses <rdar://problem/8122812>.
Modified:
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/include/clang/Parse/Template.h
cfe/trunk/lib/Parse/ParseTemplate.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplate.cpp
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=107354&r1=107353&r2=107354&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Wed Jun 30 19:00:45 2010
@@ -1833,46 +1833,87 @@
//===---------------------------C++ Templates----------------------------===//
- /// 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
- /// (otherwise, "class" was used), ellipsis specifies whether this is a
- /// C++0x parameter pack, EllipsisLoc specifies the start of the ellipsis,
- /// and KeyLoc is the location of the "class" or "typename" keyword.
- // ParamName is the name of the parameter (NULL indicates an unnamed template
- // parameter) and ParamNameLoc is the location of the parameter name (if any)
- /// If the type parameter has a default argument, it will be added
- /// later via ActOnTypeParameterDefault. Depth and Position provide
- /// the number of enclosing templates (see
- /// ActOnTemplateParameterList) and the number of previous
- /// parameters within this template parameter list.
+ /// \brief Called when a C++ template type parameter(e.g., "typename T") has
+ /// been parsed.
+ ///
+ /// Given
+ ///
+ /// \code
+ /// template<typename T, typename U = T> struct pair;
+ /// \endcode
+ ///
+ /// this callback will be invoked twice: once for the type parameter \c T
+ /// with \p Depth=0 and \p Position=0, and once for the type parameter \c U
+ /// with \p Depth=0 and \p Position=1.
+ ///
+ /// \param Typename Specifies whether the keyword "typename" was used to
+ /// declare the type parameter (otherwise, "class" was used).
+ ///
+ /// \param Ellipsis Specifies whether this is a C++0x parameter pack.
+ ///
+ /// \param EllipsisLoc Specifies the start of the ellipsis.
+ ///
+ /// \param KeyLoc The location of the "class" or "typename" keyword.
+ ///
+ /// \param ParamName The name of the parameter, where NULL indicates an
+ /// unnamed template parameter.
+ ///
+ /// \param ParamNameLoc The location of the parameter name (if any).
+ ///
+ /// \param Depth The depth of this template parameter, e.g., the number of
+ /// template parameter lists that occurred outside the template parameter
+ /// list in which this template type parameter occurs.
+ ///
+ /// \param Position The zero-based position of this template parameter within
+ /// its template parameter list, which is also the number of template
+ /// parameters that precede this parameter in the template parameter list.
+ ///
+ /// \param EqualLoc The location of the '=' sign for the default template
+ /// argument, if any.
+ ///
+ /// \param DefaultArg The default argument, if provided.
virtual DeclPtrTy ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
SourceLocation EllipsisLoc,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
SourceLocation ParamNameLoc,
- unsigned Depth, unsigned Position) {
+ unsigned Depth, unsigned Position,
+ SourceLocation EqualLoc,
+ TypeTy *DefaultArg) {
return DeclPtrTy();
}
- /// ActOnTypeParameterDefault - Adds a default argument (the type
- /// Default) to the given template type parameter (TypeParam).
- virtual void ActOnTypeParameterDefault(DeclPtrTy TypeParam,
- SourceLocation EqualLoc,
- SourceLocation DefaultLoc,
- TypeTy *Default) {
- }
-
- /// ActOnNonTypeTemplateParameter - Called when a C++ non-type
- /// template parameter (e.g., "int Size" in "template<int Size>
- /// class Array") has been parsed. S is the current scope and D is
- /// the parsed declarator. Depth and Position provide the number of
- /// enclosing templates (see
- /// ActOnTemplateParameterList) and the number of previous
- /// parameters within this template parameter list.
+ /// \brief Called when a C++ non-type template parameter has been parsed.
+ ///
+ /// Given
+ ///
+ /// \code
+ /// template<int Size> class Array;
+ /// \endcode
+ ///
+ /// This callback will be invoked for the 'Size' non-type template parameter.
+ ///
+ /// \param S The current scope.
+ ///
+ /// \param D The parsed declarator.
+ ///
+ /// \param Depth The depth of this template parameter, e.g., the number of
+ /// template parameter lists that occurred outside the template parameter
+ /// list in which this template type parameter occurs.
+ ///
+ /// \param Position The zero-based position of this template parameter within
+ /// its template parameter list, which is also the number of template
+ /// parameters that precede this parameter in the template parameter list.
+ ///
+ /// \param EqualLoc The location of the '=' sign for the default template
+ /// argument, if any.
+ ///
+ /// \param DefaultArg The default argument, if provided.
virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
unsigned Depth,
- unsigned Position) {
+ unsigned Position,
+ SourceLocation EqualLoc,
+ ExprArg DefaultArg) {
return DeclPtrTy();
}
@@ -1883,29 +1924,50 @@
ExprArg Default) {
}
- /// ActOnTemplateTemplateParameter - Called when a C++ template template
- /// parameter (e.g., "int T" in "template<template <typename> class T> class
- /// Array") has been parsed. TmpLoc is the location of the "template" keyword,
- /// TemplateParams is the sequence of parameters required by the template,
- /// ParamName is the name of the parameter (null if unnamed), and ParamNameLoc
- /// is the source location of the identifier (if given).
+ /// \brief Called when a C++ template template parameter has been parsed.
+ ///
+ /// Given
+ ///
+ /// \code
+ /// template<template <typename> class T> class X;
+ /// \endcode
+ ///
+ /// this callback will be invoked for the template template parameter \c T.
+ ///
+ /// \param S The scope in which this template template parameter occurs.
+ ///
+ /// \param TmpLoc The location of the "template" keyword.
+ ///
+ /// \param TemplateParams The template parameters required by the template.
+ ///
+ /// \param ParamName The name of the parameter, or NULL if unnamed.
+ ///
+ /// \param ParamNameLoc The source location of the parameter name (if given).
+ ///
+ /// \param Depth The depth of this template parameter, e.g., the number of
+ /// template parameter lists that occurred outside the template parameter
+ /// list in which this template parameter occurs.
+ ///
+ /// \param Position The zero-based position of this template parameter within
+ /// its template parameter list, which is also the number of template
+ /// parameters that precede this parameter in the template parameter list.
+ ///
+ /// \param EqualLoc The location of the '=' sign for the default template
+ /// argument, if any.
+ ///
+ /// \param DefaultArg The default argument, if provided.
virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S,
SourceLocation TmpLoc,
TemplateParamsTy *Params,
IdentifierInfo *ParamName,
SourceLocation ParamNameLoc,
unsigned Depth,
- unsigned Position) {
+ unsigned Position,
+ SourceLocation EqualLoc,
+ const ParsedTemplateArgument &DefaultArg) {
return DeclPtrTy();
}
- /// \brief Adds a default argument to the given template template
- /// parameter.
- virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
- SourceLocation EqualLoc,
- const ParsedTemplateArgument &Default) {
- }
-
/// ActOnTemplateParameterList - Called when a complete template
/// parameter list has been parsed, e.g.,
///
Modified: cfe/trunk/include/clang/Parse/Template.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Template.h?rev=107354&r1=107353&r2=107354&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Template.h (original)
+++ cfe/trunk/include/clang/Parse/Template.h Wed Jun 30 19:00:45 2010
@@ -58,7 +58,7 @@
Loc(TemplateLoc), SS(SS) { }
/// \brief Determine whether the given template argument is invalid.
- bool isInvalid() { return Arg == 0; }
+ bool isInvalid() const { return Arg == 0; }
/// \brief Determine what kind of template argument we have.
KindType getKind() const { return Kind; }
Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=107354&r1=107353&r2=107354&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Wed Jun 30 19:00:45 2010
@@ -471,22 +471,19 @@
return DeclPtrTy();
}
- DeclPtrTy TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword,
- Ellipsis, EllipsisLoc,
- KeyLoc, ParamName, NameLoc,
- Depth, Position);
-
- // Grab a default type id (if given).
+ // Grab a default argument (if available).
+ // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
+ // we introduce the type parameter into the local scope.
+ SourceLocation EqualLoc;
+ TypeTy *DefaultArg = 0;
if (Tok.is(tok::equal)) {
- SourceLocation EqualLoc = ConsumeToken();
- SourceLocation DefaultLoc = Tok.getLocation();
- TypeResult DefaultType = ParseTypeName();
- if (!DefaultType.isInvalid())
- Actions.ActOnTypeParameterDefault(TypeParam, EqualLoc, DefaultLoc,
- DefaultType.get());
+ EqualLoc = ConsumeToken();
+ DefaultArg = ParseTypeName().get();
}
-
- return TypeParam;
+
+ return Actions.ActOnTypeParameter(CurScope, TypenameKeyword, Ellipsis,
+ EllipsisLoc, KeyLoc, ParamName, NameLoc,
+ Depth, Position, EqualLoc, DefaultArg);
}
/// ParseTemplateTemplateParameter - Handle the parsing of template
@@ -541,28 +538,28 @@
TemplateParams.size(),
RAngleLoc);
- Parser::DeclPtrTy Param
- = Actions.ActOnTemplateTemplateParameter(CurScope, TemplateLoc,
- ParamList, ParamName,
- NameLoc, Depth, Position);
-
- // Get the a default value, if given.
+ // Grab a default argument (if available).
+ // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
+ // we introduce the template parameter into the local scope.
+ SourceLocation EqualLoc;
+ ParsedTemplateArgument DefaultArg;
if (Tok.is(tok::equal)) {
- SourceLocation EqualLoc = ConsumeToken();
- ParsedTemplateArgument Default = ParseTemplateTemplateArgument();
- if (Default.isInvalid()) {
+ EqualLoc = ConsumeToken();
+ DefaultArg = ParseTemplateTemplateArgument();
+ if (DefaultArg.isInvalid()) {
Diag(Tok.getLocation(),
diag::err_default_template_template_parameter_not_template);
static const tok::TokenKind EndToks[] = {
tok::comma, tok::greater, tok::greatergreater
};
SkipUntil(EndToks, 3, true, true);
- return Param;
- } else if (Param)
- Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc, Default);
+ }
}
-
- return Param;
+
+ return Actions.ActOnTemplateTemplateParameter(CurScope, TemplateLoc,
+ ParamList, ParamName,
+ NameLoc, Depth, Position,
+ EqualLoc, DefaultArg);
}
/// ParseNonTypeTemplateParameter - Handle the parsing of non-type
@@ -571,13 +568,6 @@
/// template-parameter:
/// ...
/// parameter-declaration
-///
-/// NOTE: It would be ideal to simply call out to ParseParameterDeclaration(),
-/// but that didn't work out to well. Instead, this tries to recrate the basic
-/// parsing of parameter declarations, but tries to constrain it for template
-/// parameters.
-/// FIXME: We need to make a ParseParameterDeclaration that works for
-/// non-type template parameters and normal function parameters.
Parser::DeclPtrTy
Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
SourceLocation StartLoc = Tok.getLocation();
@@ -601,13 +591,13 @@
return DeclPtrTy();
}
- // Create the parameter.
- DeclPtrTy Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl,
- Depth, Position);
-
// If there is a default value, parse it.
+ // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
+ // we introduce the template parameter into the local scope.
+ SourceLocation EqualLoc;
+ OwningExprResult DefaultArg(Actions);
if (Tok.is(tok::equal)) {
- SourceLocation EqualLoc = ConsumeToken();
+ EqualLoc = ConsumeToken();
// C++ [temp.param]p15:
// When parsing a default template-argument for a non-type
@@ -616,15 +606,15 @@
// operator.
GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
- OwningExprResult DefaultArg = ParseAssignmentExpression();
+ DefaultArg = ParseAssignmentExpression();
if (DefaultArg.isInvalid())
SkipUntil(tok::comma, tok::greater, true, true);
- else if (Param)
- Actions.ActOnNonTypeTemplateParameterDefault(Param, EqualLoc,
- move(DefaultArg));
}
- return Param;
+ // Create the parameter.
+ return Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl,
+ Depth, Position, EqualLoc,
+ move(DefaultArg));
}
/// \brief Parses a template-id that after the template name has
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=107354&r1=107353&r2=107354&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Jun 30 19:00:45 2010
@@ -2861,29 +2861,25 @@
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
SourceLocation ParamNameLoc,
- unsigned Depth, unsigned Position);
- virtual void ActOnTypeParameterDefault(DeclPtrTy TypeParam,
- SourceLocation EqualLoc,
- SourceLocation DefaultLoc,
- TypeTy *Default);
+ unsigned Depth, unsigned Position,
+ SourceLocation EqualLoc,
+ TypeTy *DefaultArg);
QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
unsigned Depth,
- unsigned Position);
- virtual void ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParam,
- SourceLocation EqualLoc,
- ExprArg Default);
+ unsigned Position,
+ SourceLocation EqualLoc,
+ ExprArg DefaultArg);
virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S,
SourceLocation TmpLoc,
TemplateParamsTy *Params,
IdentifierInfo *ParamName,
SourceLocation ParamNameLoc,
unsigned Depth,
- unsigned Position);
- virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
- SourceLocation EqualLoc,
- const ParsedTemplateArgument &Default);
+ unsigned Position,
+ SourceLocation EqualLoc,
+ const ParsedTemplateArgument &DefaultArg);
virtual TemplateParamsTy *
ActOnTemplateParameterList(unsigned Depth,
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=107354&r1=107353&r2=107354&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Jun 30 19:00:45 2010
@@ -459,7 +459,9 @@
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
SourceLocation ParamNameLoc,
- unsigned Depth, unsigned Position) {
+ unsigned Depth, unsigned Position,
+ SourceLocation EqualLoc,
+ TypeTy *DefaultArg) {
assert(S->isTemplateParamScope() &&
"Template type parameter not in template parameter scope!");
bool Invalid = false;
@@ -490,42 +492,31 @@
IdResolver.AddDecl(Param);
}
- return DeclPtrTy::make(Param);
-}
-
-/// ActOnTypeParameterDefault - Adds a default argument (the type
-/// Default) to the given template type parameter (TypeParam).
-void Sema::ActOnTypeParameterDefault(DeclPtrTy TypeParam,
- SourceLocation EqualLoc,
- SourceLocation DefaultLoc,
- TypeTy *DefaultT) {
- TemplateTypeParmDecl *Parm
- = cast<TemplateTypeParmDecl>(TypeParam.getAs<Decl>());
-
- TypeSourceInfo *DefaultTInfo;
- GetTypeFromParser(DefaultT, &DefaultTInfo);
-
- assert(DefaultTInfo && "expected source information for type");
-
- // C++0x [temp.param]p9:
- // A default template-argument may be specified for any kind of
- // template-parameter that is not a template parameter pack.
- if (Parm->isParameterPack()) {
- Diag(DefaultLoc, diag::err_template_param_pack_default_arg);
- return;
- }
-
- // 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 template argument itself.
- if (CheckTemplateArgument(Parm, DefaultTInfo)) {
- Parm->setInvalidDecl();
- return;
+ // Handle the default argument, if provided.
+ if (DefaultArg) {
+ TypeSourceInfo *DefaultTInfo;
+ GetTypeFromParser(DefaultArg, &DefaultTInfo);
+
+ assert(DefaultTInfo && "expected source information for type");
+
+ // C++0x [temp.param]p9:
+ // A default template-argument may be specified for any kind of
+ // template-parameter that is not a template parameter pack.
+ if (Ellipsis) {
+ Diag(EqualLoc, diag::err_template_param_pack_default_arg);
+ return DeclPtrTy::make(Param);
+ }
+
+ // Check the template argument itself.
+ if (CheckTemplateArgument(Param, DefaultTInfo)) {
+ Param->setInvalidDecl();
+ return DeclPtrTy::make(Param);;
+ }
+
+ Param->setDefaultArgument(DefaultTInfo, false);
}
-
- Parm->setDefaultArgument(DefaultTInfo, false);
+
+ return DeclPtrTy::make(Param);
}
/// \brief Check that the type of a non-type template parameter is
@@ -580,13 +571,11 @@
return QualType();
}
-/// ActOnNonTypeTemplateParameter - Called when a C++ non-type
-/// template parameter (e.g., "int Size" in "template<int Size>
-/// class Array") has been parsed. S is the current scope and D is
-/// the parsed declarator.
Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
unsigned Depth,
- unsigned Position) {
+ unsigned Position,
+ SourceLocation EqualLoc,
+ ExprArg DefaultArg) {
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType T = TInfo->getType();
@@ -622,34 +611,21 @@
S->AddDecl(DeclPtrTy::make(Param));
IdResolver.AddDecl(Param);
}
- return DeclPtrTy::make(Param);
-}
-
-/// \brief Adds a default argument to the given non-type template
-/// parameter.
-void Sema::ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParamD,
- SourceLocation EqualLoc,
- ExprArg DefaultE) {
- NonTypeTemplateParmDecl *TemplateParm
- = cast<NonTypeTemplateParmDecl>(TemplateParamD.getAs<Decl>());
- Expr *Default = 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 default template argument.
- TemplateArgument Converted;
- if (CheckTemplateArgument(TemplateParm, TemplateParm->getType(), Default,
- Converted)) {
- TemplateParm->setInvalidDecl();
- return;
+
+ // Check the well-formedness of the default template argument, if provided.
+ if (Expr *Default = static_cast<Expr *>(DefaultArg.get())) {
+ TemplateArgument Converted;
+ if (CheckTemplateArgument(Param, Param->getType(), Default, Converted)) {
+ Param->setInvalidDecl();
+ return DeclPtrTy::make(Param);;
+ }
+
+ Param->setDefaultArgument(DefaultArg.takeAs<Expr>(), false);
}
-
- TemplateParm->setDefaultArgument(DefaultE.takeAs<Expr>(), false);
+
+ return DeclPtrTy::make(Param);
}
-
/// ActOnTemplateTemplateParameter - Called when a C++ template template
/// parameter (e.g. T in template <template <typename> class T> class array)
/// has been parsed. S is the current scope.
@@ -659,7 +635,9 @@
IdentifierInfo *Name,
SourceLocation NameLoc,
unsigned Depth,
- unsigned Position) {
+ unsigned Position,
+ SourceLocation EqualLoc,
+ const ParsedTemplateArgument &Default) {
assert(S->isTemplateParamScope() &&
"Template template parameter not in template parameter scope!");
@@ -669,53 +647,33 @@
TmpLoc, Depth, Position, Name,
(TemplateParameterList*)Params);
- // Make sure the parameter is valid.
- // FIXME: Decl object is not currently invalidated anywhere so this doesn't
- // do anything yet. However, if the template parameter list or (eventual)
- // default value is ever invalidated, that will propagate here.
- bool Invalid = false;
- if (Invalid) {
- Param->setInvalidDecl();
- }
-
- // If the tt-param has a name, then link the identifier into the scope
- // and lookup mechanisms.
+ // If the template template parameter has a name, then link the identifier
+ // into the scope and lookup mechanisms.
if (Name) {
S->AddDecl(DeclPtrTy::make(Param));
IdResolver.AddDecl(Param);
}
- return DeclPtrTy::make(Param);
-}
-
-/// \brief Adds a default argument to the given template template
-/// parameter.
-void Sema::ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParamD,
- SourceLocation EqualLoc,
- const ParsedTemplateArgument &Default) {
- TemplateTemplateParmDecl *TemplateParm
- = cast<TemplateTemplateParmDecl>(TemplateParamD.getAs<Decl>());
-
- // 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 only that we have a template template argument. We don't want to
- // try to check well-formedness now, because our template template parameter
- // might have dependent types in its template parameters, which we wouldn't
- // be able to match now.
- //
- // If none of the template template parameter's template arguments mention
- // other template parameters, we could actually perform more checking here.
- // However, it isn't worth doing.
- TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default);
- if (DefaultArg.getArgument().getAsTemplate().isNull()) {
- Diag(DefaultArg.getLocation(), diag::err_template_arg_not_class_template)
- << DefaultArg.getSourceRange();
- return;
+ if (!Default.isInvalid()) {
+ // Check only that we have a template template argument. We don't want to
+ // try to check well-formedness now, because our template template parameter
+ // might have dependent types in its template parameters, which we wouldn't
+ // be able to match now.
+ //
+ // If none of the template template parameter's template arguments mention
+ // other template parameters, we could actually perform more checking here.
+ // However, it isn't worth doing.
+ TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default);
+ if (DefaultArg.getArgument().getAsTemplate().isNull()) {
+ Diag(DefaultArg.getLocation(), diag::err_template_arg_not_class_template)
+ << DefaultArg.getSourceRange();
+ return DeclPtrTy::make(Param);
+ }
+
+ Param->setDefaultArgument(DefaultArg, false);
}
- TemplateParm->setDefaultArgument(DefaultArg, false);
+ return DeclPtrTy::make(Param);
}
/// ActOnTemplateParameterList - Builds a TemplateParameterList that
More information about the cfe-commits
mailing list