forked from OSchip/llvm-project
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>. llvm-svn: 107354
This commit is contained in:
parent
9dcde4bdec
commit
dc13ded606
|
@ -1833,46 +1833,87 @@ public:
|
|||
|
||||
//===---------------------------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 @@ public:
|
|||
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.,
|
||||
///
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace clang {
|
|||
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; }
|
||||
|
|
|
@ -471,22 +471,19 @@ Parser::DeclPtrTy Parser::ParseTypeParameter(unsigned Depth, unsigned Position){
|
|||
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 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
|
|||
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 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
|
|||
/// 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 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
|
|||
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 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
|
|||
// 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
|
||||
|
|
|
@ -2861,29 +2861,25 @@ public:
|
|||
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,
|
||||
|
|
|
@ -459,7 +459,9 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
|
|||
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,44 +492,33 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
|
|||
IdResolver.AddDecl(Param);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Parm->setDefaultArgument(DefaultTInfo, false);
|
||||
}
|
||||
|
||||
/// \brief Check that the type of a non-type template parameter is
|
||||
/// well-formed.
|
||||
///
|
||||
|
@ -580,13 +571,11 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
|
|||
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 @@ Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
|
|||
S->AddDecl(DeclPtrTy::make(Param));
|
||||
IdResolver.AddDecl(Param);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
TemplateParm->setDefaultArgument(DefaultE.takeAs<Expr>(), false);
|
||||
}
|
||||
|
||||
|
||||
/// 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 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S,
|
|||
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 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S,
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue