clang API Documentation

TemplateName.cpp
Go to the documentation of this file.
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 }