Home | History | Annotate | Download | only in AST
      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