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
28namespace 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