1 //===- TemplateName.cpp - C++ Template Name Representation ----------------===// 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 defines the TemplateName interface and subclasses. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/AST/TemplateName.h" 14 #include "clang/AST/Decl.h" 15 #include "clang/AST/DeclBase.h" 16 #include "clang/AST/DeclCXX.h" 17 #include "clang/AST/DeclTemplate.h" 18 #include "clang/AST/DependenceFlags.h" 19 #include "clang/AST/NestedNameSpecifier.h" 20 #include "clang/AST/PrettyPrinter.h" 21 #include "clang/AST/TemplateBase.h" 22 #include "clang/Basic/Diagnostic.h" 23 #include "clang/Basic/LLVM.h" 24 #include "clang/Basic/LangOptions.h" 25 #include "clang/Basic/OperatorKinds.h" 26 #include "llvm/ADT/ArrayRef.h" 27 #include "llvm/ADT/FoldingSet.h" 28 #include "llvm/Support/Compiler.h" 29 #include "llvm/Support/raw_ostream.h" 30 #include <cassert> 31 #include <optional> 32 #include <string> 33 34 using namespace clang; 35 36 DeducedTemplateStorage::DeducedTemplateStorage(TemplateName Underlying, 37 const DefaultArguments &DefArgs) 38 : UncommonTemplateNameStorage(Deduced, /*Index=*/DefArgs.StartPos, 39 DefArgs.Args.size()), 40 Underlying(Underlying) { 41 llvm::copy(DefArgs.Args, reinterpret_cast<TemplateArgument *>(this + 1)); 42 } 43 44 void DeducedTemplateStorage::Profile(llvm::FoldingSetNodeID &ID, 45 const ASTContext &Context) const { 46 Profile(ID, Context, Underlying, getDefaultArguments()); 47 } 48 49 void DeducedTemplateStorage::Profile(llvm::FoldingSetNodeID &ID, 50 const ASTContext &Context, 51 TemplateName Underlying, 52 const DefaultArguments &DefArgs) { 53 Underlying.Profile(ID); 54 ID.AddInteger(DefArgs.StartPos); 55 ID.AddInteger(DefArgs.Args.size()); 56 for (const TemplateArgument &Arg : DefArgs.Args) 57 Arg.Profile(ID, Context); 58 } 59 60 TemplateArgument 61 SubstTemplateTemplateParmPackStorage::getArgumentPack() const { 62 return TemplateArgument(llvm::ArrayRef(Arguments, Bits.Data)); 63 } 64 65 TemplateTemplateParmDecl * 66 SubstTemplateTemplateParmPackStorage::getParameterPack() const { 67 return cast<TemplateTemplateParmDecl>( 68 getReplacedTemplateParameterList(getAssociatedDecl()) 69 ->asArray()[Bits.Index]); 70 } 71 72 TemplateTemplateParmDecl * 73 SubstTemplateTemplateParmStorage::getParameter() const { 74 return cast<TemplateTemplateParmDecl>( 75 getReplacedTemplateParameterList(getAssociatedDecl()) 76 ->asArray()[Bits.Index]); 77 } 78 79 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) { 80 Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex()); 81 } 82 83 void SubstTemplateTemplateParmStorage::Profile( 84 llvm::FoldingSetNodeID &ID, TemplateName Replacement, Decl *AssociatedDecl, 85 unsigned Index, std::optional<unsigned> PackIndex) { 86 Replacement.Profile(ID); 87 ID.AddPointer(AssociatedDecl); 88 ID.AddInteger(Index); 89 ID.AddInteger(PackIndex ? *PackIndex + 1 : 0); 90 } 91 92 SubstTemplateTemplateParmPackStorage::SubstTemplateTemplateParmPackStorage( 93 ArrayRef<TemplateArgument> ArgPack, Decl *AssociatedDecl, unsigned Index, 94 bool Final) 95 : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index, 96 ArgPack.size()), 97 Arguments(ArgPack.data()), AssociatedDeclAndFinal(AssociatedDecl, Final) { 98 assert(AssociatedDecl != nullptr); 99 } 100 101 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, 102 ASTContext &Context) { 103 Profile(ID, Context, getArgumentPack(), getAssociatedDecl(), getIndex(), 104 getFinal()); 105 } 106 107 Decl *SubstTemplateTemplateParmPackStorage::getAssociatedDecl() const { 108 return AssociatedDeclAndFinal.getPointer(); 109 } 110 111 bool SubstTemplateTemplateParmPackStorage::getFinal() const { 112 return AssociatedDeclAndFinal.getInt(); 113 } 114 115 void SubstTemplateTemplateParmPackStorage::Profile( 116 llvm::FoldingSetNodeID &ID, ASTContext &Context, 117 const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index, 118 bool Final) { 119 ArgPack.Profile(ID, Context); 120 ID.AddPointer(AssociatedDecl); 121 ID.AddInteger(Index); 122 ID.AddBoolean(Final); 123 } 124 125 TemplateName::TemplateName(void *Ptr) { 126 Storage = StorageType::getFromOpaqueValue(Ptr); 127 } 128 129 TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {} 130 TemplateName::TemplateName(OverloadedTemplateStorage *Storage) 131 : Storage(Storage) {} 132 TemplateName::TemplateName(AssumedTemplateStorage *Storage) 133 : Storage(Storage) {} 134 TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage) 135 : Storage(Storage) {} 136 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage) 137 : Storage(Storage) {} 138 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {} 139 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {} 140 TemplateName::TemplateName(UsingShadowDecl *Using) : Storage(Using) {} 141 TemplateName::TemplateName(DeducedTemplateStorage *Deduced) 142 : Storage(Deduced) {} 143 144 bool TemplateName::isNull() const { return Storage.isNull(); } 145 146 TemplateName::NameKind TemplateName::getKind() const { 147 if (auto *ND = Storage.dyn_cast<Decl *>()) { 148 if (isa<UsingShadowDecl>(ND)) 149 return UsingTemplate; 150 assert(isa<TemplateDecl>(ND)); 151 return Template; 152 } 153 154 if (isa<DependentTemplateName *>(Storage)) 155 return DependentTemplate; 156 if (isa<QualifiedTemplateName *>(Storage)) 157 return QualifiedTemplate; 158 159 UncommonTemplateNameStorage *uncommon = 160 cast<UncommonTemplateNameStorage *>(Storage); 161 if (uncommon->getAsOverloadedStorage()) 162 return OverloadedTemplate; 163 if (uncommon->getAsAssumedTemplateName()) 164 return AssumedTemplate; 165 if (uncommon->getAsSubstTemplateTemplateParm()) 166 return SubstTemplateTemplateParm; 167 if (uncommon->getAsDeducedTemplateName()) 168 return DeducedTemplate; 169 170 assert(uncommon->getAsSubstTemplateTemplateParmPack() != nullptr); 171 return SubstTemplateTemplateParmPack; 172 } 173 174 TemplateDecl *TemplateName::getAsTemplateDecl(bool IgnoreDeduced) const { 175 TemplateName Name = *this; 176 while (std::optional<TemplateName> UnderlyingOrNone = 177 Name.desugar(IgnoreDeduced)) 178 Name = *UnderlyingOrNone; 179 180 if (!IgnoreDeduced) 181 assert(Name.getAsDeducedTemplateName() == nullptr && 182 "Unexpected canonical DeducedTemplateName; Did you mean to use " 183 "getTemplateDeclAndDefaultArgs instead?"); 184 185 return cast_if_present<TemplateDecl>( 186 dyn_cast_if_present<Decl *>(Name.Storage)); 187 } 188 189 std::pair<TemplateDecl *, DefaultArguments> 190 TemplateName::getTemplateDeclAndDefaultArgs() const { 191 for (TemplateName Name = *this; /**/; /**/) { 192 if (Name.getKind() == TemplateName::DeducedTemplate) { 193 DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); 194 TemplateDecl *TD = 195 DTS->getUnderlying().getAsTemplateDecl(/*IgnoreDeduced=*/true); 196 DefaultArguments DefArgs = DTS->getDefaultArguments(); 197 if (TD && DefArgs) 198 assert(DefArgs.StartPos + DefArgs.Args.size() <= 199 TD->getTemplateParameters()->size()); 200 return {TD, DTS->getDefaultArguments()}; 201 } 202 if (std::optional<TemplateName> UnderlyingOrNone = 203 Name.desugar(/*IgnoreDeduced=*/false)) { 204 Name = *UnderlyingOrNone; 205 continue; 206 } 207 return {cast_if_present<TemplateDecl>(Name.Storage.dyn_cast<Decl *>()), {}}; 208 } 209 } 210 211 std::optional<TemplateName> TemplateName::desugar(bool IgnoreDeduced) const { 212 if (Decl *D = dyn_cast_if_present<Decl *>(Storage)) { 213 if (auto *USD = dyn_cast<UsingShadowDecl>(D)) 214 return TemplateName(USD->getTargetDecl()); 215 return std::nullopt; 216 } 217 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) 218 return QTN->getUnderlyingTemplate(); 219 if (SubstTemplateTemplateParmStorage *S = getAsSubstTemplateTemplateParm()) 220 return S->getReplacement(); 221 if (IgnoreDeduced) 222 if (DeducedTemplateStorage *S = getAsDeducedTemplateName()) 223 return S->getUnderlying(); 224 return std::nullopt; 225 } 226 227 OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const { 228 if (UncommonTemplateNameStorage *Uncommon = 229 Storage.dyn_cast<UncommonTemplateNameStorage *>()) 230 return Uncommon->getAsOverloadedStorage(); 231 232 return nullptr; 233 } 234 235 AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const { 236 if (UncommonTemplateNameStorage *Uncommon = 237 Storage.dyn_cast<UncommonTemplateNameStorage *>()) 238 return Uncommon->getAsAssumedTemplateName(); 239 240 return nullptr; 241 } 242 243 SubstTemplateTemplateParmStorage * 244 TemplateName::getAsSubstTemplateTemplateParm() const { 245 if (UncommonTemplateNameStorage *uncommon = 246 dyn_cast_if_present<UncommonTemplateNameStorage *>(Storage)) 247 return uncommon->getAsSubstTemplateTemplateParm(); 248 249 return nullptr; 250 } 251 252 SubstTemplateTemplateParmPackStorage * 253 TemplateName::getAsSubstTemplateTemplateParmPack() const { 254 if (UncommonTemplateNameStorage *Uncommon = 255 Storage.dyn_cast<UncommonTemplateNameStorage *>()) 256 return Uncommon->getAsSubstTemplateTemplateParmPack(); 257 258 return nullptr; 259 } 260 261 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const { 262 return dyn_cast_if_present<QualifiedTemplateName *>(Storage); 263 } 264 265 DependentTemplateName *TemplateName::getAsDependentTemplateName() const { 266 return Storage.dyn_cast<DependentTemplateName *>(); 267 } 268 269 UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const { 270 if (Decl *D = Storage.dyn_cast<Decl *>()) 271 if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) 272 return USD; 273 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) 274 return QTN->getUnderlyingTemplate().getAsUsingShadowDecl(); 275 return nullptr; 276 } 277 278 DeducedTemplateStorage *TemplateName::getAsDeducedTemplateName() const { 279 if (UncommonTemplateNameStorage *Uncommon = 280 dyn_cast_if_present<UncommonTemplateNameStorage *>(Storage)) 281 return Uncommon->getAsDeducedTemplateName(); 282 283 return nullptr; 284 } 285 286 TemplateNameDependence TemplateName::getDependence() const { 287 switch (getKind()) { 288 case NameKind::Template: 289 case NameKind::UsingTemplate: { 290 TemplateDecl *Template = getAsTemplateDecl(); 291 auto D = TemplateNameDependence::None; 292 if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) { 293 D |= TemplateNameDependence::DependentInstantiation; 294 if (TTP->isParameterPack()) 295 D |= TemplateNameDependence::UnexpandedPack; 296 } 297 // FIXME: Hack, getDeclContext() can be null if Template is still 298 // initializing due to PCH reading, so we check it before using it. 299 // Should probably modify TemplateSpecializationType to allow constructing 300 // it without the isDependent() checking. 301 if (Template->getDeclContext() && 302 Template->getDeclContext()->isDependentContext()) 303 D |= TemplateNameDependence::DependentInstantiation; 304 return D; 305 } 306 case NameKind::QualifiedTemplate: { 307 QualifiedTemplateName *S = getAsQualifiedTemplateName(); 308 TemplateNameDependence D = S->getUnderlyingTemplate().getDependence(); 309 if (NestedNameSpecifier *NNS = S->getQualifier()) 310 D |= toTemplateNameDependence(NNS->getDependence()); 311 return D; 312 } 313 case NameKind::DependentTemplate: { 314 DependentTemplateName *S = getAsDependentTemplateName(); 315 auto D = TemplateNameDependence::DependentInstantiation; 316 D |= toTemplateNameDependence(S->getQualifier()->getDependence()); 317 return D; 318 } 319 case NameKind::SubstTemplateTemplateParm: { 320 auto *S = getAsSubstTemplateTemplateParm(); 321 return S->getReplacement().getDependence(); 322 } 323 case NameKind::SubstTemplateTemplateParmPack: 324 return TemplateNameDependence::UnexpandedPack | 325 TemplateNameDependence::DependentInstantiation; 326 case NameKind::DeducedTemplate: { 327 DeducedTemplateStorage *DTS = getAsDeducedTemplateName(); 328 TemplateNameDependence D = DTS->getUnderlying().getDependence(); 329 for (const TemplateArgument &Arg : DTS->getDefaultArguments().Args) 330 D |= toTemplateNameDependence(Arg.getDependence()); 331 return D; 332 } 333 case NameKind::AssumedTemplate: 334 return TemplateNameDependence::DependentInstantiation; 335 case NameKind::OverloadedTemplate: 336 llvm_unreachable("overloaded templates shouldn't survive to here."); 337 } 338 llvm_unreachable("Unknown TemplateName kind"); 339 } 340 341 bool TemplateName::isDependent() const { 342 return getDependence() & TemplateNameDependence::Dependent; 343 } 344 345 bool TemplateName::isInstantiationDependent() const { 346 return getDependence() & TemplateNameDependence::Instantiation; 347 } 348 349 bool TemplateName::containsUnexpandedParameterPack() const { 350 return getDependence() & TemplateNameDependence::UnexpandedPack; 351 } 352 353 void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, 354 Qualified Qual) const { 355 auto handleAnonymousTTP = [](TemplateDecl *TD, raw_ostream &OS) { 356 if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(TD); 357 TTP && TTP->getIdentifier() == nullptr) { 358 OS << "template-parameter-" << TTP->getDepth() << "-" << TTP->getIndex(); 359 return true; 360 } 361 return false; 362 }; 363 if (NameKind Kind = getKind(); 364 Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) { 365 // After `namespace ns { using std::vector }`, what is the fully-qualified 366 // name of the UsingTemplateName `vector` within ns? 367 // 368 // - ns::vector (the qualified name of the using-shadow decl) 369 // - std::vector (the qualified name of the underlying template decl) 370 // 371 // Similar to the UsingType behavior, using declarations are used to import 372 // names more often than to export them, thus using the original name is 373 // most useful in this case. 374 TemplateDecl *Template = getAsTemplateDecl(); 375 if (handleAnonymousTTP(Template, OS)) 376 return; 377 if (Qual == Qualified::None) 378 OS << *Template; 379 else 380 Template->printQualifiedName(OS, Policy); 381 } else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { 382 if (NestedNameSpecifier *NNS = QTN->getQualifier(); 383 Qual != Qualified::None && NNS) 384 NNS->print(OS, Policy); 385 if (QTN->hasTemplateKeyword()) 386 OS << "template "; 387 388 TemplateName Underlying = QTN->getUnderlyingTemplate(); 389 assert(Underlying.getKind() == TemplateName::Template || 390 Underlying.getKind() == TemplateName::UsingTemplate); 391 392 TemplateDecl *UTD = Underlying.getAsTemplateDecl(); 393 394 if (handleAnonymousTTP(UTD, OS)) 395 return; 396 397 if (IdentifierInfo *II = UTD->getIdentifier(); 398 Policy.CleanUglifiedParameters && II && 399 isa<TemplateTemplateParmDecl>(UTD)) 400 OS << II->deuglifiedName(); 401 else 402 OS << *UTD; 403 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { 404 if (NestedNameSpecifier *NNS = DTN->getQualifier()) 405 NNS->print(OS, Policy); 406 OS << "template "; 407 408 if (DTN->isIdentifier()) 409 OS << DTN->getIdentifier()->getName(); 410 else 411 OS << "operator " << getOperatorSpelling(DTN->getOperator()); 412 } else if (SubstTemplateTemplateParmStorage *subst = 413 getAsSubstTemplateTemplateParm()) { 414 subst->getReplacement().print(OS, Policy, Qual); 415 } else if (SubstTemplateTemplateParmPackStorage *SubstPack = 416 getAsSubstTemplateTemplateParmPack()) 417 OS << *SubstPack->getParameterPack(); 418 else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) { 419 Assumed->getDeclName().print(OS, Policy); 420 } else if (DeducedTemplateStorage *Deduced = getAsDeducedTemplateName()) { 421 Deduced->getUnderlying().print(OS, Policy); 422 DefaultArguments DefArgs = Deduced->getDefaultArguments(); 423 OS << ":" << DefArgs.StartPos; 424 printTemplateArgumentList(OS, DefArgs.Args, Policy); 425 } else { 426 assert(getKind() == TemplateName::OverloadedTemplate); 427 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); 428 (*OTS->begin())->printName(OS, Policy); 429 } 430 } 431 432 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB, 433 TemplateName N) { 434 std::string NameStr; 435 llvm::raw_string_ostream OS(NameStr); 436 LangOptions LO; 437 LO.CPlusPlus = true; 438 LO.Bool = true; 439 OS << '\''; 440 N.print(OS, PrintingPolicy(LO)); 441 OS << '\''; 442 return DB << NameStr; 443 } 444