From: John McCall Date: Thu, 29 Oct 2009 07:48:15 +0000 (+0000) Subject: Extract TemplateArgument into a new header just for common template X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=275c10a8a4a43219f67d8d2c912ec6294d9d9af2;p=clang Extract TemplateArgument into a new header just for common template classes. Move its implementation into a new module. This will seem marginally more justified in a bit. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85499 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 0de33023bf..1b3ce46ee5 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -15,8 +15,7 @@ #define LLVM_CLANG_AST_DECLTEMPLATE_H #include "clang/AST/DeclCXX.h" -#include "llvm/ADT/APSInt.h" -#include "llvm/ADT/FoldingSet.h" +#include "clang/AST/TemplateBase.h" #include "llvm/ADT/PointerUnion.h" #include @@ -107,251 +106,6 @@ public: } }; -/// \brief Represents a template argument within a class template -/// specialization. -class TemplateArgument { - union { - uintptr_t TypeOrValue; - struct { - char Value[sizeof(llvm::APSInt)]; - void *Type; - } Integer; - struct { - TemplateArgument *Args; - unsigned NumArgs; - bool CopyArgs; - } Args; - }; - - /// \brief Location of the beginning of this template argument. - SourceLocation StartLoc; - -public: - /// \brief The type of template argument we're storing. - enum ArgKind { - 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, - /// The template argument is a value- or type-dependent expression - /// stored in an Expr*. - Expression = 4, - - /// The template argument is actually a parameter pack. Arguments are stored - /// in the Args struct. - Pack = 5 - } Kind; - - /// \brief Construct an empty, invalid template argument. - TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { } - - /// \brief Construct a template type argument. - TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) { - TypeOrValue = reinterpret_cast(T.getAsOpaquePtr()); - StartLoc = Loc; - } - - /// \brief Construct a template argument that refers to a - /// declaration, which is either an external declaration or a - /// template declaration. - TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) { - // FIXME: Need to be sure we have the "canonical" declaration! - TypeOrValue = reinterpret_cast(D); - StartLoc = Loc; - } - - /// \brief Construct an integral constant template argument. - TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value, - QualType Type) - : Kind(Integral) { - new (Integer.Value) llvm::APSInt(Value); - Integer.Type = Type.getAsOpaquePtr(); - StartLoc = Loc; - } - - /// \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); - - /// \brief Copy constructor for a template argument. - TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) { - if (Kind == Integral) { - new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); - Integer.Type = Other.Integer.Type; - } else if (Kind == Pack) { - Args.NumArgs = Other.Args.NumArgs; - Args.Args = new TemplateArgument[Args.NumArgs]; - for (unsigned I = 0; I != Args.NumArgs; ++I) - Args.Args[I] = Other.Args.Args[I]; - } - else - TypeOrValue = Other.TypeOrValue; - StartLoc = Other.StartLoc; - } - - TemplateArgument& operator=(const TemplateArgument& Other) { - // FIXME: Does not provide the strong guarantee for exception - // safety. - using llvm::APSInt; - - // FIXME: Handle Packs - assert(Kind != Pack && "FIXME: Handle packs"); - assert(Other.Kind != Pack && "FIXME: Handle packs"); - - if (Kind == Other.Kind && Kind == Integral) { - // Copy integral values. - *this->getAsIntegral() = *Other.getAsIntegral(); - Integer.Type = Other.Integer.Type; - } else { - // Destroy the current integral value, if that's what we're holding. - if (Kind == Integral) - getAsIntegral()->~APSInt(); - - Kind = Other.Kind; - - if (Other.Kind == Integral) { - new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); - Integer.Type = Other.Integer.Type; - } else - TypeOrValue = Other.TypeOrValue; - } - StartLoc = Other.StartLoc; - - return *this; - } - - ~TemplateArgument() { - using llvm::APSInt; - - if (Kind == Integral) - getAsIntegral()->~APSInt(); - else if (Kind == Pack && Args.CopyArgs) - delete[] Args.Args; - } - - /// \brief Return the kind of stored template argument. - ArgKind getKind() const { return Kind; } - - /// \brief Determine whether this template argument has no value. - bool isNull() const { return Kind == Null; } - - /// \brief Retrieve the template argument as a type. - QualType getAsType() const { - if (Kind != Type) - return QualType(); - - return QualType::getFromOpaquePtr(reinterpret_cast(TypeOrValue)); - } - - /// \brief Retrieve the template argument as a declaration. - Decl *getAsDecl() const { - if (Kind != Declaration) - return 0; - return reinterpret_cast(TypeOrValue); - } - - /// \brief Retrieve the template argument as an integral value. - llvm::APSInt *getAsIntegral() { - if (Kind != Integral) - return 0; - return reinterpret_cast(&Integer.Value[0]); - } - - const llvm::APSInt *getAsIntegral() const { - return const_cast(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(); - }; - - /// \brief Retrieve the template argument as an expression. - Expr *getAsExpr() const { - if (Kind != Expression) - return 0; - - return reinterpret_cast(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; - } - - /// \brief Retrieve the location where the template argument starts. - SourceLocation getLocation() const { return StartLoc; } - - /// \brief Construct a template argument pack. - void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs); - - /// \brief Used to insert TemplateArguments into FoldingSets. - void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const { - ID.AddInteger(Kind); - switch (Kind) { - case Null: - break; - - case Type: - getAsType().Profile(ID); - break; - - case Declaration: - ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); - break; - - case Integral: - getAsIntegral()->Profile(ID); - getIntegralType().Profile(ID); - break; - - case Expression: - getAsExpr()->Profile(ID, Context, true); - break; - - case Pack: - ID.AddInteger(Args.NumArgs); - for (unsigned I = 0; I != Args.NumArgs; ++I) - Args.Args[I].Profile(ID, Context); - } - } -}; - /// \brief A helper class for making template argument lists. class TemplateArgumentListBuilder { TemplateArgument *StructuredArgs; diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h new file mode 100644 index 0000000000..a328eafc7e --- /dev/null +++ b/include/clang/AST/TemplateBase.h @@ -0,0 +1,249 @@ +//===-- 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 + +#include "llvm/ADT/APSInt.h" +#include "clang/AST/Type.h" + +namespace llvm { + class FoldingSetNodeID; +} + +namespace clang { + +class Decl; +class Expr; + +/// \brief Represents a template argument within a class template +/// specialization. +class TemplateArgument { + union { + uintptr_t TypeOrValue; + struct { + char Value[sizeof(llvm::APSInt)]; + void *Type; + } Integer; + struct { + TemplateArgument *Args; + unsigned NumArgs; + bool CopyArgs; + } Args; + }; + + /// \brief Location of the beginning of this template argument. + SourceLocation StartLoc; + +public: + /// \brief The type of template argument we're storing. + enum ArgKind { + 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, + /// The template argument is a value- or type-dependent expression + /// stored in an Expr*. + Expression = 4, + + /// The template argument is actually a parameter pack. Arguments are stored + /// in the Args struct. + Pack = 5 + } Kind; + + /// \brief Construct an empty, invalid template argument. + TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { } + + /// \brief Construct a template type argument. + TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) { + TypeOrValue = reinterpret_cast(T.getAsOpaquePtr()); + StartLoc = Loc; + } + + /// \brief Construct a template argument that refers to a + /// declaration, which is either an external declaration or a + /// template declaration. + TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) { + // FIXME: Need to be sure we have the "canonical" declaration! + TypeOrValue = reinterpret_cast(D); + StartLoc = Loc; + } + + /// \brief Construct an integral constant template argument. + TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value, + QualType Type) + : Kind(Integral) { + new (Integer.Value) llvm::APSInt(Value); + Integer.Type = Type.getAsOpaquePtr(); + StartLoc = Loc; + } + + /// \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); + + /// \brief Copy constructor for a template argument. + TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) { + if (Kind == Integral) { + new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); + Integer.Type = Other.Integer.Type; + } else if (Kind == Pack) { + Args.NumArgs = Other.Args.NumArgs; + Args.Args = new TemplateArgument[Args.NumArgs]; + for (unsigned I = 0; I != Args.NumArgs; ++I) + Args.Args[I] = Other.Args.Args[I]; + } + else + TypeOrValue = Other.TypeOrValue; + StartLoc = Other.StartLoc; + } + + TemplateArgument& operator=(const TemplateArgument& Other) { + // FIXME: Does not provide the strong guarantee for exception + // safety. + using llvm::APSInt; + + // FIXME: Handle Packs + assert(Kind != Pack && "FIXME: Handle packs"); + assert(Other.Kind != Pack && "FIXME: Handle packs"); + + if (Kind == Other.Kind && Kind == Integral) { + // Copy integral values. + *this->getAsIntegral() = *Other.getAsIntegral(); + Integer.Type = Other.Integer.Type; + } else { + // Destroy the current integral value, if that's what we're holding. + if (Kind == Integral) + getAsIntegral()->~APSInt(); + + Kind = Other.Kind; + + if (Other.Kind == Integral) { + new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); + Integer.Type = Other.Integer.Type; + } else + TypeOrValue = Other.TypeOrValue; + } + StartLoc = Other.StartLoc; + + return *this; + } + + ~TemplateArgument() { + using llvm::APSInt; + + if (Kind == Integral) + getAsIntegral()->~APSInt(); + else if (Kind == Pack && Args.CopyArgs) + delete[] Args.Args; + } + + /// \brief Return the kind of stored template argument. + ArgKind getKind() const { return Kind; } + + /// \brief Determine whether this template argument has no value. + bool isNull() const { return Kind == Null; } + + /// \brief Retrieve the template argument as a type. + QualType getAsType() const { + if (Kind != Type) + return QualType(); + + return QualType::getFromOpaquePtr(reinterpret_cast(TypeOrValue)); + } + + /// \brief Retrieve the template argument as a declaration. + Decl *getAsDecl() const { + if (Kind != Declaration) + return 0; + return reinterpret_cast(TypeOrValue); + } + + /// \brief Retrieve the template argument as an integral value. + llvm::APSInt *getAsIntegral() { + if (Kind != Integral) + return 0; + return reinterpret_cast(&Integer.Value[0]); + } + + const llvm::APSInt *getAsIntegral() const { + return const_cast(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(); + }; + + /// \brief Retrieve the template argument as an expression. + Expr *getAsExpr() const { + if (Kind != Expression) + return 0; + + return reinterpret_cast(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; + } + + /// \brief Retrieve the location where the template argument starts. + SourceLocation getLocation() const { return StartLoc; } + + /// \brief Construct a template argument pack. + void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs); + + /// \brief Used to insert TemplateArguments into FoldingSets. + void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const; +}; + +} + +#endif diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 20e1150b22..e541406790 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -26,6 +26,7 @@ add_clang_library(clangAST StmtPrinter.cpp StmtProfile.cpp StmtViz.cpp + TemplateBase.cpp TemplateName.cpp Type.cpp TypeLoc.cpp diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index fb3bd09ff4..49244e1dba 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -286,34 +286,6 @@ SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const { : SourceLocation(); } -//===----------------------------------------------------------------------===// -// TemplateArgument Implementation -//===----------------------------------------------------------------------===// - -TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) { - TypeOrValue = reinterpret_cast(E); - StartLoc = E->getSourceRange().getBegin(); -} - -/// \brief Construct a template argument pack. -void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs, - bool CopyArgs) { - assert(isNull() && "Must call setArgumentPack on a null argument"); - - Kind = Pack; - Args.NumArgs = NumArgs; - Args.CopyArgs = CopyArgs; - if (!Args.CopyArgs) { - Args.Args = args; - return; - } - - // FIXME: Allocate in ASTContext - Args.Args = new TemplateArgument[NumArgs]; - for (unsigned I = 0; I != Args.NumArgs; ++I) - Args.Args[I] = args[I]; -} - //===----------------------------------------------------------------------===// // TemplateArgumentListBuilder Implementation //===----------------------------------------------------------------------===// diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp new file mode 100644 index 0000000000..3b3ec2b530 --- /dev/null +++ b/lib/AST/TemplateBase.cpp @@ -0,0 +1,79 @@ +//===--- TemplateBase.cpp - Common template AST class implementation ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements common classes used throughout C++ template +// representations. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/FoldingSet.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/Expr.h" + +using namespace clang; + +//===----------------------------------------------------------------------===// +// TemplateArgument Implementation +//===----------------------------------------------------------------------===// + +TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) { + TypeOrValue = reinterpret_cast(E); + StartLoc = E->getSourceRange().getBegin(); +} + +/// \brief Construct a template argument pack. +void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs, + bool CopyArgs) { + assert(isNull() && "Must call setArgumentPack on a null argument"); + + Kind = Pack; + Args.NumArgs = NumArgs; + Args.CopyArgs = CopyArgs; + if (!Args.CopyArgs) { + Args.Args = args; + return; + } + + // FIXME: Allocate in ASTContext + Args.Args = new TemplateArgument[NumArgs]; + for (unsigned I = 0; I != Args.NumArgs; ++I) + Args.Args[I] = args[I]; +} + +void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, + ASTContext &Context) const { + ID.AddInteger(Kind); + switch (Kind) { + case Null: + break; + + case Type: + getAsType().Profile(ID); + break; + + case Declaration: + ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); + break; + + case Integral: + getAsIntegral()->Profile(ID); + getIntegralType().Profile(ID); + break; + + case Expression: + getAsExpr()->Profile(ID, Context, true); + break; + + case Pack: + ID.AddInteger(Args.NumArgs); + for (unsigned I = 0; I != Args.NumArgs; ++I) + Args.Args[I].Profile(ID, Context); + } +}