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----------------------------===//
|
//===---------------------------C++ Templates----------------------------===//
|
||||||
|
|
||||||
/// ActOnTypeParameter - Called when a C++ template type parameter
|
/// \brief Called when a C++ template type parameter(e.g., "typename T") has
|
||||||
/// (e.g., "typename T") has been parsed. Typename specifies whether
|
/// been parsed.
|
||||||
/// the keyword "typename" was used to declare the type parameter
|
///
|
||||||
/// (otherwise, "class" was used), ellipsis specifies whether this is a
|
/// Given
|
||||||
/// C++0x parameter pack, EllipsisLoc specifies the start of the ellipsis,
|
///
|
||||||
/// and KeyLoc is the location of the "class" or "typename" keyword.
|
/// \code
|
||||||
// ParamName is the name of the parameter (NULL indicates an unnamed template
|
/// template<typename T, typename U = T> struct pair;
|
||||||
// parameter) and ParamNameLoc is the location of the parameter name (if any)
|
/// \endcode
|
||||||
/// If the type parameter has a default argument, it will be added
|
///
|
||||||
/// later via ActOnTypeParameterDefault. Depth and Position provide
|
/// this callback will be invoked twice: once for the type parameter \c T
|
||||||
/// the number of enclosing templates (see
|
/// with \p Depth=0 and \p Position=0, and once for the type parameter \c U
|
||||||
/// ActOnTemplateParameterList) and the number of previous
|
/// with \p Depth=0 and \p Position=1.
|
||||||
/// parameters within this template parameter list.
|
///
|
||||||
|
/// \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,
|
virtual DeclPtrTy ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
|
||||||
SourceLocation EllipsisLoc,
|
SourceLocation EllipsisLoc,
|
||||||
SourceLocation KeyLoc,
|
SourceLocation KeyLoc,
|
||||||
IdentifierInfo *ParamName,
|
IdentifierInfo *ParamName,
|
||||||
SourceLocation ParamNameLoc,
|
SourceLocation ParamNameLoc,
|
||||||
unsigned Depth, unsigned Position) {
|
unsigned Depth, unsigned Position,
|
||||||
|
SourceLocation EqualLoc,
|
||||||
|
TypeTy *DefaultArg) {
|
||||||
return DeclPtrTy();
|
return DeclPtrTy();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ActOnTypeParameterDefault - Adds a default argument (the type
|
/// \brief Called when a C++ non-type template parameter has been parsed.
|
||||||
/// Default) to the given template type parameter (TypeParam).
|
///
|
||||||
virtual void ActOnTypeParameterDefault(DeclPtrTy TypeParam,
|
/// Given
|
||||||
SourceLocation EqualLoc,
|
///
|
||||||
SourceLocation DefaultLoc,
|
/// \code
|
||||||
TypeTy *Default) {
|
/// template<int Size> class Array;
|
||||||
}
|
/// \endcode
|
||||||
|
///
|
||||||
/// ActOnNonTypeTemplateParameter - Called when a C++ non-type
|
/// This callback will be invoked for the 'Size' non-type template parameter.
|
||||||
/// template parameter (e.g., "int Size" in "template<int Size>
|
///
|
||||||
/// class Array") has been parsed. S is the current scope and D is
|
/// \param S The current scope.
|
||||||
/// the parsed declarator. Depth and Position provide the number of
|
///
|
||||||
/// enclosing templates (see
|
/// \param D The parsed declarator.
|
||||||
/// ActOnTemplateParameterList) and the number of previous
|
///
|
||||||
/// parameters within this template parameter list.
|
/// \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,
|
virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
|
||||||
unsigned Depth,
|
unsigned Depth,
|
||||||
unsigned Position) {
|
unsigned Position,
|
||||||
|
SourceLocation EqualLoc,
|
||||||
|
ExprArg DefaultArg) {
|
||||||
return DeclPtrTy();
|
return DeclPtrTy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1883,29 +1924,50 @@ public:
|
||||||
ExprArg Default) {
|
ExprArg Default) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ActOnTemplateTemplateParameter - Called when a C++ template template
|
/// \brief Called when a C++ template template parameter has been parsed.
|
||||||
/// parameter (e.g., "int T" in "template<template <typename> class T> class
|
///
|
||||||
/// Array") has been parsed. TmpLoc is the location of the "template" keyword,
|
/// Given
|
||||||
/// TemplateParams is the sequence of parameters required by the template,
|
///
|
||||||
/// ParamName is the name of the parameter (null if unnamed), and ParamNameLoc
|
/// \code
|
||||||
/// is the source location of the identifier (if given).
|
/// 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,
|
virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S,
|
||||||
SourceLocation TmpLoc,
|
SourceLocation TmpLoc,
|
||||||
TemplateParamsTy *Params,
|
TemplateParamsTy *Params,
|
||||||
IdentifierInfo *ParamName,
|
IdentifierInfo *ParamName,
|
||||||
SourceLocation ParamNameLoc,
|
SourceLocation ParamNameLoc,
|
||||||
unsigned Depth,
|
unsigned Depth,
|
||||||
unsigned Position) {
|
unsigned Position,
|
||||||
|
SourceLocation EqualLoc,
|
||||||
|
const ParsedTemplateArgument &DefaultArg) {
|
||||||
return DeclPtrTy();
|
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
|
/// ActOnTemplateParameterList - Called when a complete template
|
||||||
/// parameter list has been parsed, e.g.,
|
/// parameter list has been parsed, e.g.,
|
||||||
///
|
///
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace clang {
|
||||||
Loc(TemplateLoc), SS(SS) { }
|
Loc(TemplateLoc), SS(SS) { }
|
||||||
|
|
||||||
/// \brief Determine whether the given template argument is invalid.
|
/// \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.
|
/// \brief Determine what kind of template argument we have.
|
||||||
KindType getKind() const { return Kind; }
|
KindType getKind() const { return Kind; }
|
||||||
|
|
|
@ -471,22 +471,19 @@ Parser::DeclPtrTy Parser::ParseTypeParameter(unsigned Depth, unsigned Position){
|
||||||
return DeclPtrTy();
|
return DeclPtrTy();
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclPtrTy TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword,
|
// Grab a default argument (if available).
|
||||||
Ellipsis, EllipsisLoc,
|
// Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
|
||||||
KeyLoc, ParamName, NameLoc,
|
// we introduce the type parameter into the local scope.
|
||||||
Depth, Position);
|
SourceLocation EqualLoc;
|
||||||
|
TypeTy *DefaultArg = 0;
|
||||||
// Grab a default type id (if given).
|
|
||||||
if (Tok.is(tok::equal)) {
|
if (Tok.is(tok::equal)) {
|
||||||
SourceLocation EqualLoc = ConsumeToken();
|
EqualLoc = ConsumeToken();
|
||||||
SourceLocation DefaultLoc = Tok.getLocation();
|
DefaultArg = ParseTypeName().get();
|
||||||
TypeResult DefaultType = ParseTypeName();
|
|
||||||
if (!DefaultType.isInvalid())
|
|
||||||
Actions.ActOnTypeParameterDefault(TypeParam, EqualLoc, DefaultLoc,
|
|
||||||
DefaultType.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TypeParam;
|
return Actions.ActOnTypeParameter(CurScope, TypenameKeyword, Ellipsis,
|
||||||
|
EllipsisLoc, KeyLoc, ParamName, NameLoc,
|
||||||
|
Depth, Position, EqualLoc, DefaultArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ParseTemplateTemplateParameter - Handle the parsing of template
|
/// ParseTemplateTemplateParameter - Handle the parsing of template
|
||||||
|
@ -541,28 +538,28 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
|
||||||
TemplateParams.size(),
|
TemplateParams.size(),
|
||||||
RAngleLoc);
|
RAngleLoc);
|
||||||
|
|
||||||
Parser::DeclPtrTy Param
|
// Grab a default argument (if available).
|
||||||
= Actions.ActOnTemplateTemplateParameter(CurScope, TemplateLoc,
|
// Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
|
||||||
ParamList, ParamName,
|
// we introduce the template parameter into the local scope.
|
||||||
NameLoc, Depth, Position);
|
SourceLocation EqualLoc;
|
||||||
|
ParsedTemplateArgument DefaultArg;
|
||||||
// Get the a default value, if given.
|
|
||||||
if (Tok.is(tok::equal)) {
|
if (Tok.is(tok::equal)) {
|
||||||
SourceLocation EqualLoc = ConsumeToken();
|
EqualLoc = ConsumeToken();
|
||||||
ParsedTemplateArgument Default = ParseTemplateTemplateArgument();
|
DefaultArg = ParseTemplateTemplateArgument();
|
||||||
if (Default.isInvalid()) {
|
if (DefaultArg.isInvalid()) {
|
||||||
Diag(Tok.getLocation(),
|
Diag(Tok.getLocation(),
|
||||||
diag::err_default_template_template_parameter_not_template);
|
diag::err_default_template_template_parameter_not_template);
|
||||||
static const tok::TokenKind EndToks[] = {
|
static const tok::TokenKind EndToks[] = {
|
||||||
tok::comma, tok::greater, tok::greatergreater
|
tok::comma, tok::greater, tok::greatergreater
|
||||||
};
|
};
|
||||||
SkipUntil(EndToks, 3, true, true);
|
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
|
/// ParseNonTypeTemplateParameter - Handle the parsing of non-type
|
||||||
|
@ -571,13 +568,6 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
|
||||||
/// template-parameter:
|
/// template-parameter:
|
||||||
/// ...
|
/// ...
|
||||||
/// parameter-declaration
|
/// 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::DeclPtrTy
|
||||||
Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
|
Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
|
||||||
SourceLocation StartLoc = Tok.getLocation();
|
SourceLocation StartLoc = Tok.getLocation();
|
||||||
|
@ -601,13 +591,13 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
|
||||||
return DeclPtrTy();
|
return DeclPtrTy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the parameter.
|
|
||||||
DeclPtrTy Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl,
|
|
||||||
Depth, Position);
|
|
||||||
|
|
||||||
// If there is a default value, parse it.
|
// 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)) {
|
if (Tok.is(tok::equal)) {
|
||||||
SourceLocation EqualLoc = ConsumeToken();
|
EqualLoc = ConsumeToken();
|
||||||
|
|
||||||
// C++ [temp.param]p15:
|
// C++ [temp.param]p15:
|
||||||
// When parsing a default template-argument for a non-type
|
// When parsing a default template-argument for a non-type
|
||||||
|
@ -616,15 +606,15 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
|
||||||
// operator.
|
// operator.
|
||||||
GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
|
GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
|
||||||
|
|
||||||
OwningExprResult DefaultArg = ParseAssignmentExpression();
|
DefaultArg = ParseAssignmentExpression();
|
||||||
if (DefaultArg.isInvalid())
|
if (DefaultArg.isInvalid())
|
||||||
SkipUntil(tok::comma, tok::greater, true, true);
|
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
|
/// \brief Parses a template-id that after the template name has
|
||||||
|
|
|
@ -2861,29 +2861,25 @@ public:
|
||||||
SourceLocation KeyLoc,
|
SourceLocation KeyLoc,
|
||||||
IdentifierInfo *ParamName,
|
IdentifierInfo *ParamName,
|
||||||
SourceLocation ParamNameLoc,
|
SourceLocation ParamNameLoc,
|
||||||
unsigned Depth, unsigned Position);
|
unsigned Depth, unsigned Position,
|
||||||
virtual void ActOnTypeParameterDefault(DeclPtrTy TypeParam,
|
SourceLocation EqualLoc,
|
||||||
SourceLocation EqualLoc,
|
TypeTy *DefaultArg);
|
||||||
SourceLocation DefaultLoc,
|
|
||||||
TypeTy *Default);
|
|
||||||
|
|
||||||
QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
|
QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
|
||||||
virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
|
virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
|
||||||
unsigned Depth,
|
unsigned Depth,
|
||||||
unsigned Position);
|
unsigned Position,
|
||||||
virtual void ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParam,
|
SourceLocation EqualLoc,
|
||||||
SourceLocation EqualLoc,
|
ExprArg DefaultArg);
|
||||||
ExprArg Default);
|
|
||||||
virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S,
|
virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S,
|
||||||
SourceLocation TmpLoc,
|
SourceLocation TmpLoc,
|
||||||
TemplateParamsTy *Params,
|
TemplateParamsTy *Params,
|
||||||
IdentifierInfo *ParamName,
|
IdentifierInfo *ParamName,
|
||||||
SourceLocation ParamNameLoc,
|
SourceLocation ParamNameLoc,
|
||||||
unsigned Depth,
|
unsigned Depth,
|
||||||
unsigned Position);
|
unsigned Position,
|
||||||
virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
|
SourceLocation EqualLoc,
|
||||||
SourceLocation EqualLoc,
|
const ParsedTemplateArgument &DefaultArg);
|
||||||
const ParsedTemplateArgument &Default);
|
|
||||||
|
|
||||||
virtual TemplateParamsTy *
|
virtual TemplateParamsTy *
|
||||||
ActOnTemplateParameterList(unsigned Depth,
|
ActOnTemplateParameterList(unsigned Depth,
|
||||||
|
|
|
@ -459,7 +459,9 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
|
||||||
SourceLocation KeyLoc,
|
SourceLocation KeyLoc,
|
||||||
IdentifierInfo *ParamName,
|
IdentifierInfo *ParamName,
|
||||||
SourceLocation ParamNameLoc,
|
SourceLocation ParamNameLoc,
|
||||||
unsigned Depth, unsigned Position) {
|
unsigned Depth, unsigned Position,
|
||||||
|
SourceLocation EqualLoc,
|
||||||
|
TypeTy *DefaultArg) {
|
||||||
assert(S->isTemplateParamScope() &&
|
assert(S->isTemplateParamScope() &&
|
||||||
"Template type parameter not in template parameter scope!");
|
"Template type parameter not in template parameter scope!");
|
||||||
bool Invalid = false;
|
bool Invalid = false;
|
||||||
|
@ -490,44 +492,33 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
|
||||||
IdResolver.AddDecl(Param);
|
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);
|
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
|
/// \brief Check that the type of a non-type template parameter is
|
||||||
/// well-formed.
|
/// well-formed.
|
||||||
///
|
///
|
||||||
|
@ -580,13 +571,11 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
|
||||||
return QualType();
|
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,
|
Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
|
||||||
unsigned Depth,
|
unsigned Depth,
|
||||||
unsigned Position) {
|
unsigned Position,
|
||||||
|
SourceLocation EqualLoc,
|
||||||
|
ExprArg DefaultArg) {
|
||||||
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
|
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
|
||||||
QualType T = TInfo->getType();
|
QualType T = TInfo->getType();
|
||||||
|
|
||||||
|
@ -622,34 +611,21 @@ Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
|
||||||
S->AddDecl(DeclPtrTy::make(Param));
|
S->AddDecl(DeclPtrTy::make(Param));
|
||||||
IdResolver.AddDecl(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);
|
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
|
/// ActOnTemplateTemplateParameter - Called when a C++ template template
|
||||||
/// parameter (e.g. T in template <template <typename> class T> class array)
|
/// parameter (e.g. T in template <template <typename> class T> class array)
|
||||||
/// has been parsed. S is the current scope.
|
/// has been parsed. S is the current scope.
|
||||||
|
@ -659,7 +635,9 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S,
|
||||||
IdentifierInfo *Name,
|
IdentifierInfo *Name,
|
||||||
SourceLocation NameLoc,
|
SourceLocation NameLoc,
|
||||||
unsigned Depth,
|
unsigned Depth,
|
||||||
unsigned Position) {
|
unsigned Position,
|
||||||
|
SourceLocation EqualLoc,
|
||||||
|
const ParsedTemplateArgument &Default) {
|
||||||
assert(S->isTemplateParamScope() &&
|
assert(S->isTemplateParamScope() &&
|
||||||
"Template template parameter not in template parameter scope!");
|
"Template template parameter not in template parameter scope!");
|
||||||
|
|
||||||
|
@ -669,53 +647,33 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S,
|
||||||
TmpLoc, Depth, Position, Name,
|
TmpLoc, Depth, Position, Name,
|
||||||
(TemplateParameterList*)Params);
|
(TemplateParameterList*)Params);
|
||||||
|
|
||||||
// Make sure the parameter is valid.
|
// If the template template parameter has a name, then link the identifier
|
||||||
// FIXME: Decl object is not currently invalidated anywhere so this doesn't
|
// into the scope and lookup mechanisms.
|
||||||
// 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 (Name) {
|
if (Name) {
|
||||||
S->AddDecl(DeclPtrTy::make(Param));
|
S->AddDecl(DeclPtrTy::make(Param));
|
||||||
IdResolver.AddDecl(Param);
|
IdResolver.AddDecl(Param);
|
||||||
}
|
}
|
||||||
|
|
||||||
return DeclPtrTy::make(Param);
|
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
|
||||||
/// \brief Adds a default argument to the given template template
|
// might have dependent types in its template parameters, which we wouldn't
|
||||||
/// parameter.
|
// be able to match now.
|
||||||
void Sema::ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParamD,
|
//
|
||||||
SourceLocation EqualLoc,
|
// If none of the template template parameter's template arguments mention
|
||||||
const ParsedTemplateArgument &Default) {
|
// other template parameters, we could actually perform more checking here.
|
||||||
TemplateTemplateParmDecl *TemplateParm
|
// However, it isn't worth doing.
|
||||||
= cast<TemplateTemplateParmDecl>(TemplateParamD.getAs<Decl>());
|
TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default);
|
||||||
|
if (DefaultArg.getArgument().getAsTemplate().isNull()) {
|
||||||
// C++ [temp.param]p14:
|
Diag(DefaultArg.getLocation(), diag::err_template_arg_not_class_template)
|
||||||
// A template-parameter shall not be used in its own default argument.
|
<< DefaultArg.getSourceRange();
|
||||||
// FIXME: Implement this check! Needs a recursive walk over the types.
|
return DeclPtrTy::make(Param);
|
||||||
|
}
|
||||||
// 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
|
Param->setDefaultArgument(DefaultArg, false);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TemplateParm->setDefaultArgument(DefaultArg, false);
|
return DeclPtrTy::make(Param);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ActOnTemplateParameterList - Builds a TemplateParameterList that
|
/// ActOnTemplateParameterList - Builds a TemplateParameterList that
|
||||||
|
|
Loading…
Reference in New Issue