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(P: 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(P: 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 Sz: totalSizeToAlloc<ParsedTemplateArgument>(Counts: TemplateArgs.size())))
207 TemplateIdAnnotation(TemplateKWLoc, TemplateNameLoc, Name,
208 OperatorKind, OpaqueTemplateName, TemplateKind,
209 LAngleLoc, RAngleLoc, TemplateArgs, ArgsInvalid);
210 CleanupList.push_back(Elt: TemplateId);
211 return TemplateId;
212 }
213
214 void Destroy() {
215 for (ParsedTemplateArgument &A :
216 llvm::make_range(x: getTemplateArgs(), y: getTemplateArgs() + NumArgs))
217 A.~ParsedTemplateArgument();
218 this->~TemplateIdAnnotation();
219 free(ptr: 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(first: TemplateArgs.begin(), last: TemplateArgs.end(),
252 result: 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

source code of clang/include/clang/Sema/ParsedTemplate.h