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