2009-11-04 15:04:32 +00:00
|
|
|
//===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file provides definitions which are common for all kinds of
|
|
|
|
// template representation.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
|
|
|
|
#define LLVM_CLANG_AST_TEMPLATEBASE_H
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
#include "clang/AST/Type.h"
|
|
|
|
#include "clang/AST/TemplateName.h"
|
2009-11-04 15:04:32 +00:00
|
|
|
#include "llvm/ADT/APSInt.h"
|
2009-12-01 11:08:04 +00:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2012-04-14 14:01:31 +00:00
|
|
|
#include "llvm/Support/Compiler.h"
|
2009-11-04 15:04:32 +00:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
class FoldingSetNodeID;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
|
|
|
|
class Decl;
|
2010-05-27 15:17:06 +00:00
|
|
|
class DiagnosticBuilder;
|
2009-11-04 15:04:32 +00:00
|
|
|
class Expr;
|
2011-02-20 13:06:31 +00:00
|
|
|
struct PrintingPolicy;
|
2009-12-15 18:49:47 +00:00
|
|
|
class TypeSourceInfo;
|
2009-11-04 15:04:32 +00:00
|
|
|
|
|
|
|
/// \brief Represents a template argument within a class template
|
|
|
|
/// specialization.
|
|
|
|
class TemplateArgument {
|
|
|
|
public:
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief The kind of template argument we're storing.
|
2009-11-04 15:04:32 +00:00
|
|
|
enum ArgKind {
|
2009-11-18 14:59:57 +00:00
|
|
|
/// \brief Represents an empty template argument, e.g., one that has not
|
|
|
|
/// been deduced.
|
2009-11-04 15:04:32 +00:00
|
|
|
Null = 0,
|
|
|
|
/// The template argument is a type. Its value is stored in the
|
|
|
|
/// TypeOrValue field.
|
2009-11-18 14:59:57 +00:00
|
|
|
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,
|
2011-02-20 13:06:31 +00:00
|
|
|
/// The template argument is a pack expansion of a template name that was
|
|
|
|
/// provided for a template template parameter.
|
|
|
|
TemplateExpansion,
|
2009-11-04 15:04:32 +00:00
|
|
|
/// The template argument is a value- or type-dependent expression
|
|
|
|
/// stored in an Expr*.
|
2009-11-18 14:59:57 +00:00
|
|
|
Expression,
|
2009-11-04 15:04:32 +00:00
|
|
|
/// The template argument is actually a parameter pack. Arguments are stored
|
|
|
|
/// in the Args struct.
|
2009-11-18 14:59:57 +00:00
|
|
|
Pack
|
2011-02-20 13:06:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
|
|
|
/// \brief The kind of template argument we're storing.
|
|
|
|
unsigned Kind;
|
|
|
|
|
|
|
|
union {
|
|
|
|
uintptr_t TypeOrValue;
|
|
|
|
struct {
|
|
|
|
char Value[sizeof(llvm::APSInt)];
|
|
|
|
void *Type;
|
|
|
|
} Integer;
|
|
|
|
struct {
|
|
|
|
const TemplateArgument *Args;
|
|
|
|
unsigned NumArgs;
|
|
|
|
} Args;
|
|
|
|
struct {
|
|
|
|
void *Name;
|
|
|
|
unsigned NumExpansions;
|
|
|
|
} TemplateArg;
|
|
|
|
};
|
2009-11-04 15:04:32 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
TemplateArgument(TemplateName, bool); // DO NOT USE
|
|
|
|
|
|
|
|
public:
|
2009-11-04 15:04:32 +00:00
|
|
|
/// \brief Construct an empty, invalid template argument.
|
2011-02-20 13:06:31 +00:00
|
|
|
TemplateArgument() : Kind(Null), TypeOrValue(0) { }
|
2009-11-04 15:04:32 +00:00
|
|
|
|
|
|
|
/// \brief Construct a template type argument.
|
|
|
|
TemplateArgument(QualType T) : Kind(Type) {
|
|
|
|
TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Construct a template argument that refers to a
|
|
|
|
/// declaration, which is either an external declaration or a
|
|
|
|
/// template declaration.
|
|
|
|
TemplateArgument(Decl *D) : Kind(Declaration) {
|
|
|
|
TypeOrValue = reinterpret_cast<uintptr_t>(D);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Construct an integral constant template argument.
|
2009-11-18 14:59:57 +00:00
|
|
|
TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) {
|
2011-02-20 13:06:31 +00:00
|
|
|
// FIXME: Large integral values will get leaked. Do something
|
|
|
|
// similar to what we did with IntegerLiteral.
|
2009-11-04 15:04:32 +00:00
|
|
|
new (Integer.Value) llvm::APSInt(Value);
|
|
|
|
Integer.Type = Type.getAsOpaquePtr();
|
|
|
|
}
|
|
|
|
|
2009-11-18 14:59:57 +00:00
|
|
|
/// \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.
|
2011-02-20 13:06:31 +00:00
|
|
|
///
|
|
|
|
/// \param Name The template name.
|
|
|
|
TemplateArgument(TemplateName Name) : Kind(Template)
|
|
|
|
{
|
|
|
|
TemplateArg.Name = Name.getAsVoidPointer();
|
|
|
|
TemplateArg.NumExpansions = 0;
|
2009-11-18 14:59:57 +00:00
|
|
|
}
|
2011-02-20 13:06:31 +00:00
|
|
|
|
|
|
|
/// \brief Construct a template argument that is a template pack expansion.
|
|
|
|
///
|
|
|
|
/// 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.
|
|
|
|
///
|
|
|
|
/// \param Name The template name.
|
|
|
|
///
|
|
|
|
/// \param NumExpansions The number of expansions that will be generated by
|
|
|
|
/// instantiating
|
|
|
|
TemplateArgument(TemplateName Name, llvm::Optional<unsigned> NumExpansions)
|
|
|
|
: Kind(TemplateExpansion)
|
|
|
|
{
|
|
|
|
TemplateArg.Name = Name.getAsVoidPointer();
|
|
|
|
if (NumExpansions)
|
|
|
|
TemplateArg.NumExpansions = *NumExpansions + 1;
|
|
|
|
else
|
|
|
|
TemplateArg.NumExpansions = 0;
|
|
|
|
}
|
|
|
|
|
2009-11-04 15:04:32 +00:00
|
|
|
/// \brief Construct a template argument that is an expression.
|
|
|
|
///
|
|
|
|
/// This form of template argument only occurs in template argument
|
|
|
|
/// lists used for dependent types and for expression; it will not
|
|
|
|
/// occur in a non-dependent, canonical template argument list.
|
|
|
|
TemplateArgument(Expr *E) : Kind(Expression) {
|
|
|
|
TypeOrValue = reinterpret_cast<uintptr_t>(E);
|
|
|
|
}
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief Construct a template argument that is a template argument pack.
|
|
|
|
///
|
|
|
|
/// We assume that storage for the template arguments provided
|
|
|
|
/// outlives the TemplateArgument itself.
|
|
|
|
TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) : Kind(Pack){
|
|
|
|
this->Args.Args = Args;
|
|
|
|
this->Args.NumArgs = NumArgs;
|
|
|
|
}
|
|
|
|
|
2009-11-04 15:04:32 +00:00
|
|
|
/// \brief Copy constructor for a template argument.
|
|
|
|
TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
|
2011-02-20 13:06:31 +00:00
|
|
|
// FIXME: Large integral values will get leaked. Do something
|
|
|
|
// similar to what we did with IntegerLiteral.
|
2009-11-04 15:04:32 +00:00
|
|
|
if (Kind == Integral) {
|
|
|
|
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
|
|
|
|
Integer.Type = Other.Integer.Type;
|
|
|
|
} else if (Kind == Pack) {
|
|
|
|
Args.NumArgs = Other.Args.NumArgs;
|
2011-02-20 13:06:31 +00:00
|
|
|
Args.Args = Other.Args.Args;
|
|
|
|
} else if (Kind == Template || Kind == TemplateExpansion) {
|
|
|
|
TemplateArg.Name = Other.TemplateArg.Name;
|
|
|
|
TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
|
|
|
|
} else
|
2009-11-04 15:04:32 +00:00
|
|
|
TypeOrValue = Other.TypeOrValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateArgument& operator=(const TemplateArgument& Other) {
|
|
|
|
using llvm::APSInt;
|
|
|
|
|
|
|
|
if (Kind == Other.Kind && Kind == Integral) {
|
|
|
|
// Copy integral values.
|
|
|
|
*this->getAsIntegral() = *Other.getAsIntegral();
|
|
|
|
Integer.Type = Other.Integer.Type;
|
2011-02-20 13:06:31 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Destroy the current integral value, if that's what we're holding.
|
|
|
|
if (Kind == Integral)
|
|
|
|
getAsIntegral()->~APSInt();
|
2009-11-04 15:04:32 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
Kind = Other.Kind;
|
2009-11-04 15:04:32 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
if (Other.Kind == Integral) {
|
|
|
|
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
|
|
|
|
Integer.Type = Other.Integer.Type;
|
|
|
|
} else if (Other.Kind == Pack) {
|
|
|
|
Args.NumArgs = Other.Args.NumArgs;
|
|
|
|
Args.Args = Other.Args.Args;
|
|
|
|
} else if (Kind == Template || Kind == TemplateExpansion) {
|
|
|
|
TemplateArg.Name = Other.TemplateArg.Name;
|
|
|
|
TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
|
|
|
|
} else {
|
|
|
|
TypeOrValue = Other.TypeOrValue;
|
2009-11-04 15:04:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
~TemplateArgument() {
|
|
|
|
using llvm::APSInt;
|
|
|
|
|
|
|
|
if (Kind == Integral)
|
|
|
|
getAsIntegral()->~APSInt();
|
|
|
|
}
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief Create a new template argument pack by copying the given set of
|
|
|
|
/// template arguments.
|
|
|
|
static TemplateArgument CreatePackCopy(ASTContext &Context,
|
|
|
|
const TemplateArgument *Args,
|
|
|
|
unsigned NumArgs);
|
|
|
|
|
2009-11-04 15:04:32 +00:00
|
|
|
/// \brief Return the kind of stored template argument.
|
2011-02-20 13:06:31 +00:00
|
|
|
ArgKind getKind() const { return (ArgKind)Kind; }
|
2009-11-04 15:04:32 +00:00
|
|
|
|
|
|
|
/// \brief Determine whether this template argument has no value.
|
|
|
|
bool isNull() const { return Kind == Null; }
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief Whether this template argument is dependent on a template
|
2011-07-17 15:40:56 +00:00
|
|
|
/// parameter such that its result can change from one instantiation to
|
|
|
|
/// another.
|
2011-02-20 13:06:31 +00:00
|
|
|
bool isDependent() const;
|
|
|
|
|
2011-07-17 15:40:56 +00:00
|
|
|
/// \brief Whether this template argument is dependent on a template
|
|
|
|
/// parameter.
|
|
|
|
bool isInstantiationDependent() const;
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief Whether this template argument contains an unexpanded
|
|
|
|
/// parameter pack.
|
|
|
|
bool containsUnexpandedParameterPack() const;
|
|
|
|
|
|
|
|
/// \brief Determine whether this template argument is a pack expansion.
|
|
|
|
bool isPackExpansion() const;
|
|
|
|
|
2009-11-04 15:04:32 +00:00
|
|
|
/// \brief Retrieve the template argument as a type.
|
|
|
|
QualType getAsType() const {
|
|
|
|
if (Kind != Type)
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Retrieve the template argument as a declaration.
|
|
|
|
Decl *getAsDecl() const {
|
|
|
|
if (Kind != Declaration)
|
|
|
|
return 0;
|
|
|
|
return reinterpret_cast<Decl *>(TypeOrValue);
|
|
|
|
}
|
|
|
|
|
2009-11-18 14:59:57 +00:00
|
|
|
/// \brief Retrieve the template argument as a template name.
|
|
|
|
TemplateName getAsTemplate() const {
|
|
|
|
if (Kind != Template)
|
|
|
|
return TemplateName();
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
return TemplateName::getFromVoidPointer(TemplateArg.Name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Retrieve the template argument as a template name; if the argument
|
|
|
|
/// is a pack expansion, return the pattern as a template name.
|
|
|
|
TemplateName getAsTemplateOrTemplatePattern() const {
|
|
|
|
if (Kind != Template && Kind != TemplateExpansion)
|
|
|
|
return TemplateName();
|
|
|
|
|
|
|
|
return TemplateName::getFromVoidPointer(TemplateArg.Name);
|
2009-11-18 14:59:57 +00:00
|
|
|
}
|
2011-02-20 13:06:31 +00:00
|
|
|
|
|
|
|
/// \brief Retrieve the number of expansions that a template template argument
|
|
|
|
/// expansion will produce, if known.
|
|
|
|
llvm::Optional<unsigned> getNumTemplateExpansions() const;
|
2009-11-18 14:59:57 +00:00
|
|
|
|
2009-11-04 15:04:32 +00:00
|
|
|
/// \brief Retrieve the template argument as an integral value.
|
|
|
|
llvm::APSInt *getAsIntegral() {
|
|
|
|
if (Kind != Integral)
|
|
|
|
return 0;
|
|
|
|
return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
const llvm::APSInt *getAsIntegral() const {
|
|
|
|
return const_cast<TemplateArgument*>(this)->getAsIntegral();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Retrieve the type of the integral value.
|
|
|
|
QualType getIntegralType() const {
|
|
|
|
if (Kind != Integral)
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
return QualType::getFromOpaquePtr(Integer.Type);
|
|
|
|
}
|
|
|
|
|
|
|
|
void setIntegralType(QualType T) {
|
|
|
|
assert(Kind == Integral &&
|
|
|
|
"Cannot set the integral type of a non-integral template argument");
|
|
|
|
Integer.Type = T.getAsOpaquePtr();
|
2010-01-01 10:34:51 +00:00
|
|
|
}
|
2009-11-04 15:04:32 +00:00
|
|
|
|
|
|
|
/// \brief Retrieve the template argument as an expression.
|
|
|
|
Expr *getAsExpr() const {
|
|
|
|
if (Kind != Expression)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return reinterpret_cast<Expr *>(TypeOrValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Iterator that traverses the elements of a template argument pack.
|
|
|
|
typedef const TemplateArgument * pack_iterator;
|
|
|
|
|
|
|
|
/// \brief Iterator referencing the first argument of a template argument
|
|
|
|
/// pack.
|
|
|
|
pack_iterator pack_begin() const {
|
|
|
|
assert(Kind == Pack);
|
|
|
|
return Args.Args;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Iterator referencing one past the last argument of a template
|
|
|
|
/// argument pack.
|
|
|
|
pack_iterator pack_end() const {
|
|
|
|
assert(Kind == Pack);
|
|
|
|
return Args.Args + Args.NumArgs;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief The number of template arguments in the given template argument
|
|
|
|
/// pack.
|
|
|
|
unsigned pack_size() const {
|
|
|
|
assert(Kind == Pack);
|
|
|
|
return Args.NumArgs;
|
|
|
|
}
|
|
|
|
|
2010-07-13 17:21:42 +00:00
|
|
|
/// Determines whether two template arguments are superficially the
|
|
|
|
/// same.
|
|
|
|
bool structurallyEquals(const TemplateArgument &Other) const;
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief When the template argument is a pack expansion, returns
|
|
|
|
/// the pattern of the pack expansion.
|
|
|
|
///
|
|
|
|
/// \param Ellipsis Will be set to the location of the ellipsis.
|
|
|
|
TemplateArgument getPackExpansionPattern() const;
|
2009-11-04 15:04:32 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief Print this template argument to the given output stream.
|
2011-10-20 21:14:49 +00:00
|
|
|
void print(const PrintingPolicy &Policy, raw_ostream &Out) const;
|
2011-02-20 13:06:31 +00:00
|
|
|
|
2009-11-04 15:04:32 +00:00
|
|
|
/// \brief Used to insert TemplateArguments into FoldingSets.
|
2011-02-20 13:06:31 +00:00
|
|
|
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
|
2009-11-04 15:04:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Location information for a TemplateArgument.
|
|
|
|
struct TemplateArgumentLocInfo {
|
|
|
|
private:
|
|
|
|
union {
|
|
|
|
Expr *Expression;
|
2009-12-15 18:49:47 +00:00
|
|
|
TypeSourceInfo *Declarator;
|
2009-11-18 14:59:57 +00:00
|
|
|
struct {
|
2011-05-02 19:39:53 +00:00
|
|
|
// FIXME: We'd like to just use the qualifier in the TemplateName,
|
|
|
|
// but template arguments get canonicalized too quickly.
|
|
|
|
NestedNameSpecifier *Qualifier;
|
|
|
|
void *QualifierLocData;
|
2009-11-18 14:59:57 +00:00
|
|
|
unsigned TemplateNameLoc;
|
2011-02-20 13:06:31 +00:00
|
|
|
unsigned EllipsisLoc;
|
2009-11-18 14:59:57 +00:00
|
|
|
} Template;
|
2009-11-04 15:04:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
2011-02-20 13:06:31 +00:00
|
|
|
TemplateArgumentLocInfo();
|
2009-11-04 15:04:32 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
|
2009-11-04 15:04:32 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
|
2009-11-18 14:59:57 +00:00
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc,
|
2011-02-20 13:06:31 +00:00
|
|
|
SourceLocation TemplateNameLoc,
|
|
|
|
SourceLocation EllipsisLoc)
|
2009-11-18 14:59:57 +00:00
|
|
|
{
|
2011-05-02 19:39:53 +00:00
|
|
|
Template.Qualifier = QualifierLoc.getNestedNameSpecifier();
|
|
|
|
Template.QualifierLocData = QualifierLoc.getOpaqueData();
|
2009-11-18 14:59:57 +00:00
|
|
|
Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
|
2011-02-20 13:06:31 +00:00
|
|
|
Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
|
2009-11-18 14:59:57 +00:00
|
|
|
}
|
2009-11-04 15:04:32 +00:00
|
|
|
|
2009-12-15 18:49:47 +00:00
|
|
|
TypeSourceInfo *getAsTypeSourceInfo() const {
|
2009-11-04 15:04:32 +00:00
|
|
|
return Declarator;
|
|
|
|
}
|
|
|
|
|
|
|
|
Expr *getAsExpr() const {
|
|
|
|
return Expression;
|
|
|
|
}
|
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
NestedNameSpecifierLoc getTemplateQualifierLoc() const {
|
|
|
|
return NestedNameSpecifierLoc(Template.Qualifier,
|
|
|
|
Template.QualifierLocData);
|
2009-11-18 14:59:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation getTemplateNameLoc() const {
|
|
|
|
return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
|
|
|
|
}
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
SourceLocation getTemplateEllipsisLoc() const {
|
|
|
|
return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
|
2009-11-04 15:04:32 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Location wrapper for a TemplateArgument. TemplateArgument is to
|
|
|
|
/// TemplateArgumentLoc as Type is to TypeLoc.
|
|
|
|
class TemplateArgumentLoc {
|
|
|
|
TemplateArgument Argument;
|
|
|
|
TemplateArgumentLocInfo LocInfo;
|
|
|
|
|
|
|
|
public:
|
|
|
|
TemplateArgumentLoc() {}
|
|
|
|
|
|
|
|
TemplateArgumentLoc(const TemplateArgument &Argument,
|
|
|
|
TemplateArgumentLocInfo Opaque)
|
|
|
|
: Argument(Argument), LocInfo(Opaque) {
|
|
|
|
}
|
|
|
|
|
2009-12-15 18:49:47 +00:00
|
|
|
TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
|
|
|
|
: Argument(Argument), LocInfo(TInfo) {
|
2009-11-04 15:04:32 +00:00
|
|
|
assert(Argument.getKind() == TemplateArgument::Type);
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
|
|
|
|
: Argument(Argument), LocInfo(E) {
|
|
|
|
assert(Argument.getKind() == TemplateArgument::Expression);
|
|
|
|
}
|
|
|
|
|
2009-11-18 14:59:57 +00:00
|
|
|
TemplateArgumentLoc(const TemplateArgument &Argument,
|
2011-05-02 19:39:53 +00:00
|
|
|
NestedNameSpecifierLoc QualifierLoc,
|
2011-02-20 13:06:31 +00:00
|
|
|
SourceLocation TemplateNameLoc,
|
|
|
|
SourceLocation EllipsisLoc = SourceLocation())
|
2011-05-02 19:39:53 +00:00
|
|
|
: Argument(Argument), LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) {
|
2011-02-20 13:06:31 +00:00
|
|
|
assert(Argument.getKind() == TemplateArgument::Template ||
|
|
|
|
Argument.getKind() == TemplateArgument::TemplateExpansion);
|
2009-11-18 14:59:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief - Fetches the primary location of the argument.
|
2009-11-04 15:04:32 +00:00
|
|
|
SourceLocation getLocation() const {
|
2011-02-20 13:06:31 +00:00
|
|
|
if (Argument.getKind() == TemplateArgument::Template ||
|
|
|
|
Argument.getKind() == TemplateArgument::TemplateExpansion)
|
2009-11-18 14:59:57 +00:00
|
|
|
return getTemplateNameLoc();
|
|
|
|
|
2009-11-04 15:04:32 +00:00
|
|
|
return getSourceRange().getBegin();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief - Fetches the full source range of the argument.
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY;
|
2009-11-04 15:04:32 +00:00
|
|
|
|
|
|
|
const TemplateArgument &getArgument() const {
|
|
|
|
return Argument;
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateArgumentLocInfo getLocInfo() const {
|
|
|
|
return LocInfo;
|
|
|
|
}
|
|
|
|
|
2009-12-15 18:49:47 +00:00
|
|
|
TypeSourceInfo *getTypeSourceInfo() const {
|
2009-11-04 15:04:32 +00:00
|
|
|
assert(Argument.getKind() == TemplateArgument::Type);
|
2009-12-15 18:49:47 +00:00
|
|
|
return LocInfo.getAsTypeSourceInfo();
|
2009-11-04 15:04:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Expr *getSourceExpression() const {
|
|
|
|
assert(Argument.getKind() == TemplateArgument::Expression);
|
|
|
|
return LocInfo.getAsExpr();
|
|
|
|
}
|
|
|
|
|
|
|
|
Expr *getSourceDeclExpression() const {
|
|
|
|
assert(Argument.getKind() == TemplateArgument::Declaration);
|
|
|
|
return LocInfo.getAsExpr();
|
|
|
|
}
|
2009-11-18 14:59:57 +00:00
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
NestedNameSpecifierLoc getTemplateQualifierLoc() const {
|
2011-02-20 13:06:31 +00:00
|
|
|
assert(Argument.getKind() == TemplateArgument::Template ||
|
|
|
|
Argument.getKind() == TemplateArgument::TemplateExpansion);
|
2011-05-02 19:39:53 +00:00
|
|
|
return LocInfo.getTemplateQualifierLoc();
|
2009-11-18 14:59:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation getTemplateNameLoc() const {
|
2011-02-20 13:06:31 +00:00
|
|
|
assert(Argument.getKind() == TemplateArgument::Template ||
|
|
|
|
Argument.getKind() == TemplateArgument::TemplateExpansion);
|
2009-11-18 14:59:57 +00:00
|
|
|
return LocInfo.getTemplateNameLoc();
|
|
|
|
}
|
2011-02-20 13:06:31 +00:00
|
|
|
|
|
|
|
SourceLocation getTemplateEllipsisLoc() const {
|
|
|
|
assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
|
|
|
|
return LocInfo.getTemplateEllipsisLoc();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief When the template argument is a pack expansion, returns
|
|
|
|
/// the pattern of the pack expansion.
|
|
|
|
///
|
|
|
|
/// \param Ellipsis Will be set to the location of the ellipsis.
|
|
|
|
///
|
|
|
|
/// \param NumExpansions Will be set to the number of expansions that will
|
|
|
|
/// be generated from this pack expansion, if known a priori.
|
|
|
|
TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis,
|
|
|
|
llvm::Optional<unsigned> &NumExpansions,
|
|
|
|
ASTContext &Context) const;
|
2009-11-04 15:04:32 +00:00
|
|
|
};
|
|
|
|
|
2009-12-01 11:08:04 +00:00
|
|
|
/// A convenient class for passing around template argument
|
|
|
|
/// information. Designed to be passed by reference.
|
|
|
|
class TemplateArgumentListInfo {
|
2011-10-20 21:14:49 +00:00
|
|
|
SmallVector<TemplateArgumentLoc, 8> Arguments;
|
2009-12-01 11:08:04 +00:00
|
|
|
SourceLocation LAngleLoc;
|
|
|
|
SourceLocation RAngleLoc;
|
|
|
|
|
2011-10-20 21:14:49 +00:00
|
|
|
// This can leak if used in an AST node, use ASTTemplateArgumentListInfo
|
|
|
|
// instead.
|
|
|
|
void* operator new(size_t bytes, ASTContext& C);
|
|
|
|
|
2009-12-01 11:08:04 +00:00
|
|
|
public:
|
|
|
|
TemplateArgumentListInfo() {}
|
|
|
|
|
|
|
|
TemplateArgumentListInfo(SourceLocation LAngleLoc,
|
|
|
|
SourceLocation RAngleLoc)
|
|
|
|
: LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
|
|
|
|
|
|
|
|
SourceLocation getLAngleLoc() const { return LAngleLoc; }
|
|
|
|
SourceLocation getRAngleLoc() const { return RAngleLoc; }
|
|
|
|
|
|
|
|
void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
|
|
|
|
void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
|
|
|
|
|
|
|
|
unsigned size() const { return Arguments.size(); }
|
|
|
|
|
|
|
|
const TemplateArgumentLoc *getArgumentArray() const {
|
|
|
|
return Arguments.data();
|
|
|
|
}
|
|
|
|
|
|
|
|
const TemplateArgumentLoc &operator[](unsigned I) const {
|
|
|
|
return Arguments[I];
|
|
|
|
}
|
|
|
|
|
|
|
|
void addArgument(const TemplateArgumentLoc &Loc) {
|
|
|
|
Arguments.push_back(Loc);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-10-20 21:14:49 +00:00
|
|
|
/// \brief Represents an explicit template argument list in C++, e.g.,
|
|
|
|
/// the "<int>" in "sort<int>".
|
|
|
|
/// This is safe to be used inside an AST node, in contrast with
|
|
|
|
/// TemplateArgumentListInfo.
|
|
|
|
struct ASTTemplateArgumentListInfo {
|
|
|
|
/// \brief The source location of the left angle bracket ('<');
|
|
|
|
SourceLocation LAngleLoc;
|
|
|
|
|
|
|
|
/// \brief The source location of the right angle bracket ('>');
|
|
|
|
SourceLocation RAngleLoc;
|
|
|
|
|
|
|
|
/// \brief The number of template arguments in TemplateArgs.
|
|
|
|
/// The actual template arguments (if any) are stored after the
|
|
|
|
/// ExplicitTemplateArgumentList structure.
|
|
|
|
unsigned NumTemplateArgs;
|
|
|
|
|
|
|
|
/// \brief Retrieve the template arguments
|
|
|
|
TemplateArgumentLoc *getTemplateArgs() {
|
|
|
|
return reinterpret_cast<TemplateArgumentLoc *> (this + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Retrieve the template arguments
|
|
|
|
const TemplateArgumentLoc *getTemplateArgs() const {
|
|
|
|
return reinterpret_cast<const TemplateArgumentLoc *> (this + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
const TemplateArgumentLoc &operator[](unsigned I) const {
|
|
|
|
return getTemplateArgs()[I];
|
|
|
|
}
|
|
|
|
|
|
|
|
static const ASTTemplateArgumentListInfo *Create(ASTContext &C,
|
|
|
|
const TemplateArgumentListInfo &List);
|
|
|
|
|
|
|
|
void initializeFrom(const TemplateArgumentListInfo &List);
|
|
|
|
void initializeFrom(const TemplateArgumentListInfo &List,
|
|
|
|
bool &Dependent, bool &InstantiationDependent,
|
|
|
|
bool &ContainsUnexpandedParameterPack);
|
|
|
|
void copyInto(TemplateArgumentListInfo &List) const;
|
|
|
|
static std::size_t sizeFor(unsigned NumTemplateArgs);
|
2012-04-14 14:01:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// \brief Extends ASTTemplateArgumentListInfo with the source location
|
|
|
|
/// information for the template keyword; this is used as part of the
|
|
|
|
/// representation of qualified identifiers, such as S<T>::template apply<T>.
|
|
|
|
struct ASTTemplateKWAndArgsInfo : public ASTTemplateArgumentListInfo {
|
|
|
|
typedef ASTTemplateArgumentListInfo Base;
|
|
|
|
|
|
|
|
// NOTE: the source location of the (optional) template keyword is
|
|
|
|
// stored after all template arguments.
|
|
|
|
|
|
|
|
/// \brief Get the source location of the template keyword.
|
|
|
|
SourceLocation getTemplateKeywordLoc() const {
|
|
|
|
return *reinterpret_cast<const SourceLocation*>
|
|
|
|
(getTemplateArgs() + NumTemplateArgs);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Sets the source location of the template keyword.
|
|
|
|
void setTemplateKeywordLoc(SourceLocation TemplateKWLoc) {
|
|
|
|
*reinterpret_cast<SourceLocation*>
|
|
|
|
(getTemplateArgs() + NumTemplateArgs) = TemplateKWLoc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const ASTTemplateKWAndArgsInfo*
|
|
|
|
Create(ASTContext &C, SourceLocation TemplateKWLoc,
|
|
|
|
const TemplateArgumentListInfo &List);
|
|
|
|
|
|
|
|
void initializeFrom(SourceLocation TemplateKWLoc,
|
|
|
|
const TemplateArgumentListInfo &List);
|
|
|
|
void initializeFrom(SourceLocation TemplateKWLoc,
|
|
|
|
const TemplateArgumentListInfo &List,
|
|
|
|
bool &Dependent, bool &InstantiationDependent,
|
|
|
|
bool &ContainsUnexpandedParameterPack);
|
|
|
|
void initializeFrom(SourceLocation TemplateKWLoc);
|
|
|
|
|
|
|
|
static std::size_t sizeFor(unsigned NumTemplateArgs);
|
2011-10-20 21:14:49 +00:00
|
|
|
};
|
|
|
|
|
2010-05-27 15:17:06 +00:00
|
|
|
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
|
|
|
const TemplateArgument &Arg);
|
2010-07-13 17:21:42 +00:00
|
|
|
|
|
|
|
inline TemplateSpecializationType::iterator
|
|
|
|
TemplateSpecializationType::end() const {
|
|
|
|
return getArgs() + getNumArgs();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline DependentTemplateSpecializationType::iterator
|
|
|
|
DependentTemplateSpecializationType::end() const {
|
|
|
|
return getArgs() + getNumArgs();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const TemplateArgument &
|
|
|
|
TemplateSpecializationType::getArg(unsigned Idx) const {
|
|
|
|
assert(Idx < getNumArgs() && "Template argument out of range");
|
|
|
|
return getArgs()[Idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const TemplateArgument &
|
|
|
|
DependentTemplateSpecializationType::getArg(unsigned Idx) const {
|
|
|
|
assert(Idx < getNumArgs() && "Template argument out of range");
|
|
|
|
return getArgs()[Idx];
|
|
|
|
}
|
2010-05-27 15:17:06 +00:00
|
|
|
|
|
|
|
} // end namespace clang
|
2009-11-04 15:04:32 +00:00
|
|
|
|
|
|
|
#endif
|