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