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::NameKind TemplateName::getKind() const { 55 if (Storage.is<TemplateDecl *>()) 56 return Template; 57 if (Storage.is<DependentTemplateName *>()) 58 return DependentTemplate; 59 if (Storage.is<QualifiedTemplateName *>()) 60 return QualifiedTemplate; 61 62 UncommonTemplateNameStorage *uncommon 63 = Storage.get<UncommonTemplateNameStorage*>(); 64 if (uncommon->getAsOverloadedStorage()) 65 return OverloadedTemplate; 66 if (uncommon->getAsSubstTemplateTemplateParm()) 67 return SubstTemplateTemplateParm; 68 return SubstTemplateTemplateParmPack; 69 } 70 71 TemplateDecl *TemplateName::getAsTemplateDecl() const { 72 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) 73 return Template; 74 75 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) 76 return QTN->getTemplateDecl(); 77 78 if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm()) 79 return sub->getReplacement().getAsTemplateDecl(); 80 81 return nullptr; 82 } 83 84 bool TemplateName::isDependent() const { 85 if (TemplateDecl *Template = getAsTemplateDecl()) { 86 if (isa<TemplateTemplateParmDecl>(Template)) 87 return true; 88 // FIXME: Hack, getDeclContext() can be null if Template is still 89 // initializing due to PCH reading, so we check it before using it. 90 // Should probably modify TemplateSpecializationType to allow constructing 91 // it without the isDependent() checking. 92 return Template->getDeclContext() && 93 Template->getDeclContext()->isDependentContext(); 94 } 95 96 assert(!getAsOverloadedTemplate() && 97 "overloaded templates shouldn't survive to here"); 98 99 return true; 100 } 101 102 bool TemplateName::isInstantiationDependent() const { 103 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { 104 if (QTN->getQualifier()->isInstantiationDependent()) 105 return true; 106 } 107 108 return isDependent(); 109 } 110 111 bool TemplateName::containsUnexpandedParameterPack() const { 112 if (TemplateDecl *Template = getAsTemplateDecl()) { 113 if (TemplateTemplateParmDecl *TTP 114 = dyn_cast<TemplateTemplateParmDecl>(Template)) 115 return TTP->isParameterPack(); 116 117 return false; 118 } 119 120 if (DependentTemplateName *DTN = getAsDependentTemplateName()) 121 return DTN->getQualifier() && 122 DTN->getQualifier()->containsUnexpandedParameterPack(); 123 124 return getAsSubstTemplateTemplateParmPack() != nullptr; 125 } 126 127 void 128 TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, 129 bool SuppressNNS) const { 130 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) 131 OS << *Template; 132 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { 133 if (!SuppressNNS) 134 QTN->getQualifier()->print(OS, Policy); 135 if (QTN->hasTemplateKeyword()) 136 OS << "template "; 137 OS << *QTN->getDecl(); 138 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { 139 if (!SuppressNNS && DTN->getQualifier()) 140 DTN->getQualifier()->print(OS, Policy); 141 OS << "template "; 142 143 if (DTN->isIdentifier()) 144 OS << DTN->getIdentifier()->getName(); 145 else 146 OS << "operator " << getOperatorSpelling(DTN->getOperator()); 147 } else if (SubstTemplateTemplateParmStorage *subst 148 = getAsSubstTemplateTemplateParm()) { 149 subst->getReplacement().print(OS, Policy, SuppressNNS); 150 } else if (SubstTemplateTemplateParmPackStorage *SubstPack 151 = getAsSubstTemplateTemplateParmPack()) 152 OS << *SubstPack->getParameterPack(); 153 else { 154 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); 155 (*OTS->begin())->printName(OS); 156 } 157 } 158 159 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 160 TemplateName N) { 161 std::string NameStr; 162 raw_string_ostream OS(NameStr); 163 LangOptions LO; 164 LO.CPlusPlus = true; 165 LO.Bool = true; 166 OS << '\''; 167 N.print(OS, PrintingPolicy(LO)); 168 OS << '\''; 169 OS.flush(); 170 return DB << NameStr; 171 } 172 173 void TemplateName::dump(raw_ostream &OS) const { 174 LangOptions LO; // FIXME! 175 LO.CPlusPlus = true; 176 LO.Bool = true; 177 print(OS, PrintingPolicy(LO)); 178 } 179 180 void TemplateName::dump() const { 181 dump(llvm::errs()); 182 } 183