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(SubstTemplateTemplateParmStorage *Storage) 70 : Storage(Storage) {} 71 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage) 72 : Storage(Storage) {} 73 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {} 74 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {} 75 76 bool TemplateName::isNull() const { return Storage.isNull(); } 77 78 TemplateName::NameKind TemplateName::getKind() const { 79 if (Storage.is<TemplateDecl *>()) 80 return Template; 81 if (Storage.is<DependentTemplateName *>()) 82 return DependentTemplate; 83 if (Storage.is<QualifiedTemplateName *>()) 84 return QualifiedTemplate; 85 86 UncommonTemplateNameStorage *uncommon 87 = Storage.get<UncommonTemplateNameStorage*>(); 88 if (uncommon->getAsOverloadedStorage()) 89 return OverloadedTemplate; 90 if (uncommon->getAsSubstTemplateTemplateParm()) 91 return SubstTemplateTemplateParm; 92 return SubstTemplateTemplateParmPack; 93 } 94 95 TemplateDecl *TemplateName::getAsTemplateDecl() const { 96 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) 97 return Template; 98 99 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) 100 return QTN->getTemplateDecl(); 101 102 if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm()) 103 return sub->getReplacement().getAsTemplateDecl(); 104 105 return nullptr; 106 } 107 108 OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const { 109 if (UncommonTemplateNameStorage *Uncommon = 110 Storage.dyn_cast<UncommonTemplateNameStorage *>()) 111 return Uncommon->getAsOverloadedStorage(); 112 113 return nullptr; 114 } 115 116 SubstTemplateTemplateParmStorage * 117 TemplateName::getAsSubstTemplateTemplateParm() const { 118 if (UncommonTemplateNameStorage *uncommon = 119 Storage.dyn_cast<UncommonTemplateNameStorage *>()) 120 return uncommon->getAsSubstTemplateTemplateParm(); 121 122 return nullptr; 123 } 124 125 SubstTemplateTemplateParmPackStorage * 126 TemplateName::getAsSubstTemplateTemplateParmPack() const { 127 if (UncommonTemplateNameStorage *Uncommon = 128 Storage.dyn_cast<UncommonTemplateNameStorage *>()) 129 return Uncommon->getAsSubstTemplateTemplateParmPack(); 130 131 return nullptr; 132 } 133 134 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const { 135 return Storage.dyn_cast<QualifiedTemplateName *>(); 136 } 137 138 DependentTemplateName *TemplateName::getAsDependentTemplateName() const { 139 return Storage.dyn_cast<DependentTemplateName *>(); 140 } 141 142 TemplateName TemplateName::getNameToSubstitute() const { 143 TemplateDecl *Decl = getAsTemplateDecl(); 144 145 // Substituting a dependent template name: preserve it as written. 146 if (!Decl) 147 return *this; 148 149 // If we have a template declaration, use the most recent non-friend 150 // declaration of that template. 151 Decl = cast<TemplateDecl>(Decl->getMostRecentDecl()); 152 while (Decl->getFriendObjectKind()) { 153 Decl = cast<TemplateDecl>(Decl->getPreviousDecl()); 154 assert(Decl && "all declarations of template are friends"); 155 } 156 return TemplateName(Decl); 157 } 158 159 bool TemplateName::isDependent() const { 160 if (TemplateDecl *Template = getAsTemplateDecl()) { 161 if (isa<TemplateTemplateParmDecl>(Template)) 162 return true; 163 // FIXME: Hack, getDeclContext() can be null if Template is still 164 // initializing due to PCH reading, so we check it before using it. 165 // Should probably modify TemplateSpecializationType to allow constructing 166 // it without the isDependent() checking. 167 return Template->getDeclContext() && 168 Template->getDeclContext()->isDependentContext(); 169 } 170 171 assert(!getAsOverloadedTemplate() && 172 "overloaded templates shouldn't survive to here"); 173 174 return true; 175 } 176 177 bool TemplateName::isInstantiationDependent() const { 178 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { 179 if (QTN->getQualifier()->isInstantiationDependent()) 180 return true; 181 } 182 183 return isDependent(); 184 } 185 186 bool TemplateName::containsUnexpandedParameterPack() const { 187 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { 188 if (QTN->getQualifier()->containsUnexpandedParameterPack()) 189 return true; 190 } 191 192 if (TemplateDecl *Template = getAsTemplateDecl()) { 193 if (TemplateTemplateParmDecl *TTP 194 = dyn_cast<TemplateTemplateParmDecl>(Template)) 195 return TTP->isParameterPack(); 196 197 return false; 198 } 199 200 if (DependentTemplateName *DTN = getAsDependentTemplateName()) 201 return DTN->getQualifier() && 202 DTN->getQualifier()->containsUnexpandedParameterPack(); 203 204 return getAsSubstTemplateTemplateParmPack() != nullptr; 205 } 206 207 void 208 TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, 209 bool SuppressNNS) const { 210 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) 211 OS << *Template; 212 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { 213 if (!SuppressNNS) 214 QTN->getQualifier()->print(OS, Policy); 215 if (QTN->hasTemplateKeyword()) 216 OS << "template "; 217 OS << *QTN->getDecl(); 218 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { 219 if (!SuppressNNS && DTN->getQualifier()) 220 DTN->getQualifier()->print(OS, Policy); 221 OS << "template "; 222 223 if (DTN->isIdentifier()) 224 OS << DTN->getIdentifier()->getName(); 225 else 226 OS << "operator " << getOperatorSpelling(DTN->getOperator()); 227 } else if (SubstTemplateTemplateParmStorage *subst 228 = getAsSubstTemplateTemplateParm()) { 229 subst->getReplacement().print(OS, Policy, SuppressNNS); 230 } else if (SubstTemplateTemplateParmPackStorage *SubstPack 231 = getAsSubstTemplateTemplateParmPack()) 232 OS << *SubstPack->getParameterPack(); 233 else { 234 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); 235 (*OTS->begin())->printName(OS); 236 } 237 } 238 239 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 240 TemplateName N) { 241 std::string NameStr; 242 llvm::raw_string_ostream OS(NameStr); 243 LangOptions LO; 244 LO.CPlusPlus = true; 245 LO.Bool = true; 246 OS << '\''; 247 N.print(OS, PrintingPolicy(LO)); 248 OS << '\''; 249 OS.flush(); 250 return DB << NameStr; 251 } 252 253 void TemplateName::dump(raw_ostream &OS) const { 254 LangOptions LO; // FIXME! 255 LO.CPlusPlus = true; 256 LO.Bool = true; 257 print(OS, PrintingPolicy(LO)); 258 } 259 260 LLVM_DUMP_METHOD void TemplateName::dump() const { 261 dump(llvm::errs()); 262 } 263