• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
28 namespace 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.
ParsedTemplateArgument()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.
ParsedTemplateArgument(KindType Kind,void * Arg,SourceLocation Loc)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.
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()),
68         SS(SS), Loc(TemplateLoc), EllipsisLoc() { }
69 
70     /// \brief Determine whether the given template argument is invalid.
isInvalid()71     bool isInvalid() const { return Arg == nullptr; }
72 
73     /// \brief Determine what kind of template argument we have.
getKind()74     KindType getKind() const { return Kind; }
75 
76     /// \brief Retrieve the template type argument's type.
getAsType()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.
getAsExpr()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.
getAsTemplate()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.
getLocation()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.
getScopeSpec()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.
getEllipsisLoc()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 {
149     /// \brief The nested-name-specifier that precedes the template name.
150     CXXScopeSpec SS;
151 
152     /// TemplateKWLoc - The location of the template keyword within the
153     /// source.
154     SourceLocation TemplateKWLoc;
155 
156     /// TemplateNameLoc - The location of the template name within the
157     /// source.
158     SourceLocation TemplateNameLoc;
159 
160     /// FIXME: Temporarily stores the name of a specialization
161     IdentifierInfo *Name;
162 
163     /// FIXME: Temporarily stores the overloaded operator kind.
164     OverloadedOperatorKind Operator;
165 
166     /// The declaration of the template corresponding to the
167     /// template-name.
168     ParsedTemplateTy Template;
169 
170     /// The kind of template that Template refers to.
171     TemplateNameKind Kind;
172 
173     /// The location of the '<' before the template argument
174     /// list.
175     SourceLocation LAngleLoc;
176 
177     /// The location of the '>' after the template argument
178     /// list.
179     SourceLocation RAngleLoc;
180 
181     /// NumArgs - The number of template arguments.
182     unsigned NumArgs;
183 
184     /// \brief Retrieves a pointer to the template arguments
getTemplateArgsTemplateIdAnnotation185     ParsedTemplateArgument *getTemplateArgs() {
186       return reinterpret_cast<ParsedTemplateArgument *>(this + 1);
187     }
188 
189     /// \brief Creates a new TemplateIdAnnotation with NumArgs arguments and
190     /// appends it to List.
191     static TemplateIdAnnotation *
AllocateTemplateIdAnnotation192     Allocate(unsigned NumArgs, SmallVectorImpl<TemplateIdAnnotation*> &List) {
193       TemplateIdAnnotation *TemplateId
194         = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
195                                       sizeof(ParsedTemplateArgument) * NumArgs);
196       TemplateId->NumArgs = NumArgs;
197 
198       // Default-construct nested-name-specifier.
199       new (&TemplateId->SS) CXXScopeSpec();
200 
201       // Default-construct parsed template arguments.
202       ParsedTemplateArgument *TemplateArgs = TemplateId->getTemplateArgs();
203       for (unsigned I = 0; I != NumArgs; ++I)
204         new (TemplateArgs + I) ParsedTemplateArgument();
205 
206       List.push_back(TemplateId);
207       return TemplateId;
208     }
209 
DestroyTemplateIdAnnotation210     void Destroy() {
211       SS.~CXXScopeSpec();
212       free(this);
213     }
214   };
215 
216   /// Retrieves the range of the given template parameter lists.
217   SourceRange getTemplateParamsRange(TemplateParameterList const *const *Params,
218                                      unsigned NumParams);
219 } // end namespace clang
220 
221 #endif // LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
222