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 "llvm/ADT/APSInt.h"
     19 #include "llvm/ADT/SmallVector.h"
     20 #include "llvm/Support/ErrorHandling.h"
     21 #include "clang/AST/Type.h"
     22 #include "clang/AST/TemplateName.h"
     23 
     24 namespace llvm {
     25   class FoldingSetNodeID;
     26   class raw_ostream;
     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       char Value[sizeof(llvm::APSInt)];
     77       void *Type;
     78     } Integer;
     79     struct {
     80       const TemplateArgument *Args;
     81       unsigned NumArgs;
     82     } Args;
     83     struct {
     84       void *Name;
     85       unsigned NumExpansions;
     86     } TemplateArg;
     87   };
     88 
     89   TemplateArgument(TemplateName, bool); // DO NOT USE
     90 
     91 public:
     92   /// \brief Construct an empty, invalid template argument.
     93   TemplateArgument() : Kind(Null), TypeOrValue(0) { }
     94 
     95   /// \brief Construct a template type argument.
     96   TemplateArgument(QualType T) : Kind(Type) {
     97     TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
     98   }
     99 
    100   /// \brief Construct a template argument that refers to a
    101   /// declaration, which is either an external declaration or a
    102   /// template declaration.
    103   TemplateArgument(Decl *D) : Kind(Declaration) {
    104     // FIXME: Need to be sure we have the "canonical" declaration!
    105     TypeOrValue = reinterpret_cast<uintptr_t>(D);
    106   }
    107 
    108   /// \brief Construct an integral constant template argument.
    109   TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) {
    110     // FIXME: Large integral values will get leaked. Do something
    111     // similar to what we did with IntegerLiteral.
    112     new (Integer.Value) llvm::APSInt(Value);
    113     Integer.Type = Type.getAsOpaquePtr();
    114   }
    115 
    116   /// \brief Construct a template argument that is a template.
    117   ///
    118   /// This form of template argument is generally used for template template
    119   /// parameters. However, the template name could be a dependent template
    120   /// name that ends up being instantiated to a function template whose address
    121   /// is taken.
    122   ///
    123   /// \param Name The template name.
    124   TemplateArgument(TemplateName Name) : Kind(Template)
    125   {
    126     TemplateArg.Name = Name.getAsVoidPointer();
    127     TemplateArg.NumExpansions = 0;
    128   }
    129 
    130   /// \brief Construct a template argument that is a template pack expansion.
    131   ///
    132   /// This form of template argument is generally used for template template
    133   /// parameters. However, the template name could be a dependent template
    134   /// name that ends up being instantiated to a function template whose address
    135   /// is taken.
    136   ///
    137   /// \param Name The template name.
    138   ///
    139   /// \param NumExpansions The number of expansions that will be generated by
    140   /// instantiating
    141   TemplateArgument(TemplateName Name, llvm::Optional<unsigned> NumExpansions)
    142     : Kind(TemplateExpansion)
    143   {
    144     TemplateArg.Name = Name.getAsVoidPointer();
    145     if (NumExpansions)
    146       TemplateArg.NumExpansions = *NumExpansions + 1;
    147     else
    148       TemplateArg.NumExpansions = 0;
    149   }
    150 
    151   /// \brief Construct a template argument that is an expression.
    152   ///
    153   /// This form of template argument only occurs in template argument
    154   /// lists used for dependent types and for expression; it will not
    155   /// occur in a non-dependent, canonical template argument list.
    156   TemplateArgument(Expr *E) : Kind(Expression) {
    157     TypeOrValue = reinterpret_cast<uintptr_t>(E);
    158   }
    159 
    160   /// \brief Construct a template argument that is a template argument pack.
    161   ///
    162   /// We assume that storage for the template arguments provided
    163   /// outlives the TemplateArgument itself.
    164   TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) : Kind(Pack){
    165     this->Args.Args = Args;
    166     this->Args.NumArgs = NumArgs;
    167   }
    168 
    169   /// \brief Copy constructor for a template argument.
    170   TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
    171     // FIXME: Large integral values will get leaked. Do something
    172     // similar to what we did with IntegerLiteral.
    173     if (Kind == Integral) {
    174       new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
    175       Integer.Type = Other.Integer.Type;
    176     } else if (Kind == Pack) {
    177       Args.NumArgs = Other.Args.NumArgs;
    178       Args.Args = Other.Args.Args;
    179     } else if (Kind == Template || Kind == TemplateExpansion) {
    180       TemplateArg.Name = Other.TemplateArg.Name;
    181       TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
    182     } else
    183       TypeOrValue = Other.TypeOrValue;
    184   }
    185 
    186   TemplateArgument& operator=(const TemplateArgument& Other) {
    187     using llvm::APSInt;
    188 
    189     if (Kind == Other.Kind && Kind == Integral) {
    190       // Copy integral values.
    191       *this->getAsIntegral() = *Other.getAsIntegral();
    192       Integer.Type = Other.Integer.Type;
    193       return *this;
    194     }
    195 
    196     // Destroy the current integral value, if that's what we're holding.
    197     if (Kind == Integral)
    198       getAsIntegral()->~APSInt();
    199 
    200     Kind = Other.Kind;
    201 
    202     if (Other.Kind == Integral) {
    203       new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
    204       Integer.Type = Other.Integer.Type;
    205     } else if (Other.Kind == Pack) {
    206       Args.NumArgs = Other.Args.NumArgs;
    207       Args.Args = Other.Args.Args;
    208     } else if (Kind == Template || Kind == TemplateExpansion) {
    209       TemplateArg.Name = Other.TemplateArg.Name;
    210       TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
    211     } else {
    212       TypeOrValue = Other.TypeOrValue;
    213     }
    214 
    215     return *this;
    216   }
    217 
    218   ~TemplateArgument() {
    219     using llvm::APSInt;
    220 
    221     if (Kind == Integral)
    222       getAsIntegral()->~APSInt();
    223   }
    224 
    225   /// \brief Create a new template argument pack by copying the given set of
    226   /// template arguments.
    227   static TemplateArgument CreatePackCopy(ASTContext &Context,
    228                                          const TemplateArgument *Args,
    229                                          unsigned NumArgs);
    230 
    231   /// \brief Return the kind of stored template argument.
    232   ArgKind getKind() const { return (ArgKind)Kind; }
    233 
    234   /// \brief Determine whether this template argument has no value.
    235   bool isNull() const { return Kind == Null; }
    236 
    237   /// \brief Whether this template argument is dependent on a template
    238   /// parameter such that its result can change from one instantiation to
    239   /// another.
    240   bool isDependent() const;
    241 
    242   /// \brief Whether this template argument is dependent on a template
    243   /// parameter.
    244   bool isInstantiationDependent() const;
    245 
    246   /// \brief Whether this template argument contains an unexpanded
    247   /// parameter pack.
    248   bool containsUnexpandedParameterPack() const;
    249 
    250   /// \brief Determine whether this template argument is a pack expansion.
    251   bool isPackExpansion() const;
    252 
    253   /// \brief Retrieve the template argument as a type.
    254   QualType getAsType() const {
    255     if (Kind != Type)
    256       return QualType();
    257 
    258     return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
    259   }
    260 
    261   /// \brief Retrieve the template argument as a declaration.
    262   Decl *getAsDecl() const {
    263     if (Kind != Declaration)
    264       return 0;
    265     return reinterpret_cast<Decl *>(TypeOrValue);
    266   }
    267 
    268   /// \brief Retrieve the template argument as a template name.
    269   TemplateName getAsTemplate() const {
    270     if (Kind != Template)
    271       return TemplateName();
    272 
    273     return TemplateName::getFromVoidPointer(TemplateArg.Name);
    274   }
    275 
    276   /// \brief Retrieve the template argument as a template name; if the argument
    277   /// is a pack expansion, return the pattern as a template name.
    278   TemplateName getAsTemplateOrTemplatePattern() const {
    279     if (Kind != Template && Kind != TemplateExpansion)
    280       return TemplateName();
    281 
    282     return TemplateName::getFromVoidPointer(TemplateArg.Name);
    283   }
    284 
    285   /// \brief Retrieve the number of expansions that a template template argument
    286   /// expansion will produce, if known.
    287   llvm::Optional<unsigned> getNumTemplateExpansions() const;
    288 
    289   /// \brief Retrieve the template argument as an integral value.
    290   llvm::APSInt *getAsIntegral() {
    291     if (Kind != Integral)
    292       return 0;
    293     return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
    294   }
    295 
    296   const llvm::APSInt *getAsIntegral() const {
    297     return const_cast<TemplateArgument*>(this)->getAsIntegral();
    298   }
    299 
    300   /// \brief Retrieve the type of the integral value.
    301   QualType getIntegralType() const {
    302     if (Kind != Integral)
    303       return QualType();
    304 
    305     return QualType::getFromOpaquePtr(Integer.Type);
    306   }
    307 
    308   void setIntegralType(QualType T) {
    309     assert(Kind == Integral &&
    310            "Cannot set the integral type of a non-integral template argument");
    311     Integer.Type = T.getAsOpaquePtr();
    312   }
    313 
    314   /// \brief Retrieve the template argument as an expression.
    315   Expr *getAsExpr() const {
    316     if (Kind != Expression)
    317       return 0;
    318 
    319     return reinterpret_cast<Expr *>(TypeOrValue);
    320   }
    321 
    322   /// \brief Iterator that traverses the elements of a template argument pack.
    323   typedef const TemplateArgument * pack_iterator;
    324 
    325   /// \brief Iterator referencing the first argument of a template argument
    326   /// pack.
    327   pack_iterator pack_begin() const {
    328     assert(Kind == Pack);
    329     return Args.Args;
    330   }
    331 
    332   /// \brief Iterator referencing one past the last argument of a template
    333   /// argument pack.
    334   pack_iterator pack_end() const {
    335     assert(Kind == Pack);
    336     return Args.Args + Args.NumArgs;
    337   }
    338 
    339   /// \brief The number of template arguments in the given template argument
    340   /// pack.
    341   unsigned pack_size() const {
    342     assert(Kind == Pack);
    343     return Args.NumArgs;
    344   }
    345 
    346   /// Determines whether two template arguments are superficially the
    347   /// same.
    348   bool structurallyEquals(const TemplateArgument &Other) const;
    349 
    350   /// \brief When the template argument is a pack expansion, returns
    351   /// the pattern of the pack expansion.
    352   ///
    353   /// \param Ellipsis Will be set to the location of the ellipsis.
    354   TemplateArgument getPackExpansionPattern() const;
    355 
    356   /// \brief Print this template argument to the given output stream.
    357   void print(const PrintingPolicy &Policy, llvm::raw_ostream &Out) const;
    358 
    359   /// \brief Used to insert TemplateArguments into FoldingSets.
    360   void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
    361 };
    362 
    363 /// Location information for a TemplateArgument.
    364 struct TemplateArgumentLocInfo {
    365 private:
    366   union {
    367     Expr *Expression;
    368     TypeSourceInfo *Declarator;
    369     struct {
    370       // FIXME: We'd like to just use the qualifier in the TemplateName,
    371       // but template arguments get canonicalized too quickly.
    372       NestedNameSpecifier *Qualifier;
    373       void *QualifierLocData;
    374       unsigned TemplateNameLoc;
    375       unsigned EllipsisLoc;
    376     } Template;
    377   };
    378 
    379 public:
    380   TemplateArgumentLocInfo();
    381 
    382   TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
    383 
    384   TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
    385 
    386   TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc,
    387                           SourceLocation TemplateNameLoc,
    388                           SourceLocation EllipsisLoc)
    389   {
    390     Template.Qualifier = QualifierLoc.getNestedNameSpecifier();
    391     Template.QualifierLocData = QualifierLoc.getOpaqueData();
    392     Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
    393     Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
    394   }
    395 
    396   TypeSourceInfo *getAsTypeSourceInfo() const {
    397     return Declarator;
    398   }
    399 
    400   Expr *getAsExpr() const {
    401     return Expression;
    402   }
    403 
    404   NestedNameSpecifierLoc getTemplateQualifierLoc() const {
    405     return NestedNameSpecifierLoc(Template.Qualifier,
    406                                   Template.QualifierLocData);
    407   }
    408 
    409   SourceLocation getTemplateNameLoc() const {
    410     return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
    411   }
    412 
    413   SourceLocation getTemplateEllipsisLoc() const {
    414     return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
    415   }
    416 };
    417 
    418 /// Location wrapper for a TemplateArgument.  TemplateArgument is to
    419 /// TemplateArgumentLoc as Type is to TypeLoc.
    420 class TemplateArgumentLoc {
    421   TemplateArgument Argument;
    422   TemplateArgumentLocInfo LocInfo;
    423 
    424 public:
    425   TemplateArgumentLoc() {}
    426 
    427   TemplateArgumentLoc(const TemplateArgument &Argument,
    428                       TemplateArgumentLocInfo Opaque)
    429     : Argument(Argument), LocInfo(Opaque) {
    430   }
    431 
    432   TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
    433     : Argument(Argument), LocInfo(TInfo) {
    434     assert(Argument.getKind() == TemplateArgument::Type);
    435   }
    436 
    437   TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
    438     : Argument(Argument), LocInfo(E) {
    439     assert(Argument.getKind() == TemplateArgument::Expression);
    440   }
    441 
    442   TemplateArgumentLoc(const TemplateArgument &Argument,
    443                       NestedNameSpecifierLoc QualifierLoc,
    444                       SourceLocation TemplateNameLoc,
    445                       SourceLocation EllipsisLoc = SourceLocation())
    446     : Argument(Argument), LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) {
    447     assert(Argument.getKind() == TemplateArgument::Template ||
    448            Argument.getKind() == TemplateArgument::TemplateExpansion);
    449   }
    450 
    451   /// \brief - Fetches the primary location of the argument.
    452   SourceLocation getLocation() const {
    453     if (Argument.getKind() == TemplateArgument::Template ||
    454         Argument.getKind() == TemplateArgument::TemplateExpansion)
    455       return getTemplateNameLoc();
    456 
    457     return getSourceRange().getBegin();
    458   }
    459 
    460   /// \brief - Fetches the full source range of the argument.
    461   SourceRange getSourceRange() const;
    462 
    463   const TemplateArgument &getArgument() const {
    464     return Argument;
    465   }
    466 
    467   TemplateArgumentLocInfo getLocInfo() const {
    468     return LocInfo;
    469   }
    470 
    471   TypeSourceInfo *getTypeSourceInfo() const {
    472     assert(Argument.getKind() == TemplateArgument::Type);
    473     return LocInfo.getAsTypeSourceInfo();
    474   }
    475 
    476   Expr *getSourceExpression() const {
    477     assert(Argument.getKind() == TemplateArgument::Expression);
    478     return LocInfo.getAsExpr();
    479   }
    480 
    481   Expr *getSourceDeclExpression() const {
    482     assert(Argument.getKind() == TemplateArgument::Declaration);
    483     return LocInfo.getAsExpr();
    484   }
    485 
    486   NestedNameSpecifierLoc getTemplateQualifierLoc() const {
    487     assert(Argument.getKind() == TemplateArgument::Template ||
    488            Argument.getKind() == TemplateArgument::TemplateExpansion);
    489     return LocInfo.getTemplateQualifierLoc();
    490   }
    491 
    492   SourceLocation getTemplateNameLoc() const {
    493     assert(Argument.getKind() == TemplateArgument::Template ||
    494            Argument.getKind() == TemplateArgument::TemplateExpansion);
    495     return LocInfo.getTemplateNameLoc();
    496   }
    497 
    498   SourceLocation getTemplateEllipsisLoc() const {
    499     assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
    500     return LocInfo.getTemplateEllipsisLoc();
    501   }
    502 
    503   /// \brief When the template argument is a pack expansion, returns
    504   /// the pattern of the pack expansion.
    505   ///
    506   /// \param Ellipsis Will be set to the location of the ellipsis.
    507   ///
    508   /// \param NumExpansions Will be set to the number of expansions that will
    509   /// be generated from this pack expansion, if known a priori.
    510   TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis,
    511                                         llvm::Optional<unsigned> &NumExpansions,
    512                                               ASTContext &Context) const;
    513 };
    514 
    515 /// A convenient class for passing around template argument
    516 /// information.  Designed to be passed by reference.
    517 class TemplateArgumentListInfo {
    518   llvm::SmallVector<TemplateArgumentLoc, 8> Arguments;
    519   SourceLocation LAngleLoc;
    520   SourceLocation RAngleLoc;
    521 
    522 public:
    523   TemplateArgumentListInfo() {}
    524 
    525   TemplateArgumentListInfo(SourceLocation LAngleLoc,
    526                            SourceLocation RAngleLoc)
    527     : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
    528 
    529   SourceLocation getLAngleLoc() const { return LAngleLoc; }
    530   SourceLocation getRAngleLoc() const { return RAngleLoc; }
    531 
    532   void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
    533   void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
    534 
    535   unsigned size() const { return Arguments.size(); }
    536 
    537   const TemplateArgumentLoc *getArgumentArray() const {
    538     return Arguments.data();
    539   }
    540 
    541   const TemplateArgumentLoc &operator[](unsigned I) const {
    542     return Arguments[I];
    543   }
    544 
    545   void addArgument(const TemplateArgumentLoc &Loc) {
    546     Arguments.push_back(Loc);
    547   }
    548 };
    549 
    550 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
    551                                     const TemplateArgument &Arg);
    552 
    553 inline TemplateSpecializationType::iterator
    554     TemplateSpecializationType::end() const {
    555   return getArgs() + getNumArgs();
    556 }
    557 
    558 inline DependentTemplateSpecializationType::iterator
    559     DependentTemplateSpecializationType::end() const {
    560   return getArgs() + getNumArgs();
    561 }
    562 
    563 inline const TemplateArgument &
    564     TemplateSpecializationType::getArg(unsigned Idx) const {
    565   assert(Idx < getNumArgs() && "Template argument out of range");
    566   return getArgs()[Idx];
    567 }
    568 
    569 inline const TemplateArgument &
    570     DependentTemplateSpecializationType::getArg(unsigned Idx) const {
    571   assert(Idx < getNumArgs() && "Template argument out of range");
    572   return getArgs()[Idx];
    573 }
    574 
    575 } // end namespace clang
    576 
    577 #endif
    578