Home | History | Annotate | Download | only in Sema
      1 //===--- ParsedTemplate.h - Template Parsing Data Types ---------*- 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 data structures that store the parsed representation of
     11 //  templates.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
     16 #define LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
     17 
     18 #include "clang/Basic/OperatorKinds.h"
     19 #include "clang/Basic/SourceLocation.h"
     20 #include "clang/Basic/TemplateKinds.h"
     21 #include "clang/Sema/DeclSpec.h"
     22 #include "clang/Sema/Ownership.h"
     23 #include "llvm/ADT/SmallVector.h"
     24 #include <cassert>
     25 #include <cstdlib>
     26 #include <new>
     27 
     28 namespace clang {
     29   /// \brief Represents the parsed form of a C++ template argument.
     30   class ParsedTemplateArgument {
     31   public:
     32     /// \brief Describes the kind of template argument that was parsed.
     33     enum KindType {
     34       /// \brief A template type parameter, stored as a type.
     35       Type,
     36       /// \brief A non-type template parameter, stored as an expression.
     37       NonType,
     38       /// \brief A template template argument, stored as a template name.
     39       Template
     40     };
     41 
     42     /// \brief Build an empty template argument.
     43     ///
     44     /// This template argument is invalid.
     45     ParsedTemplateArgument() : Kind(Type), Arg(nullptr) { }
     46 
     47     /// \brief Create a template type argument or non-type template argument.
     48     ///
     49     /// \param Arg the template type argument or non-type template argument.
     50     /// \param Loc the location of the type.
     51     ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc)
     52       : Kind(Kind), Arg(Arg), Loc(Loc) { }
     53 
     54     /// \brief Create a template template argument.
     55     ///
     56     /// \param SS the C++ scope specifier that precedes the template name, if
     57     /// any.
     58     ///
     59     /// \param Template the template to which this template template
     60     /// argument refers.
     61     ///
     62     /// \param TemplateLoc the location of the template name.
     63     ParsedTemplateArgument(const CXXScopeSpec &SS,
     64                            ParsedTemplateTy Template,
     65                            SourceLocation TemplateLoc)
     66       : Kind(ParsedTemplateArgument::Template),
     67         Arg(Template.getAsOpaquePtr()),
     68         SS(SS), Loc(TemplateLoc), EllipsisLoc() { }
     69 
     70     /// \brief Determine whether the given template argument is invalid.
     71     bool isInvalid() const { return Arg == nullptr; }
     72 
     73     /// \brief Determine what kind of template argument we have.
     74     KindType getKind() const { return Kind; }
     75 
     76     /// \brief Retrieve the template type argument's type.
     77     ParsedType getAsType() const {
     78       assert(Kind == Type && "Not a template type argument");
     79       return ParsedType::getFromOpaquePtr(Arg);
     80     }
     81 
     82     /// \brief Retrieve the non-type template argument's expression.
     83     Expr *getAsExpr() const {
     84       assert(Kind == NonType && "Not a non-type template argument");
     85       return static_cast<Expr*>(Arg);
     86     }
     87 
     88     /// \brief Retrieve the template template argument's template name.
     89     ParsedTemplateTy getAsTemplate() const {
     90       assert(Kind == Template && "Not a template template argument");
     91       return ParsedTemplateTy::getFromOpaquePtr(Arg);
     92     }
     93 
     94     /// \brief Retrieve the location of the template argument.
     95     SourceLocation getLocation() const { return Loc; }
     96 
     97     /// \brief Retrieve the nested-name-specifier that precedes the template
     98     /// name in a template template argument.
     99     const CXXScopeSpec &getScopeSpec() const {
    100       assert(Kind == Template &&
    101              "Only template template arguments can have a scope specifier");
    102       return SS;
    103     }
    104 
    105     /// \brief Retrieve the location of the ellipsis that makes a template
    106     /// template argument into a pack expansion.
    107     SourceLocation getEllipsisLoc() const {
    108       assert(Kind == Template &&
    109              "Only template template arguments can have an ellipsis");
    110       return EllipsisLoc;
    111     }
    112 
    113     /// \brief Retrieve a pack expansion of the given template template
    114     /// argument.
    115     ///
    116     /// \param EllipsisLoc The location of the ellipsis.
    117     ParsedTemplateArgument getTemplatePackExpansion(
    118                                               SourceLocation EllipsisLoc) const;
    119 
    120   private:
    121     KindType Kind;
    122 
    123     /// \brief The actual template argument representation, which may be
    124     /// an \c Sema::TypeTy* (for a type), an Expr* (for an
    125     /// expression), or an Sema::TemplateTy (for a template).
    126     void *Arg;
    127 
    128     /// \brief The nested-name-specifier that can accompany a template template
    129     /// argument.
    130     CXXScopeSpec SS;
    131 
    132     /// \brief the location of the template argument.
    133     SourceLocation Loc;
    134 
    135     /// \brief The ellipsis location that can accompany a template template
    136     /// argument (turning it into a template template argument expansion).
    137     SourceLocation EllipsisLoc;
    138   };
    139 
    140   /// \brief Information about a template-id annotation
    141   /// token.
    142   ///
    143   /// A template-id annotation token contains the template declaration,
    144   /// template arguments, whether those template arguments were types,
    145   /// expressions, or template names, and the source locations for important
    146   /// tokens. All of the information about template arguments is allocated
    147   /// directly after this structure.
    148   struct TemplateIdAnnotation final
    149       : private llvm::TrailingObjects<TemplateIdAnnotation,
    150                                       ParsedTemplateArgument> {
    151     friend TrailingObjects;
    152     /// \brief The nested-name-specifier that precedes the template name.
    153     CXXScopeSpec SS;
    154 
    155     /// TemplateKWLoc - The location of the template keyword.
    156     /// For e.g. typename T::template Y<U>
    157     SourceLocation TemplateKWLoc;
    158 
    159     /// TemplateNameLoc - The location of the template name within the
    160     /// source.
    161     SourceLocation TemplateNameLoc;
    162 
    163     /// FIXME: Temporarily stores the name of a specialization
    164     IdentifierInfo *Name;
    165 
    166     /// FIXME: Temporarily stores the overloaded operator kind.
    167     OverloadedOperatorKind Operator;
    168 
    169     /// The declaration of the template corresponding to the
    170     /// template-name.
    171     ParsedTemplateTy Template;
    172 
    173     /// The kind of template that Template refers to.
    174     TemplateNameKind Kind;
    175 
    176     /// The location of the '<' before the template argument
    177     /// list.
    178     SourceLocation LAngleLoc;
    179 
    180     /// The location of the '>' after the template argument
    181     /// list.
    182     SourceLocation RAngleLoc;
    183 
    184     /// NumArgs - The number of template arguments.
    185     unsigned NumArgs;
    186 
    187     /// \brief Retrieves a pointer to the template arguments
    188     ParsedTemplateArgument *getTemplateArgs() {
    189       return getTrailingObjects<ParsedTemplateArgument>();
    190     }
    191 
    192     /// \brief Creates a new TemplateIdAnnotation with NumArgs arguments and
    193     /// appends it to List.
    194     static TemplateIdAnnotation *
    195     Create(CXXScopeSpec SS, SourceLocation TemplateKWLoc,
    196            SourceLocation TemplateNameLoc, IdentifierInfo *Name,
    197            OverloadedOperatorKind OperatorKind,
    198            ParsedTemplateTy OpaqueTemplateName, TemplateNameKind TemplateKind,
    199            SourceLocation LAngleLoc, SourceLocation RAngleLoc,
    200            ArrayRef<ParsedTemplateArgument> TemplateArgs,
    201            SmallVectorImpl<TemplateIdAnnotation *> &CleanupList) {
    202 
    203       TemplateIdAnnotation *TemplateId = new (std::malloc(
    204           totalSizeToAlloc<ParsedTemplateArgument>(TemplateArgs.size())))
    205           TemplateIdAnnotation(SS, TemplateKWLoc, TemplateNameLoc, Name,
    206                                OperatorKind, OpaqueTemplateName, TemplateKind,
    207                                LAngleLoc, RAngleLoc, TemplateArgs);
    208       CleanupList.push_back(TemplateId);
    209       return TemplateId;
    210     }
    211 
    212     void Destroy() {
    213       std::for_each(
    214           getTemplateArgs(), getTemplateArgs() + NumArgs,
    215           [](ParsedTemplateArgument &A) { A.~ParsedTemplateArgument(); });
    216       this->~TemplateIdAnnotation();
    217       free(this);
    218     }
    219   private:
    220     TemplateIdAnnotation(const TemplateIdAnnotation &) = delete;
    221 
    222     TemplateIdAnnotation(CXXScopeSpec SS, SourceLocation TemplateKWLoc,
    223                          SourceLocation TemplateNameLoc, IdentifierInfo *Name,
    224                          OverloadedOperatorKind OperatorKind,
    225                          ParsedTemplateTy OpaqueTemplateName,
    226                          TemplateNameKind TemplateKind,
    227                          SourceLocation LAngleLoc, SourceLocation RAngleLoc,
    228                          ArrayRef<ParsedTemplateArgument> TemplateArgs) noexcept
    229         : SS(SS), TemplateKWLoc(TemplateKWLoc),
    230           TemplateNameLoc(TemplateNameLoc), Name(Name), Operator(OperatorKind),
    231           Template(OpaqueTemplateName), Kind(TemplateKind),
    232           LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
    233           NumArgs(TemplateArgs.size()) {
    234 
    235       std::uninitialized_copy(TemplateArgs.begin(), TemplateArgs.end(),
    236                               getTemplateArgs());
    237     }
    238     ~TemplateIdAnnotation() = default;
    239   };
    240 
    241   /// Retrieves the range of the given template parameter lists.
    242   SourceRange getTemplateParamsRange(TemplateParameterList const *const *Params,
    243                                      unsigned NumParams);
    244 } // end namespace clang
    245 
    246 #endif // LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
    247