xref: /freebsd/contrib/llvm-project/clang/include/clang/Sema/ParsedTemplate.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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/STLExtras.h"
23 #include "llvm/ADT/SmallVector.h"
24 #include <cassert>
25 #include <cstdlib>
26 #include <new>
27 
28 namespace clang {
29   /// Represents the parsed form of a C++ template argument.
30   class ParsedTemplateArgument {
31   public:
32     /// Describes the kind of template argument that was parsed.
33     enum KindType {
34       /// A template type parameter, stored as a type.
35       Type,
36       /// A non-type template parameter, stored as an expression.
37       NonType,
38       /// A template template argument, stored as a template name.
39       Template
40     };
41 
42     /// Build an empty template argument.
43     ///
44     /// This template argument is invalid.
ParsedTemplateArgument()45     ParsedTemplateArgument() : Kind(Type), Arg(nullptr) { }
46 
47     /// 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.
ParsedTemplateArgument(KindType Kind,void * Arg,SourceLocation Loc)51     ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc)
52       : Kind(Kind), Arg(Arg), Loc(Loc) { }
53 
54     /// 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.
ParsedTemplateArgument(const CXXScopeSpec & SS,ParsedTemplateTy Template,SourceLocation TemplateLoc)63     ParsedTemplateArgument(const CXXScopeSpec &SS,
64                            ParsedTemplateTy Template,
65                            SourceLocation TemplateLoc)
66       : Kind(ParsedTemplateArgument::Template),
67         Arg(Template.getAsOpaquePtr()), SS(SS), Loc(TemplateLoc) {}
68 
69     /// Determine whether the given template argument is invalid.
isInvalid()70     bool isInvalid() const { return Arg == nullptr; }
71 
72     /// Determine what kind of template argument we have.
getKind()73     KindType getKind() const { return Kind; }
74 
75     /// Retrieve the template type argument's type.
getAsType()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.
getAsExpr()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.
getAsTemplate()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.
getLocation()94     SourceLocation getLocation() const { return Loc; }
95 
96     /// Retrieve the nested-name-specifier that precedes the template
97     /// name in a template template argument.
getScopeSpec()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.
getEllipsisLoc()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     const 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
getTemplateArgsfinal193     ParsedTemplateArgument *getTemplateArgs() { return getTrailingObjects(); }
194 
195     /// Creates a new TemplateIdAnnotation with NumArgs arguments and
196     /// appends it to List.
197     static TemplateIdAnnotation *
Createfinal198     Create(SourceLocation TemplateKWLoc, SourceLocation TemplateNameLoc,
199            const IdentifierInfo *Name, OverloadedOperatorKind OperatorKind,
200            ParsedTemplateTy OpaqueTemplateName, TemplateNameKind TemplateKind,
201            SourceLocation LAngleLoc, SourceLocation RAngleLoc,
202            ArrayRef<ParsedTemplateArgument> TemplateArgs, bool ArgsInvalid,
203            SmallVectorImpl<TemplateIdAnnotation *> &CleanupList) {
204       TemplateIdAnnotation *TemplateId = new (llvm::safe_malloc(
205           totalSizeToAlloc<ParsedTemplateArgument>(TemplateArgs.size())))
206           TemplateIdAnnotation(TemplateKWLoc, TemplateNameLoc, Name,
207                                OperatorKind, OpaqueTemplateName, TemplateKind,
208                                LAngleLoc, RAngleLoc, TemplateArgs, ArgsInvalid);
209       CleanupList.push_back(TemplateId);
210       return TemplateId;
211     }
212 
Destroyfinal213     void Destroy() {
214       for (ParsedTemplateArgument &A :
215            llvm::make_range(getTemplateArgs(), getTemplateArgs() + NumArgs))
216         A.~ParsedTemplateArgument();
217       this->~TemplateIdAnnotation();
218       free(this);
219     }
220 
221     /// Determine whether this might be a type template.
mightBeTypefinal222     bool mightBeType() const {
223       return Kind == TNK_Non_template ||
224              Kind == TNK_Type_template ||
225              Kind == TNK_Dependent_template_name ||
226              Kind == TNK_Undeclared_template;
227     }
228 
hasInvalidNamefinal229     bool hasInvalidName() const { return Kind == TNK_Non_template; }
hasInvalidArgsfinal230     bool hasInvalidArgs() const { return ArgsInvalid; }
231 
isInvalidfinal232     bool isInvalid() const { return hasInvalidName() || hasInvalidArgs(); }
233 
234   private:
235     TemplateIdAnnotation(const TemplateIdAnnotation &) = delete;
236 
TemplateIdAnnotationfinal237     TemplateIdAnnotation(SourceLocation TemplateKWLoc,
238                          SourceLocation TemplateNameLoc,
239                          const 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       llvm::uninitialized_copy(TemplateArgs, getTemplateArgs());
252     }
253     ~TemplateIdAnnotation() = default;
254   };
255 
256   /// Retrieves the range of the given template parameter lists.
257   SourceRange getTemplateParamsRange(TemplateParameterList const *const *Params,
258                                      unsigned NumParams);
259 } // end namespace clang
260 
261 #endif // LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
262