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 224 TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, 225 bool SuppressNNS) const { 226 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) 227 OS << *Template; 228 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { 229 if (!SuppressNNS) 230 QTN->getQualifier()->print(OS, Policy); 231 if (QTN->hasTemplateKeyword()) 232 OS << "template "; 233 OS << *QTN->getDecl(); 234 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { 235 if (!SuppressNNS && DTN->getQualifier()) 236 DTN->getQualifier()->print(OS, Policy); 237 OS << "template "; 238 239 if (DTN->isIdentifier()) 240 OS << DTN->getIdentifier()->getName(); 241 else 242 OS << "operator " << getOperatorSpelling(DTN->getOperator()); 243 } else if (SubstTemplateTemplateParmStorage *subst 244 = getAsSubstTemplateTemplateParm()) { 245 subst->getReplacement().print(OS, Policy, SuppressNNS); 246 } else if (SubstTemplateTemplateParmPackStorage *SubstPack 247 = getAsSubstTemplateTemplateParmPack()) 248 OS << *SubstPack->getParameterPack(); 249 else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) { 250 Assumed->getDeclName().print(OS, Policy); 251 } else { 252 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); 253 (*OTS->begin())->printName(OS); 254 } 255 } 256 257 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB, 258 TemplateName N) { 259 std::string NameStr; 260 llvm::raw_string_ostream OS(NameStr); 261 LangOptions LO; 262 LO.CPlusPlus = true; 263 LO.Bool = true; 264 OS << '\''; 265 N.print(OS, PrintingPolicy(LO)); 266 OS << '\''; 267 OS.flush(); 268 return DB << NameStr; 269 } 270 271 void TemplateName::dump(raw_ostream &OS) const { 272 LangOptions LO; // FIXME! 273 LO.CPlusPlus = true; 274 LO.Bool = true; 275 print(OS, PrintingPolicy(LO)); 276 } 277 278 LLVM_DUMP_METHOD void TemplateName::dump() const { 279 dump(llvm::errs()); 280 } 281