Improve parsing of template arguments to lay the foundation for

handling template template parameters properly. This refactoring:

  - Parses template template arguments as id-expressions, representing
    the result of the parse as a template name (Action::TemplateTy)
    rather than as an expression (lame!).

  - Represents all parsed template arguments via a new parser-specific
    type, ParsedTemplateArgument, which stores the kind of template
    argument (type, non-type, template) along with all of the source
    information about the template argument. This replaces an ad hoc
    set of 3 vectors (one for a void*, which was either a type or an
    expression; one for a bit telling whether the first was a type or
    an expression; and one for a single source location pointing at
    the template argument).

  - Moves TemplateIdAnnotation into the new Parse/Template.h. It never
    belonged in the Basic library anyway.

llvm-svn: 86708
This commit is contained in:
Douglas Gregor 2009-11-10 19:49:08 +00:00
parent e034867587
commit b53edfb8dc
17 changed files with 359 additions and 200 deletions

View File

@ -248,69 +248,6 @@ struct PPConditionalInfo {
bool FoundElse;
};
/// TemplateIdAnnotation - Information about a template-id annotation
/// token, which contains the template declaration, template
/// arguments, whether those template arguments were types or
/// expressions, and the source locations for important tokens. All of
/// the information about template arguments is allocated directly
/// after this structure.
struct TemplateIdAnnotation {
/// TemplateNameLoc - The location of the template name within the
/// source.
SourceLocation TemplateNameLoc;
/// FIXME: Temporarily stores the name of a specialization
IdentifierInfo *Name;
/// FIXME: Temporarily stores the overloaded operator kind.
OverloadedOperatorKind Operator;
/// The declaration of the template corresponding to the
/// template-name. This is an Action::DeclTy*.
void *Template;
/// The kind of template that Template refers to.
TemplateNameKind Kind;
/// The location of the '<' before the template argument
/// list.
SourceLocation LAngleLoc;
/// The location of the '>' after the template argument
/// list.
SourceLocation RAngleLoc;
/// NumArgs - The number of template arguments.
unsigned NumArgs;
/// \brief Retrieves a pointer to the template arguments
void **getTemplateArgs() { return (void **)(this + 1); }
/// \brief Retrieves a pointer to the array of template argument
/// locations.
SourceLocation *getTemplateArgLocations() {
return (SourceLocation *)(getTemplateArgs() + NumArgs);
}
/// \brief Retrieves a pointer to the array of flags that states
/// whether the template arguments are types.
bool *getTemplateArgIsType() {
return (bool *)(getTemplateArgLocations() + NumArgs);
}
static TemplateIdAnnotation* Allocate(unsigned NumArgs) {
TemplateIdAnnotation *TemplateId
= (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
sizeof(void*) * NumArgs +
sizeof(SourceLocation) * NumArgs +
sizeof(bool) * NumArgs);
TemplateId->NumArgs = NumArgs;
return TemplateId;
}
void Destroy() { free(this); }
};
} // end namespace clang
#endif

View File

@ -1632,7 +1632,6 @@ public:
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc) {
return TypeResult();
};
@ -1737,7 +1736,6 @@ public:
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc,
AttributeList *Attr,
MultiTemplateParamsArg TemplateParameterLists) {
@ -1817,7 +1815,6 @@ public:
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc,
AttributeList *Attr) {
return DeclResult();

View File

@ -25,7 +25,8 @@ namespace clang {
class IdentifierInfo;
class Preprocessor;
class Declarator;
struct TemplateIdAnnotation;
/// DeclSpec - This class captures information about "declaration specifiers",
/// which encompasses storage-class-specifiers, type-specifiers,
/// type-qualifiers, and function-specifiers.
@ -642,13 +643,7 @@ public:
/// \param TemplateId the template-id annotation that describes the parsed
/// template-id. This UnqualifiedId instance will take ownership of the
/// \p TemplateId and will free it on destruction.
void setTemplateId(TemplateIdAnnotation *TemplateId) {
assert(TemplateId && "NULL template-id annotation?");
Kind = IK_TemplateId;
this->TemplateId = TemplateId;
StartLocation = TemplateId->TemplateNameLoc;
EndLocation = TemplateId->RAngleLoc;
}
void setTemplateId(TemplateIdAnnotation *TemplateId);
/// \brief Return the source range that covers this unqualified-id.
SourceRange getSourceRange() const {

View File

@ -654,41 +654,33 @@ namespace clang {
#endif
};
class ParsedTemplateArgument;
class ASTTemplateArgsPtr {
#if !defined(DISABLE_SMART_POINTERS)
ActionBase &Actions;
#endif
void **Args;
bool *ArgIsType;
ParsedTemplateArgument *Args;
mutable unsigned Count;
#if !defined(DISABLE_SMART_POINTERS)
void destroy() {
if (!Count)
return;
for (unsigned i = 0; i != Count; ++i)
if (Args[i] && !ArgIsType[i])
Actions.DeleteExpr((ActionBase::ExprTy *)Args[i]);
Count = 0;
}
void destroy();
#endif
public:
ASTTemplateArgsPtr(ActionBase &actions, void **args, bool *argIsType,
ASTTemplateArgsPtr(ActionBase &actions, ParsedTemplateArgument *args,
unsigned count) :
#if !defined(DISABLE_SMART_POINTERS)
Actions(actions),
#endif
Args(args), ArgIsType(argIsType), Count(count) { }
Args(args), Count(count) { }
// FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) :
#if !defined(DISABLE_SMART_POINTERS)
Actions(Other.Actions),
#endif
Args(Other.Args), ArgIsType(Other.ArgIsType), Count(Other.Count) {
Args(Other.Args), Count(Other.Count) {
#if !defined(DISABLE_SMART_POINTERS)
Other.Count = 0;
#endif
@ -700,7 +692,6 @@ namespace clang {
Actions = Other.Actions;
#endif
Args = Other.Args;
ArgIsType = Other.ArgIsType;
Count = Other.Count;
#if !defined(DISABLE_SMART_POINTERS)
Other.Count = 0;
@ -712,22 +703,20 @@ namespace clang {
~ASTTemplateArgsPtr() { destroy(); }
#endif
void **getArgs() const { return Args; }
bool *getArgIsType() const {return ArgIsType; }
ParsedTemplateArgument *getArgs() const { return Args; }
unsigned size() const { return Count; }
void reset(void **args, bool *argIsType, unsigned count) {
void reset(ParsedTemplateArgument *args, unsigned count) {
#if !defined(DISABLE_SMART_POINTERS)
destroy();
#endif
Args = args;
ArgIsType = argIsType;
Count = count;
}
void *operator[](unsigned Arg) const { return Args[Arg]; }
const ParsedTemplateArgument &operator[](unsigned Arg) const;
void **release() const {
ParsedTemplateArgument *release() const {
#if !defined(DISABLE_SMART_POINTERS)
Count = 0;
#endif

View File

@ -331,7 +331,7 @@ private:
/// either "commit the consumed tokens" or revert to the previously marked
/// token position. Example:
///
/// TentativeParsingAction TPA;
/// TentativeParsingAction TPA(*this);
/// ConsumeToken();
/// ....
/// TPA.Revert();
@ -1347,9 +1347,7 @@ private:
DeclPtrTy ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
DeclPtrTy ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
// C++ 14.3: Template arguments [temp.arg]
typedef llvm::SmallVector<void *, 16> TemplateArgList;
typedef llvm::SmallVector<bool, 16> TemplateArgIsTypeList;
typedef llvm::SmallVector<SourceLocation, 16> TemplateArgLocationList;
typedef llvm::SmallVector<ParsedTemplateArgument, 16> TemplateArgList;
bool ParseTemplateIdAfterTemplateName(TemplateTy Template,
SourceLocation TemplateNameLoc,
@ -1357,8 +1355,6 @@ private:
bool ConsumeLastToken,
SourceLocation &LAngleLoc,
TemplateArgList &TemplateArgs,
TemplateArgIsTypeList &TemplateArgIsType,
TemplateArgLocationList &TemplateArgLocations,
SourceLocation &RAngleLoc);
bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
@ -1367,10 +1363,8 @@ private:
SourceLocation TemplateKWLoc = SourceLocation(),
bool AllowTypeAnnotation = true);
void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0);
bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
TemplateArgIsTypeList &TemplateArgIsType,
TemplateArgLocationList &TemplateArgLocations);
void *ParseTemplateArgument(bool &ArgIsType);
bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
ParsedTemplateArgument ParseTemplateArgument();
DeclPtrTy ParseExplicitInstantiation(SourceLocation ExternLoc,
SourceLocation TemplateLoc,
SourceLocation &DeclEnd);

View File

@ -0,0 +1,183 @@
//===--- Template.h - Template Parsing Data Types -------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides data structures that store the parsed representation of
// templates.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_PARSE_TEMPLATE_H
#define LLVM_CLANG_PARSE_TEMPLATE_H
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Ownership.h"
#include <cassert>
namespace clang {
/// \brief Represents the parsed form of a C++ template argument.
class ParsedTemplateArgument {
public:
/// \brief Describes the kind of template argument that was parsed.
enum KindType {
/// \brief A template type parameter, stored as a type.
Type,
/// \brief A non-type template parameter, stored as an expression.
NonType,
/// \brief A template template argument, stored as a template name.
Template
};
/// \brief Build an empty template argument. This template argument
ParsedTemplateArgument() : Kind(Type), Arg(0) { }
/// \brief Create a template type argument or non-type template argument.
///
/// \param Arg the template type argument or non-type template argument.
/// \param Loc the location of the type.
ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc)
: Kind(Kind), Arg(Arg), Loc(Loc) { }
/// \brief Create a template template argument.
///
/// \param SS the C++ scope specifier that precedes the template name, if
/// any.
///
/// \param Template the template to which this template template
/// argument refers.
///
/// \param TemplateLoc the location of the template name.
ParsedTemplateArgument(const CXXScopeSpec &SS,
ActionBase::TemplateTy Template,
SourceLocation TemplateLoc)
: Kind(ParsedTemplateArgument::Template), Arg(Template.get()),
Loc(TemplateLoc), SS(SS) { }
/// \brief Determine whether the given template argument is invalid.
bool isInvalid() { return Arg == 0; }
/// \brief Determine what kind of template argument we have.
KindType getKind() const { return Kind; }
/// \brief Retrieve the template type argument's type.
ActionBase::TypeTy *getAsType() const {
assert(Kind == Type && "Not a template type argument");
return Arg;
}
/// \brief Retrieve the non-type template argument's expression.
ActionBase::ExprTy *getAsExpr() const {
assert(Kind == NonType && "Not a non-type template argument");
return Arg;
}
/// \brief Retrieve the template template argument's template name.
ActionBase::TemplateTy getAsTemplate() const {
assert(Kind == Template && "Not a template template argument");
return ActionBase::TemplateTy::make(Arg);
}
/// \brief Retrieve the location of the template argument.
SourceLocation getLocation() const { return Loc; }
/// \brief Retrieve the nested-name-specifier that precedes the template
/// name in a template template argument.
const CXXScopeSpec &getScopeSpec() const {
assert(Kind == Template &&
"Only template template arguments can have a scope specifier");
return SS;
}
private:
KindType Kind;
/// \brief The actual template argument representation, which may be
/// an \c ActionBase::TypeTy* (for a type), an ActionBase::ExprTy* (for an
/// expression), or an ActionBase::TemplateTy (for a template).
void *Arg;
/// \brief the location of the template argument.
SourceLocation Loc;
/// \brief The nested-name-specifier that can accompany a template template
/// argument.
CXXScopeSpec SS;
};
/// \brief Information about a template-id annotation
/// token.
///
/// A template-id annotation token contains the template declaration,
/// template arguments, whether those template arguments were types,
/// expressions, or template names, and the source locations for important
/// tokens. All of the information about template arguments is allocated
/// directly after this structure.
struct TemplateIdAnnotation {
/// TemplateNameLoc - The location of the template name within the
/// source.
SourceLocation TemplateNameLoc;
/// FIXME: Temporarily stores the name of a specialization
IdentifierInfo *Name;
/// FIXME: Temporarily stores the overloaded operator kind.
OverloadedOperatorKind Operator;
/// The declaration of the template corresponding to the
/// template-name. This is an Action::TemplateTy.
void *Template;
/// The kind of template that Template refers to.
TemplateNameKind Kind;
/// The location of the '<' before the template argument
/// list.
SourceLocation LAngleLoc;
/// The location of the '>' after the template argument
/// list.
SourceLocation RAngleLoc;
/// NumArgs - The number of template arguments.
unsigned NumArgs;
/// \brief Retrieves a pointer to the template arguments
ParsedTemplateArgument *getTemplateArgs() {
return reinterpret_cast<ParsedTemplateArgument *>(this + 1);
}
static TemplateIdAnnotation* Allocate(unsigned NumArgs) {
TemplateIdAnnotation *TemplateId
= (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
sizeof(ParsedTemplateArgument) * NumArgs);
TemplateId->NumArgs = NumArgs;
return TemplateId;
}
void Destroy() { free(this); }
};
#if !defined(DISABLE_SMART_POINTERS)
inline void ASTTemplateArgsPtr::destroy() {
if (!Count)
return;
for (unsigned I = 0; I != Count; ++I)
if (Args[I].getKind() == ParsedTemplateArgument::NonType)
Actions.DeleteExpr(Args[I].getAsExpr());
Count = 0;
}
#endif
inline const ParsedTemplateArgument &
ASTTemplateArgsPtr::operator[](unsigned Arg) const {
return Args[Arg];
}
}
#endif

View File

@ -13,6 +13,7 @@
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Template.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/STLExtras.h"
@ -26,6 +27,15 @@ static DiagnosticBuilder Diag(Diagnostic &D, SourceLocation Loc,
return D.Report(FullSourceLoc(Loc, SrcMgr), DiagID);
}
void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
assert(TemplateId && "NULL template-id annotation?");
Kind = IK_TemplateId;
this->TemplateId = TemplateId;
StartLocation = TemplateId->TemplateNameLoc;
EndLocation = TemplateId->RAngleLoc;
}
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
/// "TheDeclarator" is the declarator that this will be added to.
DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,

View File

@ -14,6 +14,7 @@
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Scope.h"
#include "clang/Parse/Template.h"
#include "ExtensionRAIIObject.h"
#include "llvm/ADT/SmallSet.h"
using namespace clang;

View File

@ -16,6 +16,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
#include "clang/Parse/Template.h"
#include "ExtensionRAIIObject.h"
using namespace clang;
@ -586,13 +587,10 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// Eat the template argument list and try to continue parsing this as
// a class (or template thereof).
TemplateArgList TemplateArgs;
TemplateArgIsTypeList TemplateArgIsType;
TemplateArgLocationList TemplateArgLocations;
SourceLocation LAngleLoc, RAngleLoc;
if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, &SS,
true, LAngleLoc,
TemplateArgs, TemplateArgIsType,
TemplateArgLocations, RAngleLoc)) {
TemplateArgs, RAngleLoc)) {
// We couldn't parse the template argument list at all, so don't
// try to give any location information for the list.
LAngleLoc = RAngleLoc = SourceLocation();
@ -704,7 +702,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// or explicit instantiation.
ASTTemplateArgsPtr TemplateArgsPtr(Actions,
TemplateId->getTemplateArgs(),
TemplateId->getTemplateArgIsType(),
TemplateId->NumArgs);
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
TUK == Action::TUK_Declaration) {
@ -720,7 +717,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
TemplateId->getTemplateArgLocations(),
TemplateId->RAngleLoc,
Attr);
} else if (TUK == Action::TUK_Reference) {
@ -729,7 +725,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
TemplateId->getTemplateArgLocations(),
TemplateId->RAngleLoc);
TypeResult = Actions.ActOnTagTemplateIdType(TypeResult, TUK,
@ -777,7 +772,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
TemplateId->getTemplateArgLocations(),
TemplateId->RAngleLoc,
Attr,
Action::MultiTemplateParamsArg(Actions,

View File

@ -14,6 +14,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Template.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
@ -814,13 +815,9 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
// Parse the enclosed template argument list.
SourceLocation LAngleLoc, RAngleLoc;
TemplateArgList TemplateArgs;
TemplateArgIsTypeList TemplateArgIsType;
TemplateArgLocationList TemplateArgLocations;
if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation,
&SS, true, LAngleLoc,
TemplateArgs,
TemplateArgIsType,
TemplateArgLocations,
RAngleLoc))
return true;
@ -845,15 +842,10 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
TemplateId->Kind = TNK;
TemplateId->LAngleLoc = LAngleLoc;
TemplateId->RAngleLoc = RAngleLoc;
void **Args = TemplateId->getTemplateArgs();
bool *ArgIsType = TemplateId->getTemplateArgIsType();
SourceLocation *ArgLocs = TemplateId->getTemplateArgLocations();
ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
for (unsigned Arg = 0, ArgEnd = TemplateArgs.size();
Arg != ArgEnd; ++Arg) {
Arg != ArgEnd; ++Arg)
Args[Arg] = TemplateArgs[Arg];
ArgIsType[Arg] = TemplateArgIsType[Arg];
ArgLocs[Arg] = TemplateArgLocations[Arg];
}
Id.setTemplateId(TemplateId);
return false;
@ -861,14 +853,12 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
// Bundle the template arguments together.
ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
TemplateArgIsType.data(),
TemplateArgs.size());
// Constructor and destructor names.
Action::TypeResult Type
= Actions.ActOnTemplateIdType(Template, NameLoc,
LAngleLoc, TemplateArgsPtr,
&TemplateArgLocations[0],
RAngleLoc);
if (Type.isInvalid())
return true;

View File

@ -15,6 +15,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
#include "clang/Parse/Template.h"
#include "llvm/Support/Compiler.h"
using namespace clang;
@ -582,8 +583,6 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
bool ConsumeLastToken,
SourceLocation &LAngleLoc,
TemplateArgList &TemplateArgs,
TemplateArgIsTypeList &TemplateArgIsType,
TemplateArgLocationList &TemplateArgLocations,
SourceLocation &RAngleLoc) {
assert(Tok.is(tok::less) && "Must have already parsed the template-name");
@ -595,8 +594,7 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
{
GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
if (Tok.isNot(tok::greater))
Invalid = ParseTemplateArgumentList(TemplateArgs, TemplateArgIsType,
TemplateArgLocations);
Invalid = ParseTemplateArgumentList(TemplateArgs);
if (Invalid) {
// Try to find the closing '>'.
@ -688,14 +686,10 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
// Parse the enclosed template argument list.
SourceLocation LAngleLoc, RAngleLoc;
TemplateArgList TemplateArgs;
TemplateArgIsTypeList TemplateArgIsType;
TemplateArgLocationList TemplateArgLocations;
bool Invalid = ParseTemplateIdAfterTemplateName(Template,
TemplateNameLoc,
SS, false, LAngleLoc,
TemplateArgs,
TemplateArgIsType,
TemplateArgLocations,
RAngleLoc);
if (Invalid) {
@ -707,7 +701,6 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
}
ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
TemplateArgIsType.data(),
TemplateArgs.size());
// Build the annotation token.
@ -715,7 +708,6 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
Action::TypeResult Type
= Actions.ActOnTemplateIdType(Template, TemplateNameLoc,
LAngleLoc, TemplateArgsPtr,
&TemplateArgLocations[0],
RAngleLoc);
if (Type.isInvalid()) {
// If we failed to parse the template ID but skipped ahead to a >, we're not
@ -751,14 +743,9 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
TemplateId->Kind = TNK;
TemplateId->LAngleLoc = LAngleLoc;
TemplateId->RAngleLoc = RAngleLoc;
void **Args = TemplateId->getTemplateArgs();
bool *ArgIsType = TemplateId->getTemplateArgIsType();
SourceLocation *ArgLocs = TemplateId->getTemplateArgLocations();
for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg) {
ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
Args[Arg] = TemplateArgs[Arg];
ArgIsType[Arg] = TemplateArgIsType[Arg];
ArgLocs[Arg] = TemplateArgLocations[Arg];
}
Tok.setAnnotationValue(TemplateId);
if (TemplateKWLoc.isValid())
Tok.setLocation(TemplateKWLoc);
@ -794,7 +781,6 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
ASTTemplateArgsPtr TemplateArgsPtr(Actions,
TemplateId->getTemplateArgs(),
TemplateId->getTemplateArgIsType(),
TemplateId->NumArgs);
Action::TypeResult Type
@ -802,7 +788,6 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
TemplateId->getTemplateArgLocations(),
TemplateId->RAngleLoc);
// Create the new "type" annotation token.
Tok.setKind(tok::annot_typename);
@ -817,33 +802,112 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
TemplateId->Destroy();
}
/// \brief Determine whether the given token can end a template argument.
static const bool isEndOfTemplateArgument(Token Tok) {
return Tok.is(tok::comma) || Tok.is(tok::greater) ||
Tok.is(tok::greatergreater);
}
/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
///
/// template-argument: [C++ 14.2]
/// constant-expression
/// type-id
/// id-expression
void *Parser::ParseTemplateArgument(bool &ArgIsType) {
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.
// Therefore, we initially try to parse a type-id.
if (isCXXTypeId(TypeIdAsTemplateArgument)) {
ArgIsType = true;
SourceLocation Loc = Tok.getLocation();
TypeResult TypeArg = ParseTypeName();
if (TypeArg.isInvalid())
return 0;
return TypeArg.get();
return ParsedTemplateArgument();
return ParsedTemplateArgument(ParsedTemplateArgument::Type, TypeArg.get(),
Loc);
}
// 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:
//
// nested-name-specifier[opt] template[opt] identifier
//
// 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;
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();
}
// Parse a non-type template argument.
SourceLocation Loc = Tok.getLocation();
OwningExprResult ExprArg = ParseConstantExpression();
if (ExprArg.isInvalid() || !ExprArg.get())
return 0;
return ParsedTemplateArgument();
ArgIsType = false;
return ExprArg.release();
return ParsedTemplateArgument(ParsedTemplateArgument::NonType,
ExprArg.release(), Loc);
}
/// ParseTemplateArgumentList - Parse a C++ template-argument-list
@ -853,22 +917,17 @@ void *Parser::ParseTemplateArgument(bool &ArgIsType) {
/// template-argument
/// template-argument-list ',' template-argument
bool
Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
TemplateArgIsTypeList &TemplateArgIsType,
TemplateArgLocationList &TemplateArgLocations) {
Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
while (true) {
bool IsType = false;
SourceLocation Loc = Tok.getLocation();
void *Arg = ParseTemplateArgument(IsType);
if (Arg) {
TemplateArgs.push_back(Arg);
TemplateArgIsType.push_back(IsType);
TemplateArgLocations.push_back(Loc);
} else {
ParsedTemplateArgument Arg = ParseTemplateArgument();
if (Arg.isInvalid()) {
SkipUntil(tok::comma, tok::greater, true, true);
return true;
}
// Save this template argument.
TemplateArgs.push_back(Arg);
// If the next token is a comma, consume it and keep reading
// arguments.
if (Tok.isNot(tok::comma)) break;

View File

@ -15,6 +15,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
#include "clang/Parse/Template.h"
#include "llvm/Support/raw_ostream.h"
#include "ExtensionRAIIObject.h"
#include "ParsePragma.h"

View File

@ -2472,8 +2472,7 @@ public:
AccessSpecifier AS);
void translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
SourceLocation *TemplateArgLocsIn,
llvm::SmallVector<TemplateArgumentLoc, 16> &TempArgs);
llvm::SmallVectorImpl<TemplateArgumentLoc> &TempArgs);
QualType CheckTemplateIdType(TemplateName Template,
SourceLocation TemplateLoc,
@ -2486,7 +2485,6 @@ public:
ActOnTemplateIdType(TemplateTy Template, SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc);
virtual TypeResult ActOnTagTemplateIdType(TypeResult Type,
@ -2508,7 +2506,6 @@ public:
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc);
virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
@ -2529,7 +2526,6 @@ public:
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc,
AttributeList *Attr,
MultiTemplateParamsArg TemplateParameterLists);
@ -2570,7 +2566,6 @@ public:
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc,
AttributeList *Attr);

View File

@ -24,6 +24,7 @@
#include "clang/AST/StmtObjC.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Template.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@ -1669,7 +1670,7 @@ DeclarationName Sema::GetNameFromUnqualifiedId(UnqualifiedId &Name) {
case UnqualifiedId::IK_TemplateId: {
TemplateName TName
= TemplateName::getFromVoidPointer(Name.TemplateId->Template);
= TemplateName::getFromVoidPointer(Name.TemplateId->Template);
if (TemplateDecl *Template = TName.getAsTemplateDecl())
return Template->getDeclName();
if (OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl())
@ -2835,10 +2836,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
ASTTemplateArgsPtr TemplateArgsPtr(*this,
TemplateId->getTemplateArgs(),
TemplateId->getTemplateArgIsType(),
TemplateId->NumArgs);
translateTemplateArguments(TemplateArgsPtr,
TemplateId->getTemplateArgLocations(),
TemplateArgs);
TemplateArgsPtr.release();

View File

@ -18,9 +18,10 @@
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Template.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/DeclSpec.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
#include <algorithm> // for std::equal

View File

@ -25,6 +25,7 @@
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Designator.h"
#include "clang/Parse/Scope.h"
#include "clang/Parse/Template.h"
using namespace clang;
@ -622,14 +623,12 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
if (Name.getKind() == UnqualifiedId::IK_TemplateId) {
ASTTemplateArgsPtr TemplateArgsPtr(*this,
Name.TemplateId->getTemplateArgs(),
Name.TemplateId->getTemplateArgIsType(),
Name.TemplateId->NumArgs);
return ActOnTemplateIdExpr(SS,
TemplateTy::make(Name.TemplateId->Template),
Name.TemplateId->TemplateNameLoc,
Name.TemplateId->LAngleLoc,
TemplateArgsPtr,
Name.TemplateId->getTemplateArgLocations(),
Name.TemplateId->RAngleLoc);
}
@ -2501,12 +2500,10 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg Base,
// Translate the parser's template argument list in our AST format.
ASTTemplateArgsPtr TemplateArgsPtr(*this,
Member.TemplateId->getTemplateArgs(),
Member.TemplateId->getTemplateArgIsType(),
Member.TemplateId->NumArgs);
llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
translateTemplateArguments(TemplateArgsPtr,
Member.TemplateId->getTemplateArgLocations(),
TemplateArgs);
TemplateArgsPtr.release();

View File

@ -16,6 +16,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Template.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "llvm/Support/Compiler.h"
@ -1121,21 +1122,43 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
/// \brief Translates template arguments as provided by the parser
/// into template arguments used by semantic analysis.
void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
SourceLocation *TemplateArgLocs,
llvm::SmallVector<TemplateArgumentLoc, 16> &TemplateArgs) {
llvm::SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {
TemplateArgs.reserve(TemplateArgsIn.size());
void **Args = TemplateArgsIn.getArgs();
bool *ArgIsType = TemplateArgsIn.getArgIsType();
for (unsigned Arg = 0, Last = TemplateArgsIn.size(); Arg != Last; ++Arg) {
if (ArgIsType[Arg]) {
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(Args[Arg], &DI);
if (!DI) DI = Context.getTrivialDeclaratorInfo(T, TemplateArgLocs[Arg]);
QualType T = Sema::GetTypeFromParser(Arg.getAsType(), &DI);
if (!DI) DI = Context.getTrivialDeclaratorInfo(T, Arg.getLocation());
TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(T), DI));
} else {
Expr *E = reinterpret_cast<Expr *>(Args[Arg]);
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));
}
}
}
}
@ -1228,13 +1251,12 @@ Action::TypeResult
Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
SourceLocation *TemplateArgLocsIn,
SourceLocation RAngleLoc) {
TemplateName Template = TemplateD.getAsVal<TemplateName>();
// Translate the parser's template argument list in our AST format.
llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
translateTemplateArguments(TemplateArgsIn, TemplateArgLocsIn, TemplateArgs);
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
QualType Result = CheckTemplateIdType(Template, TemplateLoc, LAngleLoc,
TemplateArgs.data(),
@ -1336,13 +1358,12 @@ Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
SourceLocation *TemplateArgSLs,
SourceLocation RAngleLoc) {
TemplateName Template = TemplateD.getAsVal<TemplateName>();
// Translate the parser's template argument list in our AST format.
llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
translateTemplateArguments(TemplateArgsIn, TemplateArgSLs, TemplateArgs);
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
TemplateArgsIn.release();
return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(),
@ -2803,7 +2824,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc,
AttributeList *Attr,
MultiTemplateParamsArg TemplateParameterLists) {
@ -2898,7 +2918,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// Translate the parser's template argument list in our AST format.
llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
// Check that the template argument list is well-formed for this
// template.
@ -3704,7 +3724,6 @@ Sema::ActOnExplicitInstantiation(Scope *S,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc,
AttributeList *Attr) {
// Find the class template we're specializing
@ -3743,7 +3762,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// Translate the parser's template argument list in our AST format.
llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
// Check that the template argument list is well-formed for this
// template.
@ -4126,10 +4145,8 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
ASTTemplateArgsPtr TemplateArgsPtr(*this,
TemplateId->getTemplateArgs(),
TemplateId->getTemplateArgIsType(),
TemplateId->NumArgs);
translateTemplateArguments(TemplateArgsPtr,
TemplateId->getTemplateArgLocations(),
TemplateArgs);
HasExplicitTemplateArgs = true;
TemplateArgsPtr.release();