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
27namespace 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()), SS(SS), Loc(TemplateLoc) {}
67
68    /// Determine whether the given template argument is invalid.
69    bool isInvalid() const { return Arg == nullptr; }
70
71    /// Determine what kind of template argument we have.
72    KindType getKind() const { return Kind; }
73
74    /// Retrieve the template type argument's type.
75    ParsedType getAsType() const {
76      assert(Kind == Type && "Not a template type argument");
77      return ParsedType::getFromOpaquePtr(Arg);
78    }
79
80    /// Retrieve the non-type template argument's expression.
81    Expr *getAsExpr() const {
82      assert(Kind == NonType && "Not a non-type template argument");
83      return static_cast<Expr*>(Arg);
84    }
85
86    /// Retrieve the template template argument's template name.
87    ParsedTemplateTy getAsTemplate() const {
88      assert(Kind == Template && "Not a template template argument");
89      return ParsedTemplateTy::getFromOpaquePtr(Arg);
90    }
91
92    /// Retrieve the location of the template argument.
93    SourceLocation getLocation() const { return Loc; }
94
95    /// Retrieve the nested-name-specifier that precedes the template
96    /// name in a template template argument.
97    const CXXScopeSpec &getScopeSpec() const {
98      assert(Kind == Template &&
99             "Only template template arguments can have a scope specifier");
100      return SS;
101    }
102
103    /// Retrieve the location of the ellipsis that makes a template
104    /// template argument into a pack expansion.
105    SourceLocation getEllipsisLoc() const {
106      assert(Kind == Template &&
107             "Only template template arguments can have an ellipsis");
108      return EllipsisLoc;
109    }
110
111    /// Retrieve a pack expansion of the given template template
112    /// argument.
113    ///
114    /// \param EllipsisLoc The location of the ellipsis.
115    ParsedTemplateArgument getTemplatePackExpansion(
116                                              SourceLocation EllipsisLoc) const;
117
118  private:
119    KindType Kind;
120
121    /// The actual template argument representation, which may be
122    /// an \c Sema::TypeTy* (for a type), an Expr* (for an
123    /// expression), or an Sema::TemplateTy (for a template).
124    void *Arg;
125
126    /// The nested-name-specifier that can accompany a template template
127    /// argument.
128    CXXScopeSpec SS;
129
130    /// the location of the template argument.
131    SourceLocation Loc;
132
133    /// The ellipsis location that can accompany a template template
134    /// argument (turning it into a template template argument expansion).
135    SourceLocation EllipsisLoc;
136  };
137
138  /// Information about a template-id annotation
139  /// token.
140  ///
141  /// A template-id annotation token contains the template name,
142  /// template arguments, and the source locations for important
143  /// tokens. All of the information about template arguments is allocated
144  /// directly after this structure.
145  /// A template-id annotation token can also be generated by a type-constraint
146  /// construct with no explicit template arguments, e.g. "template<C T>" would
147  /// annotate C as a TemplateIdAnnotation with no template arguments (the angle
148  /// locations would be invalid in this case).
149  struct TemplateIdAnnotation final
150      : private llvm::TrailingObjects<TemplateIdAnnotation,
151                                      ParsedTemplateArgument> {
152    friend TrailingObjects;
153    /// TemplateKWLoc - The location of the template keyword.
154    /// For e.g. typename T::template Y<U>
155    SourceLocation TemplateKWLoc;
156
157    /// TemplateNameLoc - The location of the template name within the
158    /// source.
159    SourceLocation TemplateNameLoc;
160
161    /// FIXME: Temporarily stores the name of a specialization
162    IdentifierInfo *Name;
163
164    /// FIXME: Temporarily stores the overloaded operator kind.
165    OverloadedOperatorKind Operator;
166
167    /// The declaration of the template corresponding to the
168    /// template-name.
169    ParsedTemplateTy Template;
170
171    /// The kind of template that Template refers to. If this is
172    /// TNK_Non_template, an error was encountered and diagnosed
173    /// when parsing or looking up the template name.
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    /// Whether an error was encountered in the template arguments.
188    /// If so, NumArgs and the trailing arguments are best-effort.
189    bool ArgsInvalid;
190
191    /// Retrieves a pointer to the template arguments
192    ParsedTemplateArgument *getTemplateArgs() {
193      return getTrailingObjects<ParsedTemplateArgument>();
194    }
195
196    /// Creates a new TemplateIdAnnotation with NumArgs arguments and
197    /// appends it to List.
198    static TemplateIdAnnotation *
199    Create(SourceLocation TemplateKWLoc, SourceLocation TemplateNameLoc,
200           IdentifierInfo *Name, OverloadedOperatorKind OperatorKind,
201           ParsedTemplateTy OpaqueTemplateName, TemplateNameKind TemplateKind,
202           SourceLocation LAngleLoc, SourceLocation RAngleLoc,
203           ArrayRef<ParsedTemplateArgument> TemplateArgs, bool ArgsInvalid,
204           SmallVectorImpl<TemplateIdAnnotation *> &CleanupList) {
205      TemplateIdAnnotation *TemplateId = new (llvm::safe_malloc(
206          totalSizeToAlloc<ParsedTemplateArgument>(TemplateArgs.size())))
207          TemplateIdAnnotation(TemplateKWLoc, TemplateNameLoc, Name,
208                               OperatorKind, OpaqueTemplateName, TemplateKind,
209                               LAngleLoc, RAngleLoc, TemplateArgs, ArgsInvalid);
210      CleanupList.push_back(TemplateId);
211      return TemplateId;
212    }
213
214    void Destroy() {
215      for (ParsedTemplateArgument &A :
216           llvm::make_range(getTemplateArgs(), getTemplateArgs() + NumArgs))
217        A.~ParsedTemplateArgument();
218      this->~TemplateIdAnnotation();
219      free(this);
220    }
221
222    /// Determine whether this might be a type template.
223    bool mightBeType() const {
224      return Kind == TNK_Non_template ||
225             Kind == TNK_Type_template ||
226             Kind == TNK_Dependent_template_name ||
227             Kind == TNK_Undeclared_template;
228    }
229
230    bool hasInvalidName() const { return Kind == TNK_Non_template; }
231    bool hasInvalidArgs() const { return ArgsInvalid; }
232
233    bool isInvalid() const { return hasInvalidName() || hasInvalidArgs(); }
234
235  private:
236    TemplateIdAnnotation(const TemplateIdAnnotation &) = delete;
237
238    TemplateIdAnnotation(SourceLocation TemplateKWLoc,
239                         SourceLocation TemplateNameLoc, IdentifierInfo *Name,
240                         OverloadedOperatorKind OperatorKind,
241                         ParsedTemplateTy OpaqueTemplateName,
242                         TemplateNameKind TemplateKind,
243                         SourceLocation LAngleLoc, SourceLocation RAngleLoc,
244                         ArrayRef<ParsedTemplateArgument> TemplateArgs,
245                         bool ArgsInvalid) noexcept
246        : TemplateKWLoc(TemplateKWLoc), TemplateNameLoc(TemplateNameLoc),
247          Name(Name), Operator(OperatorKind), Template(OpaqueTemplateName),
248          Kind(TemplateKind), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
249          NumArgs(TemplateArgs.size()), ArgsInvalid(ArgsInvalid) {
250
251      std::uninitialized_copy(TemplateArgs.begin(), TemplateArgs.end(),
252                              getTemplateArgs());
253    }
254    ~TemplateIdAnnotation() = default;
255  };
256
257  /// Retrieves the range of the given template parameter lists.
258  SourceRange getTemplateParamsRange(TemplateParameterList const *const *Params,
259                                     unsigned NumParams);
260} // end namespace clang
261
262#endif // LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
263