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()), 67 SS(SS), Loc(TemplateLoc), EllipsisLoc() { } 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 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() { 194 return getTrailingObjects<ParsedTemplateArgument>(); 195 } 196 197 /// Creates a new TemplateIdAnnotation with NumArgs arguments and 198 /// appends it to List. 199 static TemplateIdAnnotation * Createfinal200 Create(SourceLocation TemplateKWLoc, SourceLocation TemplateNameLoc, 201 IdentifierInfo *Name, OverloadedOperatorKind OperatorKind, 202 ParsedTemplateTy OpaqueTemplateName, TemplateNameKind TemplateKind, 203 SourceLocation LAngleLoc, SourceLocation RAngleLoc, 204 ArrayRef<ParsedTemplateArgument> TemplateArgs, bool ArgsInvalid, 205 SmallVectorImpl<TemplateIdAnnotation *> &CleanupList) { 206 TemplateIdAnnotation *TemplateId = new (llvm::safe_malloc( 207 totalSizeToAlloc<ParsedTemplateArgument>(TemplateArgs.size()))) 208 TemplateIdAnnotation(TemplateKWLoc, TemplateNameLoc, Name, 209 OperatorKind, OpaqueTemplateName, TemplateKind, 210 LAngleLoc, RAngleLoc, TemplateArgs, ArgsInvalid); 211 CleanupList.push_back(TemplateId); 212 return TemplateId; 213 } 214 Destroyfinal215 void Destroy() { 216 std::for_each( 217 getTemplateArgs(), getTemplateArgs() + NumArgs, 218 [](ParsedTemplateArgument &A) { A.~ParsedTemplateArgument(); }); 219 this->~TemplateIdAnnotation(); 220 free(this); 221 } 222 223 /// Determine whether this might be a type template. mightBeTypefinal224 bool mightBeType() const { 225 return Kind == TNK_Non_template || 226 Kind == TNK_Type_template || 227 Kind == TNK_Dependent_template_name || 228 Kind == TNK_Undeclared_template; 229 } 230 hasInvalidNamefinal231 bool hasInvalidName() const { return Kind == TNK_Non_template; } hasInvalidArgsfinal232 bool hasInvalidArgs() const { return ArgsInvalid; } 233 isInvalidfinal234 bool isInvalid() const { return hasInvalidName() || hasInvalidArgs(); } 235 236 private: 237 TemplateIdAnnotation(const TemplateIdAnnotation &) = delete; 238 TemplateIdAnnotationfinal239 TemplateIdAnnotation(SourceLocation TemplateKWLoc, 240 SourceLocation TemplateNameLoc, IdentifierInfo *Name, 241 OverloadedOperatorKind OperatorKind, 242 ParsedTemplateTy OpaqueTemplateName, 243 TemplateNameKind TemplateKind, 244 SourceLocation LAngleLoc, SourceLocation RAngleLoc, 245 ArrayRef<ParsedTemplateArgument> TemplateArgs, 246 bool ArgsInvalid) noexcept 247 : TemplateKWLoc(TemplateKWLoc), TemplateNameLoc(TemplateNameLoc), 248 Name(Name), Operator(OperatorKind), Template(OpaqueTemplateName), 249 Kind(TemplateKind), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc), 250 NumArgs(TemplateArgs.size()), ArgsInvalid(ArgsInvalid) { 251 252 std::uninitialized_copy(TemplateArgs.begin(), TemplateArgs.end(), 253 getTemplateArgs()); 254 } 255 ~TemplateIdAnnotation() = default; 256 }; 257 258 /// Retrieves the range of the given template parameter lists. 259 SourceRange getTemplateParamsRange(TemplateParameterList const *const *Params, 260 unsigned NumParams); 261 } // end namespace clang 262 263 #endif // LLVM_CLANG_SEMA_PARSEDTEMPLATE_H 264