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.
ParsedTemplateArgument()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.
ParsedTemplateArgument(KindType Kind,void * Arg,SourceLocation Loc)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.
ParsedTemplateArgument(const CXXScopeSpec & SS,ParsedTemplateTy Template,SourceLocation TemplateLoc)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.
isInvalid()69     bool isInvalid() const { return Arg == nullptr; }
70 
71     /// Determine what kind of template argument we have.
getKind()72     KindType getKind() const { return Kind; }
73 
74     /// Retrieve the template type argument's type.
getAsType()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.
getAsExpr()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.
getAsTemplate()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.
getLocation()93     SourceLocation getLocation() const { return Loc; }
94 
95     /// Retrieve the nested-name-specifier that precedes the template
96     /// name in a template template argument.
getScopeSpec()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.
getEllipsisLoc()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
getTemplateArgsfinal192     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 *
Createfinal199     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 
Destroyfinal214     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.
mightBeTypefinal223     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 
hasInvalidNamefinal230     bool hasInvalidName() const { return Kind == TNK_Non_template; }
hasInvalidArgsfinal231     bool hasInvalidArgs() const { return ArgsInvalid; }
232 
isInvalidfinal233     bool isInvalid() const { return hasInvalidName() || hasInvalidArgs(); }
234 
235   private:
236     TemplateIdAnnotation(const TemplateIdAnnotation &) = delete;
237 
TemplateIdAnnotationfinal238     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