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