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