summaryrefslogtreecommitdiffstats
path: root/clang/include/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang/include/clang')
-rw-r--r--clang/include/clang/AST/DeclTemplate.h17
-rw-r--r--clang/include/clang/AST/TemplateBase.h100
-rw-r--r--clang/include/clang/AST/TypeLoc.h4
-rw-r--r--clang/include/clang/Basic/DiagnosticParseKinds.td4
-rw-r--r--clang/include/clang/Parse/Action.h2
-rw-r--r--clang/include/clang/Parse/Parser.h1
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,
OpenPOWER on IntegriCloud