TemplateName.cpp revision d538ed9b2a617239d5bd56357663de62f6f9224c
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" 22using namespace clang; 23using namespace llvm; 24 25TemplateArgument 26SubstTemplateTemplateParmPackStorage::getArgumentPack() const { 27 return TemplateArgument(Arguments, size()); 28} 29 30void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) { 31 Profile(ID, Parameter, Replacement); 32} 33 34void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID, 35 TemplateTemplateParmDecl *parameter, 36 TemplateName replacement) { 37 ID.AddPointer(parameter); 38 ID.AddPointer(replacement.getAsVoidPointer()); 39} 40 41void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, 42 ASTContext &Context) { 43 Profile(ID, Context, Parameter, TemplateArgument(Arguments, size())); 44} 45 46void 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 54TemplateName::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 71TemplateDecl *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 0; 82} 83 84bool 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 102bool TemplateName::isInstantiationDependent() const { 103 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { 104 if (QTN->getQualifier()->isInstantiationDependent()) 105 return true; 106 } 107 108 return isDependent(); 109} 110 111bool 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() != 0; 125} 126 127void 128TemplateName::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 159const 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 N.print(OS, PrintingPolicy(LO)); 167 OS.flush(); 168 return DB << NameStr; 169} 170 171void TemplateName::dump(raw_ostream &OS) const { 172 LangOptions LO; // FIXME! 173 LO.CPlusPlus = true; 174 LO.Bool = true; 175 print(OS, PrintingPolicy(LO)); 176} 177 178void TemplateName::dump() const { 179 dump(llvm::errs()); 180} 181