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/Casting.h" 29 #include "llvm/Support/Compiler.h" 30 #include "llvm/Support/raw_ostream.h" 31 #include <cassert> 32 #include <optional> 33 #include <string> 34 35 using namespace clang; 36 37 TemplateArgument 38 SubstTemplateTemplateParmPackStorage::getArgumentPack() const { 39 return TemplateArgument(llvm::ArrayRef(Arguments, Bits.Data)); 40 } 41 42 TemplateTemplateParmDecl * 43 SubstTemplateTemplateParmPackStorage::getParameterPack() const { 44 return cast<TemplateTemplateParmDecl>( 45 getReplacedTemplateParameterList(getAssociatedDecl()) 46 ->asArray()[Bits.Index]); 47 } 48 49 TemplateTemplateParmDecl * 50 SubstTemplateTemplateParmStorage::getParameter() const { 51 return cast<TemplateTemplateParmDecl>( 52 getReplacedTemplateParameterList(getAssociatedDecl()) 53 ->asArray()[Bits.Index]); 54 } 55 56 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) { 57 Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex()); 58 } 59 60 void SubstTemplateTemplateParmStorage::Profile( 61 llvm::FoldingSetNodeID &ID, TemplateName Replacement, Decl *AssociatedDecl, 62 unsigned Index, std::optional<unsigned> PackIndex) { 63 Replacement.Profile(ID); 64 ID.AddPointer(AssociatedDecl); 65 ID.AddInteger(Index); 66 ID.AddInteger(PackIndex ? *PackIndex + 1 : 0); 67 } 68 69 SubstTemplateTemplateParmPackStorage::SubstTemplateTemplateParmPackStorage( 70 ArrayRef<TemplateArgument> ArgPack, Decl *AssociatedDecl, unsigned Index, 71 bool Final) 72 : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index, 73 ArgPack.size()), 74 Arguments(ArgPack.data()), AssociatedDeclAndFinal(AssociatedDecl, Final) { 75 assert(AssociatedDecl != nullptr); 76 } 77 78 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, 79 ASTContext &Context) { 80 Profile(ID, Context, getArgumentPack(), getAssociatedDecl(), getIndex(), 81 getFinal()); 82 } 83 84 Decl *SubstTemplateTemplateParmPackStorage::getAssociatedDecl() const { 85 return AssociatedDeclAndFinal.getPointer(); 86 } 87 88 bool SubstTemplateTemplateParmPackStorage::getFinal() const { 89 return AssociatedDeclAndFinal.getInt(); 90 } 91 92 void SubstTemplateTemplateParmPackStorage::Profile( 93 llvm::FoldingSetNodeID &ID, ASTContext &Context, 94 const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index, 95 bool Final) { 96 ArgPack.Profile(ID, Context); 97 ID.AddPointer(AssociatedDecl); 98 ID.AddInteger(Index); 99 ID.AddBoolean(Final); 100 } 101 102 TemplateName::TemplateName(void *Ptr) { 103 Storage = StorageType::getFromOpaqueValue(Ptr); 104 } 105 106 TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {} 107 TemplateName::TemplateName(OverloadedTemplateStorage *Storage) 108 : Storage(Storage) {} 109 TemplateName::TemplateName(AssumedTemplateStorage *Storage) 110 : Storage(Storage) {} 111 TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage) 112 : Storage(Storage) {} 113 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage) 114 : Storage(Storage) {} 115 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {} 116 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {} 117 TemplateName::TemplateName(UsingShadowDecl *Using) : Storage(Using) {} 118 119 bool TemplateName::isNull() const { return Storage.isNull(); } 120 121 TemplateName::NameKind TemplateName::getKind() const { 122 if (auto *ND = Storage.dyn_cast<Decl *>()) { 123 if (isa<UsingShadowDecl>(ND)) 124 return UsingTemplate; 125 assert(isa<TemplateDecl>(ND)); 126 return Template; 127 } 128 129 if (Storage.is<DependentTemplateName *>()) 130 return DependentTemplate; 131 if (Storage.is<QualifiedTemplateName *>()) 132 return QualifiedTemplate; 133 134 UncommonTemplateNameStorage *uncommon 135 = Storage.get<UncommonTemplateNameStorage*>(); 136 if (uncommon->getAsOverloadedStorage()) 137 return OverloadedTemplate; 138 if (uncommon->getAsAssumedTemplateName()) 139 return AssumedTemplate; 140 if (uncommon->getAsSubstTemplateTemplateParm()) 141 return SubstTemplateTemplateParm; 142 return SubstTemplateTemplateParmPack; 143 } 144 145 TemplateDecl *TemplateName::getAsTemplateDecl() const { 146 if (Decl *TemplateOrUsing = Storage.dyn_cast<Decl *>()) { 147 if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(TemplateOrUsing)) 148 return cast<TemplateDecl>(USD->getTargetDecl()); 149 150 assert(isa<TemplateDecl>(TemplateOrUsing)); 151 return cast<TemplateDecl>(TemplateOrUsing); 152 } 153 154 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) 155 return QTN->getUnderlyingTemplate().getAsTemplateDecl(); 156 157 if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm()) 158 return sub->getReplacement().getAsTemplateDecl(); 159 160 if (UsingShadowDecl *USD = getAsUsingShadowDecl()) 161 return cast<TemplateDecl>(USD->getTargetDecl()); 162 163 return nullptr; 164 } 165 166 OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const { 167 if (UncommonTemplateNameStorage *Uncommon = 168 Storage.dyn_cast<UncommonTemplateNameStorage *>()) 169 return Uncommon->getAsOverloadedStorage(); 170 171 return nullptr; 172 } 173 174 AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const { 175 if (UncommonTemplateNameStorage *Uncommon = 176 Storage.dyn_cast<UncommonTemplateNameStorage *>()) 177 return Uncommon->getAsAssumedTemplateName(); 178 179 return nullptr; 180 } 181 182 SubstTemplateTemplateParmStorage * 183 TemplateName::getAsSubstTemplateTemplateParm() const { 184 if (UncommonTemplateNameStorage *uncommon = 185 Storage.dyn_cast<UncommonTemplateNameStorage *>()) 186 return uncommon->getAsSubstTemplateTemplateParm(); 187 188 return nullptr; 189 } 190 191 SubstTemplateTemplateParmPackStorage * 192 TemplateName::getAsSubstTemplateTemplateParmPack() const { 193 if (UncommonTemplateNameStorage *Uncommon = 194 Storage.dyn_cast<UncommonTemplateNameStorage *>()) 195 return Uncommon->getAsSubstTemplateTemplateParmPack(); 196 197 return nullptr; 198 } 199 200 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const { 201 return Storage.dyn_cast<QualifiedTemplateName *>(); 202 } 203 204 DependentTemplateName *TemplateName::getAsDependentTemplateName() const { 205 return Storage.dyn_cast<DependentTemplateName *>(); 206 } 207 208 UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const { 209 if (Decl *D = Storage.dyn_cast<Decl *>()) 210 if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) 211 return USD; 212 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) 213 return QTN->getUnderlyingTemplate().getAsUsingShadowDecl(); 214 return nullptr; 215 } 216 217 TemplateNameDependence TemplateName::getDependence() const { 218 auto D = TemplateNameDependence::None; 219 switch (getKind()) { 220 case TemplateName::NameKind::QualifiedTemplate: 221 if (NestedNameSpecifier *NNS = getAsQualifiedTemplateName()->getQualifier()) 222 D |= toTemplateNameDependence(NNS->getDependence()); 223 break; 224 case TemplateName::NameKind::DependentTemplate: 225 D |= toTemplateNameDependence( 226 getAsDependentTemplateName()->getQualifier()->getDependence()); 227 break; 228 case TemplateName::NameKind::SubstTemplateTemplateParmPack: 229 D |= TemplateNameDependence::UnexpandedPack; 230 break; 231 case TemplateName::NameKind::OverloadedTemplate: 232 llvm_unreachable("overloaded templates shouldn't survive to here."); 233 default: 234 break; 235 } 236 if (TemplateDecl *Template = getAsTemplateDecl()) { 237 if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) { 238 D |= TemplateNameDependence::DependentInstantiation; 239 if (TTP->isParameterPack()) 240 D |= TemplateNameDependence::UnexpandedPack; 241 } 242 // FIXME: Hack, getDeclContext() can be null if Template is still 243 // initializing due to PCH reading, so we check it before using it. 244 // Should probably modify TemplateSpecializationType to allow constructing 245 // it without the isDependent() checking. 246 if (Template->getDeclContext() && 247 Template->getDeclContext()->isDependentContext()) 248 D |= TemplateNameDependence::DependentInstantiation; 249 } else { 250 D |= TemplateNameDependence::DependentInstantiation; 251 } 252 return D; 253 } 254 255 bool TemplateName::isDependent() const { 256 return getDependence() & TemplateNameDependence::Dependent; 257 } 258 259 bool TemplateName::isInstantiationDependent() const { 260 return getDependence() & TemplateNameDependence::Instantiation; 261 } 262 263 bool TemplateName::containsUnexpandedParameterPack() const { 264 return getDependence() & TemplateNameDependence::UnexpandedPack; 265 } 266 267 void TemplateName::Profile(llvm::FoldingSetNodeID &ID) { 268 if (const auto* USD = getAsUsingShadowDecl()) 269 ID.AddPointer(USD->getCanonicalDecl()); 270 else if (const auto *TD = getAsTemplateDecl()) 271 ID.AddPointer(TD->getCanonicalDecl()); 272 else 273 ID.AddPointer(Storage.getOpaqueValue()); 274 } 275 276 void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, 277 Qualified Qual) const { 278 auto handleAnonymousTTP = [](TemplateDecl *TD, raw_ostream &OS) { 279 if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(TD); 280 TTP && TTP->getIdentifier() == nullptr) { 281 OS << "template-parameter-" << TTP->getDepth() << "-" << TTP->getIndex(); 282 return true; 283 } 284 return false; 285 }; 286 if (NameKind Kind = getKind(); 287 Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) { 288 // After `namespace ns { using std::vector }`, what is the fully-qualified 289 // name of the UsingTemplateName `vector` within ns? 290 // 291 // - ns::vector (the qualified name of the using-shadow decl) 292 // - std::vector (the qualified name of the underlying template decl) 293 // 294 // Similar to the UsingType behavior, using declarations are used to import 295 // names more often than to export them, thus using the original name is 296 // most useful in this case. 297 TemplateDecl *Template = getAsTemplateDecl(); 298 if (handleAnonymousTTP(Template, OS)) 299 return; 300 if (Qual == Qualified::None) 301 OS << *Template; 302 else 303 Template->printQualifiedName(OS, Policy); 304 } else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { 305 if (NestedNameSpecifier *NNS = QTN->getQualifier(); 306 Qual != Qualified::None && NNS) 307 NNS->print(OS, Policy); 308 if (QTN->hasTemplateKeyword()) 309 OS << "template "; 310 311 TemplateName Underlying = QTN->getUnderlyingTemplate(); 312 assert(Underlying.getKind() == TemplateName::Template || 313 Underlying.getKind() == TemplateName::UsingTemplate); 314 315 TemplateDecl *UTD = Underlying.getAsTemplateDecl(); 316 317 if (handleAnonymousTTP(UTD, OS)) 318 return; 319 320 if (IdentifierInfo *II = UTD->getIdentifier(); 321 Policy.CleanUglifiedParameters && II && 322 isa<TemplateTemplateParmDecl>(UTD)) 323 OS << II->deuglifiedName(); 324 else 325 OS << *UTD; 326 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { 327 if (NestedNameSpecifier *NNS = DTN->getQualifier()) 328 NNS->print(OS, Policy); 329 OS << "template "; 330 331 if (DTN->isIdentifier()) 332 OS << DTN->getIdentifier()->getName(); 333 else 334 OS << "operator " << getOperatorSpelling(DTN->getOperator()); 335 } else if (SubstTemplateTemplateParmStorage *subst = 336 getAsSubstTemplateTemplateParm()) { 337 subst->getReplacement().print(OS, Policy, Qual); 338 } else if (SubstTemplateTemplateParmPackStorage *SubstPack = 339 getAsSubstTemplateTemplateParmPack()) 340 OS << *SubstPack->getParameterPack(); 341 else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) { 342 Assumed->getDeclName().print(OS, Policy); 343 } else { 344 assert(getKind() == TemplateName::OverloadedTemplate); 345 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); 346 (*OTS->begin())->printName(OS, Policy); 347 } 348 } 349 350 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB, 351 TemplateName N) { 352 std::string NameStr; 353 llvm::raw_string_ostream OS(NameStr); 354 LangOptions LO; 355 LO.CPlusPlus = true; 356 LO.Bool = true; 357 OS << '\''; 358 N.print(OS, PrintingPolicy(LO)); 359 OS << '\''; 360 OS.flush(); 361 return DB << NameStr; 362 } 363