clang API Documentation
00001 //===--- TemplateName.cpp - C++ Template Name Representation---------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the TemplateName interface and subclasses. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "clang/AST/TemplateName.h" 00015 #include "clang/AST/DeclTemplate.h" 00016 #include "clang/AST/NestedNameSpecifier.h" 00017 #include "clang/AST/PrettyPrinter.h" 00018 #include "clang/AST/TemplateBase.h" 00019 #include "clang/Basic/Diagnostic.h" 00020 #include "clang/Basic/LangOptions.h" 00021 #include "llvm/Support/raw_ostream.h" 00022 using namespace clang; 00023 using namespace llvm; 00024 00025 TemplateArgument 00026 SubstTemplateTemplateParmPackStorage::getArgumentPack() const { 00027 return TemplateArgument(Arguments, size()); 00028 } 00029 00030 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) { 00031 Profile(ID, Parameter, Replacement); 00032 } 00033 00034 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID, 00035 TemplateTemplateParmDecl *parameter, 00036 TemplateName replacement) { 00037 ID.AddPointer(parameter); 00038 ID.AddPointer(replacement.getAsVoidPointer()); 00039 } 00040 00041 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, 00042 ASTContext &Context) { 00043 Profile(ID, Context, Parameter, TemplateArgument(Arguments, size())); 00044 } 00045 00046 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, 00047 ASTContext &Context, 00048 TemplateTemplateParmDecl *Parameter, 00049 const TemplateArgument &ArgPack) { 00050 ID.AddPointer(Parameter); 00051 ArgPack.Profile(ID, Context); 00052 } 00053 00054 TemplateName::NameKind TemplateName::getKind() const { 00055 if (Storage.is<TemplateDecl *>()) 00056 return Template; 00057 if (Storage.is<DependentTemplateName *>()) 00058 return DependentTemplate; 00059 if (Storage.is<QualifiedTemplateName *>()) 00060 return QualifiedTemplate; 00061 00062 UncommonTemplateNameStorage *uncommon 00063 = Storage.get<UncommonTemplateNameStorage*>(); 00064 if (uncommon->getAsOverloadedStorage()) 00065 return OverloadedTemplate; 00066 if (uncommon->getAsSubstTemplateTemplateParm()) 00067 return SubstTemplateTemplateParm; 00068 return SubstTemplateTemplateParmPack; 00069 } 00070 00071 TemplateDecl *TemplateName::getAsTemplateDecl() const { 00072 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) 00073 return Template; 00074 00075 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) 00076 return QTN->getTemplateDecl(); 00077 00078 if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm()) 00079 return sub->getReplacement().getAsTemplateDecl(); 00080 00081 return nullptr; 00082 } 00083 00084 bool TemplateName::isDependent() const { 00085 if (TemplateDecl *Template = getAsTemplateDecl()) { 00086 if (isa<TemplateTemplateParmDecl>(Template)) 00087 return true; 00088 // FIXME: Hack, getDeclContext() can be null if Template is still 00089 // initializing due to PCH reading, so we check it before using it. 00090 // Should probably modify TemplateSpecializationType to allow constructing 00091 // it without the isDependent() checking. 00092 return Template->getDeclContext() && 00093 Template->getDeclContext()->isDependentContext(); 00094 } 00095 00096 assert(!getAsOverloadedTemplate() && 00097 "overloaded templates shouldn't survive to here"); 00098 00099 return true; 00100 } 00101 00102 bool TemplateName::isInstantiationDependent() const { 00103 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { 00104 if (QTN->getQualifier()->isInstantiationDependent()) 00105 return true; 00106 } 00107 00108 return isDependent(); 00109 } 00110 00111 bool TemplateName::containsUnexpandedParameterPack() const { 00112 if (TemplateDecl *Template = getAsTemplateDecl()) { 00113 if (TemplateTemplateParmDecl *TTP 00114 = dyn_cast<TemplateTemplateParmDecl>(Template)) 00115 return TTP->isParameterPack(); 00116 00117 return false; 00118 } 00119 00120 if (DependentTemplateName *DTN = getAsDependentTemplateName()) 00121 return DTN->getQualifier() && 00122 DTN->getQualifier()->containsUnexpandedParameterPack(); 00123 00124 return getAsSubstTemplateTemplateParmPack() != nullptr; 00125 } 00126 00127 void 00128 TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, 00129 bool SuppressNNS) const { 00130 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) 00131 OS << *Template; 00132 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { 00133 if (!SuppressNNS) 00134 QTN->getQualifier()->print(OS, Policy); 00135 if (QTN->hasTemplateKeyword()) 00136 OS << "template "; 00137 OS << *QTN->getDecl(); 00138 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { 00139 if (!SuppressNNS && DTN->getQualifier()) 00140 DTN->getQualifier()->print(OS, Policy); 00141 OS << "template "; 00142 00143 if (DTN->isIdentifier()) 00144 OS << DTN->getIdentifier()->getName(); 00145 else 00146 OS << "operator " << getOperatorSpelling(DTN->getOperator()); 00147 } else if (SubstTemplateTemplateParmStorage *subst 00148 = getAsSubstTemplateTemplateParm()) { 00149 subst->getReplacement().print(OS, Policy, SuppressNNS); 00150 } else if (SubstTemplateTemplateParmPackStorage *SubstPack 00151 = getAsSubstTemplateTemplateParmPack()) 00152 OS << *SubstPack->getParameterPack(); 00153 else { 00154 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); 00155 (*OTS->begin())->printName(OS); 00156 } 00157 } 00158 00159 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 00160 TemplateName N) { 00161 std::string NameStr; 00162 raw_string_ostream OS(NameStr); 00163 LangOptions LO; 00164 LO.CPlusPlus = true; 00165 LO.Bool = true; 00166 OS << '\''; 00167 N.print(OS, PrintingPolicy(LO)); 00168 OS << '\''; 00169 OS.flush(); 00170 return DB << NameStr; 00171 } 00172 00173 void TemplateName::dump(raw_ostream &OS) const { 00174 LangOptions LO; // FIXME! 00175 LO.CPlusPlus = true; 00176 LO.Bool = true; 00177 print(OS, PrintingPolicy(LO)); 00178 } 00179 00180 void TemplateName::dump() const { 00181 dump(llvm::errs()); 00182 }