diff options
Diffstat (limited to 'clang/include/clang')
-rw-r--r-- | clang/include/clang/AST/DeclTemplate.h | 17 | ||||
-rw-r--r-- | clang/include/clang/AST/TemplateBase.h | 100 | ||||
-rw-r--r-- | clang/include/clang/AST/TypeLoc.h | 4 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticParseKinds.td | 4 | ||||
-rw-r--r-- | clang/include/clang/Parse/Action.h | 2 | ||||
-rw-r--r-- | clang/include/clang/Parse/Parser.h | 1 |
6 files changed, 107 insertions, 21 deletions
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index f1a27933a1b..14f666005cd 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -699,13 +699,13 @@ class TemplateTemplateParmDecl : public TemplateDecl, protected TemplateParmPosition { /// \brief The default template argument, if any. - Expr *DefaultArgument; + TemplateArgumentLoc DefaultArgument; TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, TemplateParameterList *Params) : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), - TemplateParmPosition(D, P), DefaultArgument(0) + TemplateParmPosition(D, P), DefaultArgument() { } public: @@ -720,16 +720,17 @@ public: /// \brief Determine whether this template parameter has a default /// argument. - bool hasDefaultArgument() const { return DefaultArgument; } + bool hasDefaultArgument() const { + return !DefaultArgument.getArgument().isNull(); + } /// \brief Retrieve the default argument, if any. - Expr *getDefaultArgument() const { return DefaultArgument; } - - /// \brief Retrieve the location of the default argument, if any. - SourceLocation getDefaultArgumentLoc() const; + const TemplateArgumentLoc &getDefaultArgument() const { + return DefaultArgument; + } /// \brief Set the default argument for this template parameter. - void setDefaultArgument(Expr *DefArg) { + void setDefaultArgument(const TemplateArgumentLoc &DefArg) { DefaultArgument = DefArg; } diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h index bb14c62d777..6db095872b0 100644 --- a/clang/include/clang/AST/TemplateBase.h +++ b/clang/include/clang/AST/TemplateBase.h @@ -18,6 +18,7 @@ #include "llvm/ADT/APSInt.h" #include "llvm/Support/ErrorHandling.h" #include "clang/AST/Type.h" +#include "clang/AST/TemplateName.h" namespace llvm { class FoldingSetNodeID; @@ -48,21 +49,27 @@ class TemplateArgument { public: /// \brief The type of template argument we're storing. enum ArgKind { + /// \brief Represents an empty template argument, e.g., one that has not + /// been deduced. Null = 0, /// The template argument is a type. Its value is stored in the /// TypeOrValue field. - Type = 1, - /// The template argument is a declaration - Declaration = 2, - /// The template argument is an integral value stored in an llvm::APSInt. - Integral = 3, + Type, + /// The template argument is a declaration that was provided for a pointer + /// or reference non-type template parameter. + Declaration, + /// The template argument is an integral value stored in an llvm::APSInt + /// that was provided for an integral non-type template parameter. + Integral, + /// The template argument is a template name that was provided for a + /// template template parameter. + Template, /// The template argument is a value- or type-dependent expression /// stored in an Expr*. - Expression = 4, - + Expression, /// The template argument is actually a parameter pack. Arguments are stored /// in the Args struct. - Pack = 5 + Pack } Kind; /// \brief Construct an empty, invalid template argument. @@ -82,12 +89,21 @@ public: } /// \brief Construct an integral constant template argument. - TemplateArgument(const llvm::APSInt &Value, QualType Type) - : Kind(Integral) { + TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) { new (Integer.Value) llvm::APSInt(Value); Integer.Type = Type.getAsOpaquePtr(); } + /// \brief Construct a template argument that is a template. + /// + /// This form of template argument is generally used for template template + /// parameters. However, the template name could be a dependent template + /// name that ends up being instantiated to a function template whose address + /// is taken. + TemplateArgument(TemplateName Name) : Kind(Template) { + TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer()); + } + /// \brief Construct a template argument that is an expression. /// /// This form of template argument only occurs in template argument @@ -172,6 +188,15 @@ public: return reinterpret_cast<Decl *>(TypeOrValue); } + /// \brief Retrieve the template argument as a template name. + TemplateName getAsTemplate() const { + if (Kind != Template) + return TemplateName(); + + return TemplateName::getFromVoidPointer( + reinterpret_cast<void *> (TypeOrValue)); + } + /// \brief Retrieve the template argument as an integral value. llvm::APSInt *getAsIntegral() { if (Kind != Integral) @@ -242,13 +267,18 @@ private: union { Expr *Expression; DeclaratorInfo *Declarator; + struct { + unsigned QualifierRange[2]; + unsigned TemplateNameLoc; + } Template; }; #ifndef NDEBUG enum Kind { K_None, K_DeclaratorInfo, - K_Expression + K_Expression, + K_Template } Kind; #endif @@ -273,6 +303,17 @@ public: , Kind(K_Expression) #endif {} + + TemplateArgumentLocInfo(SourceRange QualifierRange, + SourceLocation TemplateNameLoc) +#ifndef NDEBUG + : Kind(K_Template) +#endif + { + Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding(); + Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding(); + Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); + } DeclaratorInfo *getAsDeclaratorInfo() const { assert(Kind == K_DeclaratorInfo); @@ -284,6 +325,18 @@ public: return Expression; } + SourceRange getTemplateQualifierRange() const { + assert(Kind == K_Template); + return SourceRange( + SourceLocation::getFromRawEncoding(Template.QualifierRange[0]), + SourceLocation::getFromRawEncoding(Template.QualifierRange[1])); + } + + SourceLocation getTemplateNameLoc() const { + assert(Kind == K_Template); + return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); + } + #ifndef NDEBUG void validateForArgument(const TemplateArgument &Arg) { switch (Arg.getKind()) { @@ -294,6 +347,9 @@ public: case TemplateArgument::Declaration: assert(Kind == K_Expression); break; + case TemplateArgument::Template: + assert(Kind == K_Template); + break; case TemplateArgument::Integral: case TemplateArgument::Pack: assert(Kind == K_None); @@ -329,8 +385,18 @@ public: assert(Argument.getKind() == TemplateArgument::Expression); } - /// \brief - Fetches the start location of the argument. + TemplateArgumentLoc(const TemplateArgument &Argument, + SourceRange QualifierRange, + SourceLocation TemplateNameLoc) + : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) { + assert(Argument.getKind() == TemplateArgument::Template); + } + + /// \brief - Fetches the primary location of the argument. SourceLocation getLocation() const { + if (Argument.getKind() == TemplateArgument::Template) + return getTemplateNameLoc(); + return getSourceRange().getBegin(); } @@ -359,6 +425,16 @@ public: assert(Argument.getKind() == TemplateArgument::Declaration); return LocInfo.getAsExpr(); } + + SourceRange getTemplateQualifierRange() const { + assert(Argument.getKind() == TemplateArgument::Template); + return LocInfo.getTemplateQualifierRange(); + } + + SourceLocation getTemplateNameLoc() const { + assert(Argument.getKind() == TemplateArgument::Template); + return LocInfo.getTemplateNameLoc(); + } }; } diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index da7857822e9..a06b9b82d0d 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -919,6 +919,10 @@ public: Info = TemplateArgumentLocInfo((DeclaratorInfo*) 0); break; + case TemplateArgument::Template: + Info = TemplateArgumentLocInfo(SourceRange(), SourceLocation()); + break; + case TemplateArgument::Integral: case TemplateArgument::Pack: case TemplateArgument::Null: diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 036d887865d..28c46cd2d70 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -289,6 +289,10 @@ def err_explicit_spec_non_template : Error< def err_variadic_templates : Error< "variadic templates are only allowed in C++0x">; +def err_default_template_template_parameter_not_template : Error< + "default template argument for a template template parameter must be a class " + "template">; + // C++ declarations def err_friend_decl_defines_class : Error< "cannot define a type in a friend declaration">; diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index 4886970c741..ceeb9c40e54 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -1577,7 +1577,7 @@ public: /// parameter. virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam, SourceLocation EqualLoc, - ExprArg Default) { + const ParsedTemplateArgument &Default) { } /// ActOnTemplateParameterList - Called when a complete template diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index dd939a98bf7..548d7468598 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1371,6 +1371,7 @@ private: bool AllowTypeAnnotation = true); void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0); bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs); + ParsedTemplateArgument ParseTemplateTemplateArgument(); ParsedTemplateArgument ParseTemplateArgument(); DeclPtrTy ParseExplicitInstantiation(SourceLocation ExternLoc, SourceLocation TemplateLoc, |