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