Home | History | Annotate | Download | only in AST
      1 //===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //  This file provides definitions which are common for all kinds of
     11 //  template representation.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
     16 #define LLVM_CLANG_AST_TEMPLATEBASE_H
     17 
     18 #include "clang/AST/Type.h"
     19 #include "clang/AST/TemplateName.h"
     20 #include "llvm/ADT/APSInt.h"
     21 #include "llvm/ADT/SmallVector.h"
     22 #include "llvm/Support/Compiler.h"
     23 #include "llvm/Support/ErrorHandling.h"
     24 
     25 namespace llvm {
     26   class FoldingSetNodeID;
     27 }
     28 
     29 namespace clang {
     30 
     31 class Decl;
     32 class DiagnosticBuilder;
     33 class Expr;
     34 struct PrintingPolicy;
     35 class TypeSourceInfo;
     36 
     37 /// \brief Represents a template argument within a class template
     38 /// specialization.
     39 class TemplateArgument {
     40 public:
     41   /// \brief The kind of template argument we're storing.
     42   enum ArgKind {
     43     /// \brief Represents an empty template argument, e.g., one that has not
     44     /// been deduced.
     45     Null = 0,
     46     /// The template argument is a type. Its value is stored in the
     47     /// TypeOrValue field.
     48     Type,
     49     /// The template argument is a declaration that was provided for a pointer
     50     /// or reference non-type template parameter.
     51     Declaration,
     52     /// The template argument is an integral value stored in an llvm::APSInt
     53     /// that was provided for an integral non-type template parameter.
     54     Integral,
     55     /// The template argument is a template name that was provided for a
     56     /// template template parameter.
     57     Template,
     58     /// The template argument is a pack expansion of a template name that was
     59     /// provided for a template template parameter.
     60     TemplateExpansion,
     61     /// The template argument is a value- or type-dependent expression
     62     /// stored in an Expr*.
     63     Expression,
     64     /// The template argument is actually a parameter pack. Arguments are stored
     65     /// in the Args struct.
     66     Pack
     67   };
     68 
     69 private:
     70   /// \brief The kind of template argument we're storing.
     71   unsigned Kind;
     72 
     73   union {
     74     uintptr_t TypeOrValue;
     75     struct {
     76       // We store a decomposed APSInt with the data allocated by ASTContext if
     77       // BitWidth > 64. The memory may be shared between multiple
     78       // TemplateArgument instances.
     79       union {
     80         uint64_t VAL;          ///< Used to store the <= 64 bits integer value.
     81         const uint64_t *pVal;  ///< Used to store the >64 bits integer value.
     82       };
     83       unsigned BitWidth : 31;
     84       unsigned IsUnsigned : 1;
     85       void *Type;
     86     } Integer;
     87     struct {
     88       const TemplateArgument *Args;
     89       unsigned NumArgs;
     90     } Args;
     91     struct {
     92       void *Name;
     93       unsigned NumExpansions;
     94     } TemplateArg;
     95   };
     96 
     97   TemplateArgument(TemplateName, bool); // DO NOT USE
     98 
     99 public:
    100   /// \brief Construct an empty, invalid template argument.
    101   TemplateArgument() : Kind(Null), TypeOrValue(0) { }
    102 
    103   /// \brief Construct a template type argument.
    104   TemplateArgument(QualType T) : Kind(Type) {
    105     TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
    106   }
    107 
    108   /// \brief Construct a template argument that refers to a
    109   /// declaration, which is either an external declaration or a
    110   /// template declaration.
    111   TemplateArgument(Decl *D) : Kind(Declaration) {
    112     TypeOrValue = reinterpret_cast<uintptr_t>(D);
    113   }
    114 
    115   /// \brief Construct an integral constant template argument. The memory to
    116   /// store the value is allocated with Ctx.
    117   TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type);
    118 
    119   /// \brief Construct an integral constant template argument with the same
    120   /// value as Other but a different type.
    121   TemplateArgument(const TemplateArgument &Other, QualType Type)
    122     : Kind(Integral) {
    123     Integer = Other.Integer;
    124     Integer.Type = Type.getAsOpaquePtr();
    125   }
    126 
    127   /// \brief Construct a template argument that is a template.
    128   ///
    129   /// This form of template argument is generally used for template template
    130   /// parameters. However, the template name could be a dependent template
    131   /// name that ends up being instantiated to a function template whose address
    132   /// is taken.
    133   ///
    134   /// \param Name The template name.
    135   TemplateArgument(TemplateName Name) : Kind(Template)
    136   {
    137     TemplateArg.Name = Name.getAsVoidPointer();
    138     TemplateArg.NumExpansions = 0;
    139   }
    140 
    141   /// \brief Construct a template argument that is a template pack expansion.
    142   ///
    143   /// This form of template argument is generally used for template template
    144   /// parameters. However, the template name could be a dependent template
    145   /// name that ends up being instantiated to a function template whose address
    146   /// is taken.
    147   ///
    148   /// \param Name The template name.
    149   ///
    150   /// \param NumExpansions The number of expansions that will be generated by
    151   /// instantiating
    152   TemplateArgument(TemplateName Name, llvm::Optional<unsigned> NumExpansions)
    153     : Kind(TemplateExpansion)
    154   {
    155     TemplateArg.Name = Name.getAsVoidPointer();
    156     if (NumExpansions)
    157       TemplateArg.NumExpansions = *NumExpansions + 1;
    158     else
    159       TemplateArg.NumExpansions = 0;
    160   }
    161 
    162   /// \brief Construct a template argument that is an expression.
    163   ///
    164   /// This form of template argument only occurs in template argument
    165   /// lists used for dependent types and for expression; it will not
    166   /// occur in a non-dependent, canonical template argument list.
    167   TemplateArgument(Expr *E) : Kind(Expression) {
    168     TypeOrValue = reinterpret_cast<uintptr_t>(E);
    169   }
    170 
    171   /// \brief Construct a template argument that is a template argument pack.
    172   ///
    173   /// We assume that storage for the template arguments provided
    174   /// outlives the TemplateArgument itself.
    175   TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) : Kind(Pack){
    176     this->Args.Args = Args;
    177     this->Args.NumArgs = NumArgs;
    178   }
    179 
    180   /// \brief Create a new template argument pack by copying the given set of
    181   /// template arguments.
    182   static TemplateArgument CreatePackCopy(ASTContext &Context,
    183                                          const TemplateArgument *Args,
    184                                          unsigned NumArgs);
    185 
    186   /// \brief Return the kind of stored template argument.
    187   ArgKind getKind() const { return (ArgKind)Kind; }
    188 
    189   /// \brief Determine whether this template argument has no value.
    190   bool isNull() const { return Kind == Null; }
    191 
    192   /// \brief Whether this template argument is dependent on a template
    193   /// parameter such that its result can change from one instantiation to
    194   /// another.
    195   bool isDependent() const;
    196 
    197   /// \brief Whether this template argument is dependent on a template
    198   /// parameter.
    199   bool isInstantiationDependent() const;
    200 
    201   /// \brief Whether this template argument contains an unexpanded
    202   /// parameter pack.
    203   bool containsUnexpandedParameterPack() const;
    204 
    205   /// \brief Determine whether this template argument is a pack expansion.
    206   bool isPackExpansion() const;
    207 
    208   /// \brief Retrieve the template argument as a type.
    209   QualType getAsType() const {
    210     if (Kind != Type)
    211       return QualType();
    212 
    213     return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
    214   }
    215 
    216   /// \brief Retrieve the template argument as a declaration.
    217   Decl *getAsDecl() const {
    218     if (Kind != Declaration)
    219       return 0;
    220     return reinterpret_cast<Decl *>(TypeOrValue);
    221   }
    222 
    223   /// \brief Retrieve the template argument as a template name.
    224   TemplateName getAsTemplate() const {
    225     if (Kind != Template)
    226       return TemplateName();
    227 
    228     return TemplateName::getFromVoidPointer(TemplateArg.Name);
    229   }
    230 
    231   /// \brief Retrieve the template argument as a template name; if the argument
    232   /// is a pack expansion, return the pattern as a template name.
    233   TemplateName getAsTemplateOrTemplatePattern() const {
    234     if (Kind != Template && Kind != TemplateExpansion)
    235       return TemplateName();
    236 
    237     return TemplateName::getFromVoidPointer(TemplateArg.Name);
    238   }
    239 
    240   /// \brief Retrieve the number of expansions that a template template argument
    241   /// expansion will produce, if known.
    242   llvm::Optional<unsigned> getNumTemplateExpansions() const;
    243 
    244   /// \brief Retrieve the template argument as an integral value.
    245   // FIXME: Provide a way to read the integral data without copying the value.
    246   llvm::APSInt getAsIntegral() const {
    247     using namespace llvm;
    248     if (Integer.BitWidth <= 64)
    249       return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned);
    250 
    251     unsigned NumWords = APInt::getNumWords(Integer.BitWidth);
    252     return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)),
    253                   Integer.IsUnsigned);
    254   }
    255 
    256   /// \brief Retrieve the type of the integral value.
    257   QualType getIntegralType() const {
    258     if (Kind != Integral)
    259       return QualType();
    260 
    261     return QualType::getFromOpaquePtr(Integer.Type);
    262   }
    263 
    264   void setIntegralType(QualType T) {
    265     assert(Kind == Integral &&
    266            "Cannot set the integral type of a non-integral template argument");
    267     Integer.Type = T.getAsOpaquePtr();
    268   }
    269 
    270   /// \brief Retrieve the template argument as an expression.
    271   Expr *getAsExpr() const {
    272     if (Kind != Expression)
    273       return 0;
    274 
    275     return reinterpret_cast<Expr *>(TypeOrValue);
    276   }
    277 
    278   /// \brief Iterator that traverses the elements of a template argument pack.
    279   typedef const TemplateArgument * pack_iterator;
    280 
    281   /// \brief Iterator referencing the first argument of a template argument
    282   /// pack.
    283   pack_iterator pack_begin() const {
    284     assert(Kind == Pack);
    285     return Args.Args;
    286   }
    287 
    288   /// \brief Iterator referencing one past the last argument of a template
    289   /// argument pack.
    290   pack_iterator pack_end() const {
    291     assert(Kind == Pack);
    292     return Args.Args + Args.NumArgs;
    293   }
    294 
    295   /// \brief The number of template arguments in the given template argument
    296   /// pack.
    297   unsigned pack_size() const {
    298     assert(Kind == Pack);
    299     return Args.NumArgs;
    300   }
    301 
    302   /// \brief Determines whether two template arguments are superficially the
    303   /// same.
    304   bool structurallyEquals(const TemplateArgument &Other) const;
    305 
    306   /// \brief When the template argument is a pack expansion, returns
    307   /// the pattern of the pack expansion.
    308   TemplateArgument getPackExpansionPattern() const;
    309 
    310   /// \brief Print this template argument to the given output stream.
    311   void print(const PrintingPolicy &Policy, raw_ostream &Out) const;
    312 
    313   /// \brief Used to insert TemplateArguments into FoldingSets.
    314   void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
    315 };
    316 
    317 /// Location information for a TemplateArgument.
    318 struct TemplateArgumentLocInfo {
    319 private:
    320   union {
    321     Expr *Expression;
    322     TypeSourceInfo *Declarator;
    323     struct {
    324       // FIXME: We'd like to just use the qualifier in the TemplateName,
    325       // but template arguments get canonicalized too quickly.
    326       NestedNameSpecifier *Qualifier;
    327       void *QualifierLocData;
    328       unsigned TemplateNameLoc;
    329       unsigned EllipsisLoc;
    330     } Template;
    331   };
    332 
    333 public:
    334   TemplateArgumentLocInfo();
    335 
    336   TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
    337 
    338   TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
    339 
    340   TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc,
    341                           SourceLocation TemplateNameLoc,
    342                           SourceLocation EllipsisLoc)
    343   {
    344     Template.Qualifier = QualifierLoc.getNestedNameSpecifier();
    345     Template.QualifierLocData = QualifierLoc.getOpaqueData();
    346     Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
    347     Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
    348   }
    349 
    350   TypeSourceInfo *getAsTypeSourceInfo() const {
    351     return Declarator;
    352   }
    353 
    354   Expr *getAsExpr() const {
    355     return Expression;
    356   }
    357 
    358   NestedNameSpecifierLoc getTemplateQualifierLoc() const {
    359     return NestedNameSpecifierLoc(Template.Qualifier,
    360                                   Template.QualifierLocData);
    361   }
    362 
    363   SourceLocation getTemplateNameLoc() const {
    364     return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
    365   }
    366 
    367   SourceLocation getTemplateEllipsisLoc() const {
    368     return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
    369   }
    370 };
    371 
    372 /// Location wrapper for a TemplateArgument.  TemplateArgument is to
    373 /// TemplateArgumentLoc as Type is to TypeLoc.
    374 class TemplateArgumentLoc {
    375   TemplateArgument Argument;
    376   TemplateArgumentLocInfo LocInfo;
    377 
    378 public:
    379   TemplateArgumentLoc() {}
    380 
    381   TemplateArgumentLoc(const TemplateArgument &Argument,
    382                       TemplateArgumentLocInfo Opaque)
    383     : Argument(Argument), LocInfo(Opaque) {
    384   }
    385 
    386   TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
    387     : Argument(Argument), LocInfo(TInfo) {
    388     assert(Argument.getKind() == TemplateArgument::Type);
    389   }
    390 
    391   TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
    392     : Argument(Argument), LocInfo(E) {
    393     assert(Argument.getKind() == TemplateArgument::Expression);
    394   }
    395 
    396   TemplateArgumentLoc(const TemplateArgument &Argument,
    397                       NestedNameSpecifierLoc QualifierLoc,
    398                       SourceLocation TemplateNameLoc,
    399                       SourceLocation EllipsisLoc = SourceLocation())
    400     : Argument(Argument), LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) {
    401     assert(Argument.getKind() == TemplateArgument::Template ||
    402            Argument.getKind() == TemplateArgument::TemplateExpansion);
    403   }
    404 
    405   /// \brief - Fetches the primary location of the argument.
    406   SourceLocation getLocation() const {
    407     if (Argument.getKind() == TemplateArgument::Template ||
    408         Argument.getKind() == TemplateArgument::TemplateExpansion)
    409       return getTemplateNameLoc();
    410 
    411     return getSourceRange().getBegin();
    412   }
    413 
    414   /// \brief - Fetches the full source range of the argument.
    415   SourceRange getSourceRange() const LLVM_READONLY;
    416 
    417   const TemplateArgument &getArgument() const {
    418     return Argument;
    419   }
    420 
    421   TemplateArgumentLocInfo getLocInfo() const {
    422     return LocInfo;
    423   }
    424 
    425   TypeSourceInfo *getTypeSourceInfo() const {
    426     assert(Argument.getKind() == TemplateArgument::Type);
    427     return LocInfo.getAsTypeSourceInfo();
    428   }
    429 
    430   Expr *getSourceExpression() const {
    431     assert(Argument.getKind() == TemplateArgument::Expression);
    432     return LocInfo.getAsExpr();
    433   }
    434 
    435   Expr *getSourceDeclExpression() const {
    436     assert(Argument.getKind() == TemplateArgument::Declaration);
    437     return LocInfo.getAsExpr();
    438   }
    439 
    440   NestedNameSpecifierLoc getTemplateQualifierLoc() const {
    441     assert(Argument.getKind() == TemplateArgument::Template ||
    442            Argument.getKind() == TemplateArgument::TemplateExpansion);
    443     return LocInfo.getTemplateQualifierLoc();
    444   }
    445 
    446   SourceLocation getTemplateNameLoc() const {
    447     assert(Argument.getKind() == TemplateArgument::Template ||
    448            Argument.getKind() == TemplateArgument::TemplateExpansion);
    449     return LocInfo.getTemplateNameLoc();
    450   }
    451 
    452   SourceLocation getTemplateEllipsisLoc() const {
    453     assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
    454     return LocInfo.getTemplateEllipsisLoc();
    455   }
    456 
    457   /// \brief When the template argument is a pack expansion, returns
    458   /// the pattern of the pack expansion.
    459   ///
    460   /// \param Ellipsis Will be set to the location of the ellipsis.
    461   ///
    462   /// \param NumExpansions Will be set to the number of expansions that will
    463   /// be generated from this pack expansion, if known a priori.
    464   TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis,
    465                                         llvm::Optional<unsigned> &NumExpansions,
    466                                               ASTContext &Context) const;
    467 };
    468 
    469 /// A convenient class for passing around template argument
    470 /// information.  Designed to be passed by reference.
    471 class TemplateArgumentListInfo {
    472   SmallVector<TemplateArgumentLoc, 8> Arguments;
    473   SourceLocation LAngleLoc;
    474   SourceLocation RAngleLoc;
    475 
    476   // This can leak if used in an AST node, use ASTTemplateArgumentListInfo
    477   // instead.
    478   void* operator new(size_t bytes, ASTContext& C);
    479 
    480 public:
    481   TemplateArgumentListInfo() {}
    482 
    483   TemplateArgumentListInfo(SourceLocation LAngleLoc,
    484                            SourceLocation RAngleLoc)
    485     : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
    486 
    487   SourceLocation getLAngleLoc() const { return LAngleLoc; }
    488   SourceLocation getRAngleLoc() const { return RAngleLoc; }
    489 
    490   void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
    491   void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
    492 
    493   unsigned size() const { return Arguments.size(); }
    494 
    495   const TemplateArgumentLoc *getArgumentArray() const {
    496     return Arguments.data();
    497   }
    498 
    499   const TemplateArgumentLoc &operator[](unsigned I) const {
    500     return Arguments[I];
    501   }
    502 
    503   void addArgument(const TemplateArgumentLoc &Loc) {
    504     Arguments.push_back(Loc);
    505   }
    506 };
    507 
    508 /// \brief Represents an explicit template argument list in C++, e.g.,
    509 /// the "<int>" in "sort<int>".
    510 /// This is safe to be used inside an AST node, in contrast with
    511 /// TemplateArgumentListInfo.
    512 struct ASTTemplateArgumentListInfo {
    513   /// \brief The source location of the left angle bracket ('<').
    514   SourceLocation LAngleLoc;
    515 
    516   /// \brief The source location of the right angle bracket ('>').
    517   SourceLocation RAngleLoc;
    518 
    519   union {
    520     /// \brief The number of template arguments in TemplateArgs.
    521     /// The actual template arguments (if any) are stored after the
    522     /// ExplicitTemplateArgumentList structure.
    523     unsigned NumTemplateArgs;
    524 
    525     /// Force ASTTemplateArgumentListInfo to the right alignment
    526     /// for the following array of TemplateArgumentLocs.
    527     void *Aligner;
    528   };
    529 
    530   /// \brief Retrieve the template arguments
    531   TemplateArgumentLoc *getTemplateArgs() {
    532     return reinterpret_cast<TemplateArgumentLoc *> (this + 1);
    533   }
    534 
    535   /// \brief Retrieve the template arguments
    536   const TemplateArgumentLoc *getTemplateArgs() const {
    537     return reinterpret_cast<const TemplateArgumentLoc *> (this + 1);
    538   }
    539 
    540   const TemplateArgumentLoc &operator[](unsigned I) const {
    541     return getTemplateArgs()[I];
    542   }
    543 
    544   static const ASTTemplateArgumentListInfo *Create(ASTContext &C,
    545                                           const TemplateArgumentListInfo &List);
    546 
    547   void initializeFrom(const TemplateArgumentListInfo &List);
    548   void initializeFrom(const TemplateArgumentListInfo &List,
    549                       bool &Dependent, bool &InstantiationDependent,
    550                       bool &ContainsUnexpandedParameterPack);
    551   void copyInto(TemplateArgumentListInfo &List) const;
    552   static std::size_t sizeFor(unsigned NumTemplateArgs);
    553 };
    554 
    555 /// \brief Extends ASTTemplateArgumentListInfo with the source location
    556 /// information for the template keyword; this is used as part of the
    557 /// representation of qualified identifiers, such as S<T>::template apply<T>.
    558 struct ASTTemplateKWAndArgsInfo : public ASTTemplateArgumentListInfo {
    559   typedef ASTTemplateArgumentListInfo Base;
    560 
    561   // NOTE: the source location of the (optional) template keyword is
    562   // stored after all template arguments.
    563 
    564   /// \brief Get the source location of the template keyword.
    565   SourceLocation getTemplateKeywordLoc() const {
    566     return *reinterpret_cast<const SourceLocation*>
    567       (getTemplateArgs() + NumTemplateArgs);
    568   }
    569 
    570   /// \brief Sets the source location of the template keyword.
    571   void setTemplateKeywordLoc(SourceLocation TemplateKWLoc) {
    572     *reinterpret_cast<SourceLocation*>
    573       (getTemplateArgs() + NumTemplateArgs) = TemplateKWLoc;
    574   }
    575 
    576   static const ASTTemplateKWAndArgsInfo*
    577   Create(ASTContext &C, SourceLocation TemplateKWLoc,
    578          const TemplateArgumentListInfo &List);
    579 
    580   void initializeFrom(SourceLocation TemplateKWLoc,
    581                       const TemplateArgumentListInfo &List);
    582   void initializeFrom(SourceLocation TemplateKWLoc,
    583                       const TemplateArgumentListInfo &List,
    584                       bool &Dependent, bool &InstantiationDependent,
    585                       bool &ContainsUnexpandedParameterPack);
    586   void initializeFrom(SourceLocation TemplateKWLoc);
    587 
    588   static std::size_t sizeFor(unsigned NumTemplateArgs);
    589 };
    590 
    591 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
    592                                     const TemplateArgument &Arg);
    593 
    594 inline TemplateSpecializationType::iterator
    595     TemplateSpecializationType::end() const {
    596   return getArgs() + getNumArgs();
    597 }
    598 
    599 inline DependentTemplateSpecializationType::iterator
    600     DependentTemplateSpecializationType::end() const {
    601   return getArgs() + getNumArgs();
    602 }
    603 
    604 inline const TemplateArgument &
    605     TemplateSpecializationType::getArg(unsigned Idx) const {
    606   assert(Idx < getNumArgs() && "Template argument out of range");
    607   return getArgs()[Idx];
    608 }
    609 
    610 inline const TemplateArgument &
    611     DependentTemplateSpecializationType::getArg(unsigned Idx) const {
    612   assert(Idx < getNumArgs() && "Template argument out of range");
    613   return getArgs()[Idx];
    614 }
    615 
    616 } // end namespace clang
    617 
    618 #endif
    619