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 TemplateName TemplateName::getNameToSubstitute() const { 218 TemplateDecl *Decl = getAsTemplateDecl(); 219 220 // Substituting a dependent template name: preserve it as written. 221 if (!Decl) 222 return *this; 223 224 // If we have a template declaration, use the most recent non-friend 225 // declaration of that template. 226 Decl = cast<TemplateDecl>(Decl->getMostRecentDecl()); 227 while (Decl->getFriendObjectKind()) { 228 Decl = cast<TemplateDecl>(Decl->getPreviousDecl()); 229 assert(Decl && "all declarations of template are friends"); 230 } 231 return TemplateName(Decl); 232 } 233 234 TemplateNameDependence TemplateName::getDependence() const { 235 auto D = TemplateNameDependence::None; 236 switch (getKind()) { 237 case TemplateName::NameKind::QualifiedTemplate: 238 D |= toTemplateNameDependence( 239 getAsQualifiedTemplateName()->getQualifier()->getDependence()); 240 break; 241 case TemplateName::NameKind::DependentTemplate: 242 D |= toTemplateNameDependence( 243 getAsDependentTemplateName()->getQualifier()->getDependence()); 244 break; 245 case TemplateName::NameKind::SubstTemplateTemplateParmPack: 246 D |= TemplateNameDependence::UnexpandedPack; 247 break; 248 case TemplateName::NameKind::OverloadedTemplate: 249 llvm_unreachable("overloaded templates shouldn't survive to here."); 250 default: 251 break; 252 } 253 if (TemplateDecl *Template = getAsTemplateDecl()) { 254 if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) { 255 D |= TemplateNameDependence::DependentInstantiation; 256 if (TTP->isParameterPack()) 257 D |= TemplateNameDependence::UnexpandedPack; 258 } 259 // FIXME: Hack, getDeclContext() can be null if Template is still 260 // initializing due to PCH reading, so we check it before using it. 261 // Should probably modify TemplateSpecializationType to allow constructing 262 // it without the isDependent() checking. 263 if (Template->getDeclContext() && 264 Template->getDeclContext()->isDependentContext()) 265 D |= TemplateNameDependence::DependentInstantiation; 266 } else { 267 D |= TemplateNameDependence::DependentInstantiation; 268 } 269 return D; 270 } 271 272 bool TemplateName::isDependent() const { 273 return getDependence() & TemplateNameDependence::Dependent; 274 } 275 276 bool TemplateName::isInstantiationDependent() const { 277 return getDependence() & TemplateNameDependence::Instantiation; 278 } 279 280 bool TemplateName::containsUnexpandedParameterPack() const { 281 return getDependence() & TemplateNameDependence::UnexpandedPack; 282 } 283 284 void TemplateName::Profile(llvm::FoldingSetNodeID &ID) { 285 if (const auto* USD = getAsUsingShadowDecl()) 286 ID.AddPointer(USD->getCanonicalDecl()); 287 else if (const auto *TD = getAsTemplateDecl()) 288 ID.AddPointer(TD->getCanonicalDecl()); 289 else 290 ID.AddPointer(Storage.getOpaqueValue()); 291 } 292 293 void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, 294 Qualified Qual) const { 295 auto Kind = getKind(); 296 TemplateDecl *Template = nullptr; 297 if (Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) { 298 // After `namespace ns { using std::vector }`, what is the fully-qualified 299 // name of the UsingTemplateName `vector` within ns? 300 // 301 // - ns::vector (the qualified name of the using-shadow decl) 302 // - std::vector (the qualified name of the underlying template decl) 303 // 304 // Similar to the UsingType behavior, using declarations are used to import 305 // names more often than to export them, thus using the original name is 306 // most useful in this case. 307 Template = getAsTemplateDecl(); 308 } 309 310 if (Template) 311 if (Policy.CleanUglifiedParameters && 312 isa<TemplateTemplateParmDecl>(Template) && Template->getIdentifier()) 313 OS << Template->getIdentifier()->deuglifiedName(); 314 else if (Qual == Qualified::Fully && 315 getDependence() != 316 TemplateNameDependenceScope::DependentInstantiation) 317 Template->printQualifiedName(OS, Policy); 318 else 319 OS << *Template; 320 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { 321 if (Qual == Qualified::Fully && 322 getDependence() != 323 TemplateNameDependenceScope::DependentInstantiation) { 324 QTN->getUnderlyingTemplate().getAsTemplateDecl()->printQualifiedName( 325 OS, Policy); 326 return; 327 } 328 if (Qual == Qualified::AsWritten) 329 QTN->getQualifier()->print(OS, Policy); 330 if (QTN->hasTemplateKeyword()) 331 OS << "template "; 332 OS << *QTN->getUnderlyingTemplate().getAsTemplateDecl(); 333 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { 334 if (Qual == Qualified::AsWritten && DTN->getQualifier()) 335 DTN->getQualifier()->print(OS, Policy); 336 OS << "template "; 337 338 if (DTN->isIdentifier()) 339 OS << DTN->getIdentifier()->getName(); 340 else 341 OS << "operator " << getOperatorSpelling(DTN->getOperator()); 342 } else if (SubstTemplateTemplateParmStorage *subst 343 = getAsSubstTemplateTemplateParm()) { 344 subst->getReplacement().print(OS, Policy, Qual); 345 } else if (SubstTemplateTemplateParmPackStorage *SubstPack 346 = getAsSubstTemplateTemplateParmPack()) 347 OS << *SubstPack->getParameterPack(); 348 else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) { 349 Assumed->getDeclName().print(OS, Policy); 350 } else { 351 assert(getKind() == TemplateName::OverloadedTemplate); 352 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); 353 (*OTS->begin())->printName(OS, Policy); 354 } 355 } 356 357 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB, 358 TemplateName N) { 359 std::string NameStr; 360 llvm::raw_string_ostream OS(NameStr); 361 LangOptions LO; 362 LO.CPlusPlus = true; 363 LO.Bool = true; 364 OS << '\''; 365 N.print(OS, PrintingPolicy(LO)); 366 OS << '\''; 367 OS.flush(); 368 return DB << NameStr; 369 } 370 371 void TemplateName::dump(raw_ostream &OS) const { 372 LangOptions LO; // FIXME! 373 LO.CPlusPlus = true; 374 LO.Bool = true; 375 print(OS, PrintingPolicy(LO)); 376 } 377 378 LLVM_DUMP_METHOD void TemplateName::dump() const { 379 dump(llvm::errs()); 380 } 381