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