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 bool TemplateName::isDependent() const { 135 if (TemplateDecl *Template = getAsTemplateDecl()) { 136 if (isa<TemplateTemplateParmDecl>(Template)) 137 return true; 138 // FIXME: Hack, getDeclContext() can be null if Template is still 139 // initializing due to PCH reading, so we check it before using it. 140 // Should probably modify TemplateSpecializationType to allow constructing 141 // it without the isDependent() checking. 142 return Template->getDeclContext() && 143 Template->getDeclContext()->isDependentContext(); 144 } 145 146 assert(!getAsOverloadedTemplate() && 147 "overloaded templates shouldn't survive to here"); 148 149 return true; 150 } 151 152 bool TemplateName::isInstantiationDependent() const { 153 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { 154 if (QTN->getQualifier()->isInstantiationDependent()) 155 return true; 156 } 157 158 return isDependent(); 159 } 160 161 bool TemplateName::containsUnexpandedParameterPack() const { 162 if (TemplateDecl *Template = getAsTemplateDecl()) { 163 if (TemplateTemplateParmDecl *TTP 164 = dyn_cast<TemplateTemplateParmDecl>(Template)) 165 return TTP->isParameterPack(); 166 167 return false; 168 } 169 170 if (DependentTemplateName *DTN = getAsDependentTemplateName()) 171 return DTN->getQualifier() && 172 DTN->getQualifier()->containsUnexpandedParameterPack(); 173 174 return getAsSubstTemplateTemplateParmPack() != nullptr; 175 } 176 177 void 178 TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, 179 bool SuppressNNS) const { 180 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) 181 OS << *Template; 182 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { 183 if (!SuppressNNS) 184 QTN->getQualifier()->print(OS, Policy); 185 if (QTN->hasTemplateKeyword()) 186 OS << "template "; 187 OS << *QTN->getDecl(); 188 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { 189 if (!SuppressNNS && DTN->getQualifier()) 190 DTN->getQualifier()->print(OS, Policy); 191 OS << "template "; 192 193 if (DTN->isIdentifier()) 194 OS << DTN->getIdentifier()->getName(); 195 else 196 OS << "operator " << getOperatorSpelling(DTN->getOperator()); 197 } else if (SubstTemplateTemplateParmStorage *subst 198 = getAsSubstTemplateTemplateParm()) { 199 subst->getReplacement().print(OS, Policy, SuppressNNS); 200 } else if (SubstTemplateTemplateParmPackStorage *SubstPack 201 = getAsSubstTemplateTemplateParmPack()) 202 OS << *SubstPack->getParameterPack(); 203 else { 204 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); 205 (*OTS->begin())->printName(OS); 206 } 207 } 208 209 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 210 TemplateName N) { 211 std::string NameStr; 212 raw_string_ostream OS(NameStr); 213 LangOptions LO; 214 LO.CPlusPlus = true; 215 LO.Bool = true; 216 OS << '\''; 217 N.print(OS, PrintingPolicy(LO)); 218 OS << '\''; 219 OS.flush(); 220 return DB << NameStr; 221 } 222 223 void TemplateName::dump(raw_ostream &OS) const { 224 LangOptions LO; // FIXME! 225 LO.CPlusPlus = true; 226 LO.Bool = true; 227 print(OS, PrintingPolicy(LO)); 228 } 229 230 LLVM_DUMP_METHOD void TemplateName::dump() const { 231 dump(llvm::errs()); 232 } 233