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->getTemplateDecl(); 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 return nullptr; 176 } 177 178 TemplateName TemplateName::getNameToSubstitute() const { 179 TemplateDecl *Decl = getAsTemplateDecl(); 180 181 // Substituting a dependent template name: preserve it as written. 182 if (!Decl) 183 return *this; 184 185 // If we have a template declaration, use the most recent non-friend 186 // declaration of that template. 187 Decl = cast<TemplateDecl>(Decl->getMostRecentDecl()); 188 while (Decl->getFriendObjectKind()) { 189 Decl = cast<TemplateDecl>(Decl->getPreviousDecl()); 190 assert(Decl && "all declarations of template are friends"); 191 } 192 return TemplateName(Decl); 193 } 194 195 TemplateNameDependence TemplateName::getDependence() const { 196 auto D = TemplateNameDependence::None; 197 switch (getKind()) { 198 case TemplateName::NameKind::QualifiedTemplate: 199 D |= toTemplateNameDependence( 200 getAsQualifiedTemplateName()->getQualifier()->getDependence()); 201 break; 202 case TemplateName::NameKind::DependentTemplate: 203 D |= toTemplateNameDependence( 204 getAsDependentTemplateName()->getQualifier()->getDependence()); 205 break; 206 case TemplateName::NameKind::SubstTemplateTemplateParmPack: 207 D |= TemplateNameDependence::UnexpandedPack; 208 break; 209 case TemplateName::NameKind::OverloadedTemplate: 210 llvm_unreachable("overloaded templates shouldn't survive to here."); 211 default: 212 break; 213 } 214 if (TemplateDecl *Template = getAsTemplateDecl()) { 215 if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) { 216 D |= TemplateNameDependence::DependentInstantiation; 217 if (TTP->isParameterPack()) 218 D |= TemplateNameDependence::UnexpandedPack; 219 } 220 // FIXME: Hack, getDeclContext() can be null if Template is still 221 // initializing due to PCH reading, so we check it before using it. 222 // Should probably modify TemplateSpecializationType to allow constructing 223 // it without the isDependent() checking. 224 if (Template->getDeclContext() && 225 Template->getDeclContext()->isDependentContext()) 226 D |= TemplateNameDependence::DependentInstantiation; 227 } else { 228 D |= TemplateNameDependence::DependentInstantiation; 229 } 230 return D; 231 } 232 233 bool TemplateName::isDependent() const { 234 return getDependence() & TemplateNameDependence::Dependent; 235 } 236 237 bool TemplateName::isInstantiationDependent() const { 238 return getDependence() & TemplateNameDependence::Instantiation; 239 } 240 241 bool TemplateName::containsUnexpandedParameterPack() const { 242 return getDependence() & TemplateNameDependence::UnexpandedPack; 243 } 244 245 void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, 246 Qualified Qual) const { 247 auto Kind = getKind(); 248 TemplateDecl *Template = nullptr; 249 if (Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) { 250 // After `namespace ns { using std::vector }`, what is the fully-qualified 251 // name of the UsingTemplateName `vector` within ns? 252 // 253 // - ns::vector (the qualified name of the using-shadow decl) 254 // - std::vector (the qualified name of the underlying template decl) 255 // 256 // Similar to the UsingType behavior, using declarations are used to import 257 // names more often than to export them, thus using the original name is 258 // most useful in this case. 259 Template = getAsTemplateDecl(); 260 } 261 262 if (Template) 263 if (Policy.CleanUglifiedParameters && 264 isa<TemplateTemplateParmDecl>(Template) && Template->getIdentifier()) 265 OS << Template->getIdentifier()->deuglifiedName(); 266 else if (Qual == Qualified::Fully && 267 getDependence() != 268 TemplateNameDependenceScope::DependentInstantiation) 269 Template->printQualifiedName(OS, Policy); 270 else 271 OS << *Template; 272 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { 273 if (Qual == Qualified::Fully && 274 getDependence() != 275 TemplateNameDependenceScope::DependentInstantiation) { 276 QTN->getTemplateDecl()->printQualifiedName(OS, Policy); 277 return; 278 } 279 if (Qual == Qualified::AsWritten) 280 QTN->getQualifier()->print(OS, Policy); 281 if (QTN->hasTemplateKeyword()) 282 OS << "template "; 283 OS << *QTN->getTemplateDecl(); 284 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { 285 if (Qual == Qualified::AsWritten && DTN->getQualifier()) 286 DTN->getQualifier()->print(OS, Policy); 287 OS << "template "; 288 289 if (DTN->isIdentifier()) 290 OS << DTN->getIdentifier()->getName(); 291 else 292 OS << "operator " << getOperatorSpelling(DTN->getOperator()); 293 } else if (SubstTemplateTemplateParmStorage *subst 294 = getAsSubstTemplateTemplateParm()) { 295 subst->getReplacement().print(OS, Policy, Qual); 296 } else if (SubstTemplateTemplateParmPackStorage *SubstPack 297 = getAsSubstTemplateTemplateParmPack()) 298 OS << *SubstPack->getParameterPack(); 299 else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) { 300 Assumed->getDeclName().print(OS, Policy); 301 } else { 302 assert(getKind() == TemplateName::OverloadedTemplate); 303 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); 304 (*OTS->begin())->printName(OS); 305 } 306 } 307 308 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB, 309 TemplateName N) { 310 std::string NameStr; 311 llvm::raw_string_ostream OS(NameStr); 312 LangOptions LO; 313 LO.CPlusPlus = true; 314 LO.Bool = true; 315 OS << '\''; 316 N.print(OS, PrintingPolicy(LO)); 317 OS << '\''; 318 OS.flush(); 319 return DB << NameStr; 320 } 321 322 void TemplateName::dump(raw_ostream &OS) const { 323 LangOptions LO; // FIXME! 324 LO.CPlusPlus = true; 325 LO.Bool = true; 326 print(OS, PrintingPolicy(LO)); 327 } 328 329 LLVM_DUMP_METHOD void TemplateName::dump() const { 330 dump(llvm::errs()); 331 } 332