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