Home | History | Annotate | Line # | Download | only in AST
      1 //===- TemplateName.cpp - C++ Template Name Representation ----------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 //  This file defines the TemplateName interface and subclasses.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #include "clang/AST/TemplateName.h"
     14 #include "clang/AST/Decl.h"
     15 #include "clang/AST/DeclBase.h"
     16 #include "clang/AST/DeclTemplate.h"
     17 #include "clang/AST/DependenceFlags.h"
     18 #include "clang/AST/NestedNameSpecifier.h"
     19 #include "clang/AST/PrettyPrinter.h"
     20 #include "clang/AST/TemplateBase.h"
     21 #include "clang/Basic/Diagnostic.h"
     22 #include "clang/Basic/LLVM.h"
     23 #include "clang/Basic/LangOptions.h"
     24 #include "clang/Basic/OperatorKinds.h"
     25 #include "llvm/ADT/ArrayRef.h"
     26 #include "llvm/ADT/FoldingSet.h"
     27 #include "llvm/Support/Casting.h"
     28 #include "llvm/Support/Compiler.h"
     29 #include "llvm/Support/raw_ostream.h"
     30 #include <cassert>
     31 #include <string>
     32 
     33 using namespace clang;
     34 
     35 TemplateArgument
     36 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
     37   return TemplateArgument(llvm::makeArrayRef(Arguments, size()));
     38 }
     39 
     40 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
     41   Profile(ID, Parameter, Replacement);
     42 }
     43 
     44 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
     45                                            TemplateTemplateParmDecl *parameter,
     46                                                TemplateName replacement) {
     47   ID.AddPointer(parameter);
     48   ID.AddPointer(replacement.getAsVoidPointer());
     49 }
     50 
     51 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
     52                                                    ASTContext &Context) {
     53   Profile(ID, Context, Parameter, getArgumentPack());
     54 }
     55 
     56 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
     57                                                    ASTContext &Context,
     58                                            TemplateTemplateParmDecl *Parameter,
     59                                              const TemplateArgument &ArgPack) {
     60   ID.AddPointer(Parameter);
     61   ArgPack.Profile(ID, Context);
     62 }
     63 
     64 TemplateName::TemplateName(void *Ptr) {
     65   Storage = StorageType::getFromOpaqueValue(Ptr);
     66 }
     67 
     68 TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
     69 TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
     70     : Storage(Storage) {}
     71 TemplateName::TemplateName(AssumedTemplateStorage *Storage)
     72     : Storage(Storage) {}
     73 TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
     74     : Storage(Storage) {}
     75 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
     76     : Storage(Storage) {}
     77 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
     78 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
     79 
     80 bool TemplateName::isNull() const { return Storage.isNull(); }
     81 
     82 TemplateName::NameKind TemplateName::getKind() const {
     83   if (Storage.is<TemplateDecl *>())
     84     return Template;
     85   if (Storage.is<DependentTemplateName *>())
     86     return DependentTemplate;
     87   if (Storage.is<QualifiedTemplateName *>())
     88     return QualifiedTemplate;
     89 
     90   UncommonTemplateNameStorage *uncommon
     91     = Storage.get<UncommonTemplateNameStorage*>();
     92   if (uncommon->getAsOverloadedStorage())
     93     return OverloadedTemplate;
     94   if (uncommon->getAsAssumedTemplateName())
     95     return AssumedTemplate;
     96   if (uncommon->getAsSubstTemplateTemplateParm())
     97     return SubstTemplateTemplateParm;
     98   return SubstTemplateTemplateParmPack;
     99 }
    100 
    101 TemplateDecl *TemplateName::getAsTemplateDecl() const {
    102   if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
    103     return Template;
    104 
    105   if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
    106     return QTN->getTemplateDecl();
    107 
    108   if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
    109     return sub->getReplacement().getAsTemplateDecl();
    110 
    111   return nullptr;
    112 }
    113 
    114 OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
    115   if (UncommonTemplateNameStorage *Uncommon =
    116           Storage.dyn_cast<UncommonTemplateNameStorage *>())
    117     return Uncommon->getAsOverloadedStorage();
    118 
    119   return nullptr;
    120 }
    121 
    122 AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {
    123   if (UncommonTemplateNameStorage *Uncommon =
    124           Storage.dyn_cast<UncommonTemplateNameStorage *>())
    125     return Uncommon->getAsAssumedTemplateName();
    126 
    127   return nullptr;
    128 }
    129 
    130 SubstTemplateTemplateParmStorage *
    131 TemplateName::getAsSubstTemplateTemplateParm() const {
    132   if (UncommonTemplateNameStorage *uncommon =
    133           Storage.dyn_cast<UncommonTemplateNameStorage *>())
    134     return uncommon->getAsSubstTemplateTemplateParm();
    135 
    136   return nullptr;
    137 }
    138 
    139 SubstTemplateTemplateParmPackStorage *
    140 TemplateName::getAsSubstTemplateTemplateParmPack() const {
    141   if (UncommonTemplateNameStorage *Uncommon =
    142           Storage.dyn_cast<UncommonTemplateNameStorage *>())
    143     return Uncommon->getAsSubstTemplateTemplateParmPack();
    144 
    145   return nullptr;
    146 }
    147 
    148 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
    149   return Storage.dyn_cast<QualifiedTemplateName *>();
    150 }
    151 
    152 DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
    153   return Storage.dyn_cast<DependentTemplateName *>();
    154 }
    155 
    156 TemplateName TemplateName::getNameToSubstitute() const {
    157   TemplateDecl *Decl = getAsTemplateDecl();
    158 
    159   // Substituting a dependent template name: preserve it as written.
    160   if (!Decl)
    161     return *this;
    162 
    163   // If we have a template declaration, use the most recent non-friend
    164   // declaration of that template.
    165   Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
    166   while (Decl->getFriendObjectKind()) {
    167     Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
    168     assert(Decl && "all declarations of template are friends");
    169   }
    170   return TemplateName(Decl);
    171 }
    172 
    173 TemplateNameDependence TemplateName::getDependence() const {
    174   auto D = TemplateNameDependence::None;
    175   switch (getKind()) {
    176   case TemplateName::NameKind::QualifiedTemplate:
    177     D |= toTemplateNameDependence(
    178         getAsQualifiedTemplateName()->getQualifier()->getDependence());
    179     break;
    180   case TemplateName::NameKind::DependentTemplate:
    181     D |= toTemplateNameDependence(
    182         getAsDependentTemplateName()->getQualifier()->getDependence());
    183     break;
    184   case TemplateName::NameKind::SubstTemplateTemplateParmPack:
    185     D |= TemplateNameDependence::UnexpandedPack;
    186     break;
    187   case TemplateName::NameKind::OverloadedTemplate:
    188     llvm_unreachable("overloaded templates shouldn't survive to here.");
    189   default:
    190     break;
    191   }
    192   if (TemplateDecl *Template = getAsTemplateDecl()) {
    193     if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
    194       D |= TemplateNameDependence::DependentInstantiation;
    195       if (TTP->isParameterPack())
    196         D |= TemplateNameDependence::UnexpandedPack;
    197     }
    198     // FIXME: Hack, getDeclContext() can be null if Template is still
    199     // initializing due to PCH reading, so we check it before using it.
    200     // Should probably modify TemplateSpecializationType to allow constructing
    201     // it without the isDependent() checking.
    202     if (Template->getDeclContext() &&
    203         Template->getDeclContext()->isDependentContext())
    204       D |= TemplateNameDependence::DependentInstantiation;
    205   } else {
    206     D |= TemplateNameDependence::DependentInstantiation;
    207   }
    208   return D;
    209 }
    210 
    211 bool TemplateName::isDependent() const {
    212   return getDependence() & TemplateNameDependence::Dependent;
    213 }
    214 
    215 bool TemplateName::isInstantiationDependent() const {
    216   return getDependence() & TemplateNameDependence::Instantiation;
    217 }
    218 
    219 bool TemplateName::containsUnexpandedParameterPack() const {
    220   return getDependence() & TemplateNameDependence::UnexpandedPack;
    221 }
    222 
    223 void
    224 TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
    225                     bool SuppressNNS) const {
    226   if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
    227     OS << *Template;
    228   else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
    229     if (!SuppressNNS)
    230       QTN->getQualifier()->print(OS, Policy);
    231     if (QTN->hasTemplateKeyword())
    232       OS << "template ";
    233     OS << *QTN->getDecl();
    234   } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
    235     if (!SuppressNNS && DTN->getQualifier())
    236       DTN->getQualifier()->print(OS, Policy);
    237     OS << "template ";
    238 
    239     if (DTN->isIdentifier())
    240       OS << DTN->getIdentifier()->getName();
    241     else
    242       OS << "operator " << getOperatorSpelling(DTN->getOperator());
    243   } else if (SubstTemplateTemplateParmStorage *subst
    244                = getAsSubstTemplateTemplateParm()) {
    245     subst->getReplacement().print(OS, Policy, SuppressNNS);
    246   } else if (SubstTemplateTemplateParmPackStorage *SubstPack
    247                                         = getAsSubstTemplateTemplateParmPack())
    248     OS << *SubstPack->getParameterPack();
    249   else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
    250     Assumed->getDeclName().print(OS, Policy);
    251   } else {
    252     OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
    253     (*OTS->begin())->printName(OS);
    254   }
    255 }
    256 
    257 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
    258                                              TemplateName N) {
    259   std::string NameStr;
    260   llvm::raw_string_ostream OS(NameStr);
    261   LangOptions LO;
    262   LO.CPlusPlus = true;
    263   LO.Bool = true;
    264   OS << '\'';
    265   N.print(OS, PrintingPolicy(LO));
    266   OS << '\'';
    267   OS.flush();
    268   return DB << NameStr;
    269 }
    270 
    271 void TemplateName::dump(raw_ostream &OS) const {
    272   LangOptions LO;  // FIXME!
    273   LO.CPlusPlus = true;
    274   LO.Bool = true;
    275   print(OS, PrintingPolicy(LO));
    276 }
    277 
    278 LLVM_DUMP_METHOD void TemplateName::dump() const {
    279   dump(llvm::errs());
    280 }
    281