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