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