brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.5 KiB · 797a354 Raw
511 lines · cpp
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-exception6//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/DeclCXX.h"17#include "clang/AST/DeclTemplate.h"18#include "clang/AST/DependenceFlags.h"19#include "clang/AST/NestedNameSpecifier.h"20#include "clang/AST/PrettyPrinter.h"21#include "clang/AST/TemplateBase.h"22#include "clang/Basic/Diagnostic.h"23#include "clang/Basic/LLVM.h"24#include "clang/Basic/LangOptions.h"25#include "clang/Basic/OperatorKinds.h"26#include "llvm/ADT/ArrayRef.h"27#include "llvm/ADT/FoldingSet.h"28#include "llvm/Support/Compiler.h"29#include "llvm/Support/raw_ostream.h"30#include <cassert>31#include <optional>32#include <string>33 34using namespace clang;35 36DeducedTemplateStorage::DeducedTemplateStorage(TemplateName Underlying,37                                               const DefaultArguments &DefArgs)38    : UncommonTemplateNameStorage(Deduced, /*Index=*/DefArgs.StartPos,39                                  DefArgs.Args.size()),40      Underlying(Underlying) {41  llvm::copy(DefArgs.Args, reinterpret_cast<TemplateArgument *>(this + 1));42}43 44void DeducedTemplateStorage::Profile(llvm::FoldingSetNodeID &ID,45                                     const ASTContext &Context) const {46  Profile(ID, Context, Underlying, getDefaultArguments());47}48 49void DeducedTemplateStorage::Profile(llvm::FoldingSetNodeID &ID,50                                     const ASTContext &Context,51                                     TemplateName Underlying,52                                     const DefaultArguments &DefArgs) {53  Underlying.Profile(ID);54  ID.AddInteger(DefArgs.StartPos);55  ID.AddInteger(DefArgs.Args.size());56  for (const TemplateArgument &Arg : DefArgs.Args)57    Arg.Profile(ID, Context);58}59 60TemplateArgument61SubstTemplateTemplateParmPackStorage::getArgumentPack() const {62  return TemplateArgument(ArrayRef(Arguments, Bits.Data));63}64 65TemplateTemplateParmDecl *66SubstTemplateTemplateParmPackStorage::getParameterPack() const {67  return cast<TemplateTemplateParmDecl>(std::get<0>(68      getReplacedTemplateParameter(getAssociatedDecl(), Bits.Index)));69}70 71TemplateTemplateParmDecl *72SubstTemplateTemplateParmStorage::getParameter() const {73  return cast<TemplateTemplateParmDecl>(std::get<0>(74      getReplacedTemplateParameter(getAssociatedDecl(), Bits.Index)));75}76 77void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {78  Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex(),79          getFinal());80}81 82void SubstTemplateTemplateParmStorage::Profile(83    llvm::FoldingSetNodeID &ID, TemplateName Replacement, Decl *AssociatedDecl,84    unsigned Index, UnsignedOrNone PackIndex, bool Final) {85  Replacement.Profile(ID);86  ID.AddPointer(AssociatedDecl);87  ID.AddInteger(Index);88  ID.AddInteger(PackIndex.toInternalRepresentation());89  ID.AddBoolean(Final);90}91 92SubstTemplateTemplateParmPackStorage::SubstTemplateTemplateParmPackStorage(93    ArrayRef<TemplateArgument> ArgPack, Decl *AssociatedDecl, unsigned Index,94    bool Final)95    : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index,96                                  ArgPack.size()),97      Arguments(ArgPack.data()), AssociatedDeclAndFinal(AssociatedDecl, Final) {98  assert(AssociatedDecl != nullptr);99}100 101void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,102                                                   ASTContext &Context) {103  Profile(ID, Context, getArgumentPack(), getAssociatedDecl(), getIndex(),104          getFinal());105}106 107Decl *SubstTemplateTemplateParmPackStorage::getAssociatedDecl() const {108  return AssociatedDeclAndFinal.getPointer();109}110 111bool SubstTemplateTemplateParmPackStorage::getFinal() const {112  return AssociatedDeclAndFinal.getInt();113}114 115void SubstTemplateTemplateParmPackStorage::Profile(116    llvm::FoldingSetNodeID &ID, ASTContext &Context,117    const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index,118    bool Final) {119  ArgPack.Profile(ID, Context);120  ID.AddPointer(AssociatedDecl);121  ID.AddInteger(Index);122  ID.AddBoolean(Final);123}124 125IdentifierOrOverloadedOperator::IdentifierOrOverloadedOperator(126    const IdentifierInfo *II)127    : PtrOrOp(reinterpret_cast<uintptr_t>(II)) {128  static_assert(NUM_OVERLOADED_OPERATORS <= 4096,129                "NUM_OVERLOADED_OPERATORS is too large");130  assert(II);131  assert(getIdentifier() == II);132}133IdentifierOrOverloadedOperator::IdentifierOrOverloadedOperator(134    OverloadedOperatorKind OOK)135    : PtrOrOp(-uintptr_t(OOK)) {136  assert(OOK != OO_None);137  assert(getOperator() == OOK);138}139 140void IdentifierOrOverloadedOperator::Profile(llvm::FoldingSetNodeID &ID) const {141  if (auto *Identifier = getIdentifier()) {142    ID.AddBoolean(false);143    ID.AddPointer(Identifier);144  } else {145    ID.AddBoolean(true);146    ID.AddInteger(getOperator());147  }148}149 150TemplateName::TemplateName(void *Ptr) {151  Storage = StorageType::getFromOpaqueValue(Ptr);152}153 154TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}155TemplateName::TemplateName(OverloadedTemplateStorage *Storage)156    : Storage(Storage) {}157TemplateName::TemplateName(AssumedTemplateStorage *Storage)158    : Storage(Storage) {}159TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)160    : Storage(Storage) {}161TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)162    : Storage(Storage) {}163TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}164TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}165TemplateName::TemplateName(UsingShadowDecl *Using) : Storage(Using) {}166TemplateName::TemplateName(DeducedTemplateStorage *Deduced)167    : Storage(Deduced) {}168 169bool TemplateName::isNull() const { return Storage.isNull(); }170 171TemplateName::NameKind TemplateName::getKind() const {172  if (auto *ND = dyn_cast<Decl *>(Storage)) {173    if (isa<UsingShadowDecl>(ND))174      return UsingTemplate;175    assert(isa<TemplateDecl>(ND));176    return Template;177  }178 179  if (isa<DependentTemplateName *>(Storage))180    return DependentTemplate;181  if (isa<QualifiedTemplateName *>(Storage))182    return QualifiedTemplate;183 184  UncommonTemplateNameStorage *uncommon =185      cast<UncommonTemplateNameStorage *>(Storage);186  if (uncommon->getAsOverloadedStorage())187    return OverloadedTemplate;188  if (uncommon->getAsAssumedTemplateName())189    return AssumedTemplate;190  if (uncommon->getAsSubstTemplateTemplateParm())191    return SubstTemplateTemplateParm;192  if (uncommon->getAsDeducedTemplateName())193    return DeducedTemplate;194 195  assert(uncommon->getAsSubstTemplateTemplateParmPack() != nullptr);196  return SubstTemplateTemplateParmPack;197}198 199TemplateDecl *TemplateName::getAsTemplateDecl(bool IgnoreDeduced) const {200  TemplateName Name = *this;201  while (std::optional<TemplateName> UnderlyingOrNone =202             Name.desugar(IgnoreDeduced))203    Name = *UnderlyingOrNone;204 205  if (!IgnoreDeduced)206    assert(Name.getAsDeducedTemplateName() == nullptr &&207           "Unexpected canonical DeducedTemplateName; Did you mean to use "208           "getTemplateDeclAndDefaultArgs instead?");209 210  return cast_if_present<TemplateDecl>(211      dyn_cast_if_present<Decl *>(Name.Storage));212}213 214std::pair<TemplateName, DefaultArguments>215TemplateName::getTemplateDeclAndDefaultArgs() const {216  DefaultArguments DefArgs;217  for (TemplateName Name = *this; /**/; /**/) {218    if (DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName()) {219      assert(!DefArgs && "multiple default args?");220      DefArgs = DTS->getDefaultArguments();221      if (TemplateDecl *TD = DTS->getUnderlying().getAsTemplateDecl();222          TD && DefArgs)223        assert(DefArgs.StartPos + DefArgs.Args.size() <=224               TD->getTemplateParameters()->size());225      Name = DTS->getUnderlying();226    }227    if (std::optional<TemplateName> UnderlyingOrNone =228            Name.desugar(/*IgnoreDeduced=*/false)) {229      Name = *UnderlyingOrNone;230      continue;231    }232    return {Name, DefArgs};233  }234}235 236std::optional<TemplateName> TemplateName::desugar(bool IgnoreDeduced) const {237  if (Decl *D = dyn_cast_if_present<Decl *>(Storage)) {238    if (auto *USD = dyn_cast<UsingShadowDecl>(D))239      return TemplateName(USD->getTargetDecl());240    return std::nullopt;241  }242  if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())243    return QTN->getUnderlyingTemplate();244  if (SubstTemplateTemplateParmStorage *S = getAsSubstTemplateTemplateParm())245    return S->getReplacement();246  if (IgnoreDeduced)247    if (DeducedTemplateStorage *S = getAsDeducedTemplateName())248      return S->getUnderlying();249  return std::nullopt;250}251 252OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {253  if (UncommonTemplateNameStorage *Uncommon =254          Storage.dyn_cast<UncommonTemplateNameStorage *>())255    return Uncommon->getAsOverloadedStorage();256 257  return nullptr;258}259 260AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {261  if (UncommonTemplateNameStorage *Uncommon =262          Storage.dyn_cast<UncommonTemplateNameStorage *>())263    return Uncommon->getAsAssumedTemplateName();264 265  return nullptr;266}267 268SubstTemplateTemplateParmStorage *269TemplateName::getAsSubstTemplateTemplateParm() const {270  if (UncommonTemplateNameStorage *uncommon =271          dyn_cast_if_present<UncommonTemplateNameStorage *>(Storage))272    return uncommon->getAsSubstTemplateTemplateParm();273 274  return nullptr;275}276 277SubstTemplateTemplateParmPackStorage *278TemplateName::getAsSubstTemplateTemplateParmPack() const {279  if (UncommonTemplateNameStorage *Uncommon =280          Storage.dyn_cast<UncommonTemplateNameStorage *>())281    return Uncommon->getAsSubstTemplateTemplateParmPack();282 283  return nullptr;284}285 286QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {287  return dyn_cast_if_present<QualifiedTemplateName *>(Storage);288}289 290DependentTemplateName *TemplateName::getAsDependentTemplateName() const {291  return Storage.dyn_cast<DependentTemplateName *>();292}293 294std::tuple<NestedNameSpecifier, bool>295TemplateName::getQualifierAndTemplateKeyword() const {296  for (std::optional<TemplateName> Cur = *this; Cur;297       Cur = Cur->desugar(/*IgnoreDeduced=*/true)) {298    if (DependentTemplateName *N = Cur->getAsDependentTemplateName())299      return {N->getQualifier(), N->hasTemplateKeyword()};300    if (QualifiedTemplateName *N = Cur->getAsQualifiedTemplateName())301      return {N->getQualifier(), N->hasTemplateKeyword()};302    if (Cur->getAsSubstTemplateTemplateParm() ||303        Cur->getAsSubstTemplateTemplateParmPack())304      break;305  }306  return {std::nullopt, false};307}308 309UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {310  if (Decl *D = Storage.dyn_cast<Decl *>())311    if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))312      return USD;313  if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())314    return QTN->getUnderlyingTemplate().getAsUsingShadowDecl();315  return nullptr;316}317 318DependentTemplateStorage::DependentTemplateStorage(319    NestedNameSpecifier Qualifier, IdentifierOrOverloadedOperator Name,320    bool HasTemplateKeyword)321    : Qualifier(Qualifier, HasTemplateKeyword), Name(Name) {322  assert((!Qualifier || Qualifier.isDependent()) &&323         "Qualifier must be dependent");324}325 326TemplateNameDependence DependentTemplateStorage::getDependence() const {327  return toTemplateNameDependence(getQualifier().getDependence()) |328         TemplateNameDependence::DependentInstantiation;329}330 331void DependentTemplateStorage::print(raw_ostream &OS,332                                     const PrintingPolicy &Policy) const {333  getQualifier().print(OS, Policy);334 335  if (hasTemplateKeyword())336    OS << "template ";337 338  IdentifierOrOverloadedOperator Name = getName();339  if (const IdentifierInfo *II = Name.getIdentifier())340    OS << II->getName();341  else342    OS << "operator " << getOperatorSpelling(Name.getOperator());343}344 345DeducedTemplateStorage *TemplateName::getAsDeducedTemplateName() const {346  if (UncommonTemplateNameStorage *Uncommon =347          dyn_cast_if_present<UncommonTemplateNameStorage *>(Storage))348    return Uncommon->getAsDeducedTemplateName();349 350  return nullptr;351}352 353TemplateNameDependence TemplateName::getDependence() const {354  switch (getKind()) {355  case NameKind::Template:356  case NameKind::UsingTemplate: {357    TemplateDecl *Template = getAsTemplateDecl();358    auto D = TemplateNameDependence::None;359    if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {360      D |= TemplateNameDependence::DependentInstantiation;361      if (TTP->isParameterPack())362        D |= TemplateNameDependence::UnexpandedPack;363    }364    // FIXME: Hack, getDeclContext() can be null if Template is still365    // initializing due to PCH reading, so we check it before using it.366    // Should probably modify TemplateSpecializationType to allow constructing367    // it without the isDependent() checking.368    if (Template->getDeclContext() &&369        Template->getDeclContext()->isDependentContext())370      D |= TemplateNameDependence::DependentInstantiation;371    return D;372  }373  case NameKind::QualifiedTemplate: {374    QualifiedTemplateName *S = getAsQualifiedTemplateName();375    TemplateNameDependence D = S->getUnderlyingTemplate().getDependence();376    D |= toTemplateNameDependence(S->getQualifier().getDependence());377    return D;378  }379  case NameKind::DependentTemplate: {380    DependentTemplateName *S = getAsDependentTemplateName();381    return toTemplateNameDependence(S->getQualifier().getDependence()) |382           TemplateNameDependence::DependentInstantiation;383  }384  case NameKind::SubstTemplateTemplateParm: {385    auto *S = getAsSubstTemplateTemplateParm();386    return S->getReplacement().getDependence();387  }388  case NameKind::SubstTemplateTemplateParmPack:389    return TemplateNameDependence::UnexpandedPack |390           TemplateNameDependence::DependentInstantiation;391  case NameKind::DeducedTemplate: {392    DeducedTemplateStorage *DTS = getAsDeducedTemplateName();393    TemplateNameDependence D = DTS->getUnderlying().getDependence();394    for (const TemplateArgument &Arg : DTS->getDefaultArguments().Args)395      D |= toTemplateNameDependence(Arg.getDependence());396    return D;397  }398  case NameKind::AssumedTemplate:399    return TemplateNameDependence::DependentInstantiation;400  case NameKind::OverloadedTemplate:401    llvm_unreachable("overloaded templates shouldn't survive to here.");402  }403  llvm_unreachable("Unknown TemplateName kind");404}405 406bool TemplateName::isDependent() const {407  return getDependence() & TemplateNameDependence::Dependent;408}409 410bool TemplateName::isInstantiationDependent() const {411  return getDependence() & TemplateNameDependence::Instantiation;412}413 414bool TemplateName::containsUnexpandedParameterPack() const {415  return getDependence() & TemplateNameDependence::UnexpandedPack;416}417 418void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,419                         Qualified Qual) const {420  auto handleAnonymousTTP = [&](TemplateDecl *TD, raw_ostream &OS) {421    if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(TD);422        TTP && (Policy.PrintAsCanonical || TTP->getIdentifier() == nullptr)) {423      OS << "template-parameter-" << TTP->getDepth() << "-" << TTP->getIndex();424      return true;425    }426    return false;427  };428  if (NameKind Kind = getKind();429      Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) {430    // After `namespace ns { using std::vector }`, what is the fully-qualified431    // name of the UsingTemplateName `vector` within ns?432    //433    // - ns::vector (the qualified name of the using-shadow decl)434    // - std::vector (the qualified name of the underlying template decl)435    //436    // Similar to the UsingType behavior, using declarations are used to import437    // names more often than to export them, thus using the original name is438    // most useful in this case.439    TemplateDecl *Template = getAsTemplateDecl();440    if (Policy.PrintAsCanonical)441      Template = cast<TemplateDecl>(Template->getCanonicalDecl());442    if (handleAnonymousTTP(Template, OS))443      return;444    if (Qual == Qualified::None || isa<TemplateTemplateParmDecl>(Template) ||445        Policy.SuppressScope) {446      if (IdentifierInfo *II = Template->getIdentifier();447          Policy.CleanUglifiedParameters && II &&448          isa<TemplateTemplateParmDecl>(Template))449        OS << II->deuglifiedName();450      else451        OS << *Template;452    } else {453      PrintingPolicy NestedNamePolicy = Policy;454      NestedNamePolicy.SuppressUnwrittenScope = true;455      Template->printQualifiedName(OS, NestedNamePolicy);456    }457  } else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {458    if (Policy.PrintAsCanonical) {459      QTN->getUnderlyingTemplate().print(OS, Policy, Qual);460      return;461    }462    if (Qual != Qualified::None)463      QTN->getQualifier().print(OS, Policy);464    if (QTN->hasTemplateKeyword())465      OS << "template ";466 467    TemplateName Underlying = QTN->getUnderlyingTemplate();468    assert(Underlying.getKind() == TemplateName::Template ||469           Underlying.getKind() == TemplateName::UsingTemplate);470 471    TemplateDecl *UTD = Underlying.getAsTemplateDecl();472 473    if (handleAnonymousTTP(UTD, OS))474      return;475 476    OS << *UTD;477  } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {478    DTN->print(OS, Policy);479  } else if (SubstTemplateTemplateParmStorage *subst =480                 getAsSubstTemplateTemplateParm()) {481    subst->getReplacement().print(OS, Policy, Qual);482  } else if (SubstTemplateTemplateParmPackStorage *SubstPack =483                 getAsSubstTemplateTemplateParmPack())484    OS << *SubstPack->getParameterPack();485  else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {486    Assumed->getDeclName().print(OS, Policy);487  } else if (DeducedTemplateStorage *Deduced = getAsDeducedTemplateName()) {488    Deduced->getUnderlying().print(OS, Policy);489    DefaultArguments DefArgs = Deduced->getDefaultArguments();490    OS << ":" << DefArgs.StartPos;491    printTemplateArgumentList(OS, DefArgs.Args, Policy);492  } else {493    assert(getKind() == TemplateName::OverloadedTemplate);494    OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();495    (*OTS->begin())->printName(OS, Policy);496  }497}498 499const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,500                                             TemplateName N) {501  std::string NameStr;502  llvm::raw_string_ostream OS(NameStr);503  LangOptions LO;504  LO.CPlusPlus = true;505  LO.Bool = true;506  OS << '\'';507  N.print(OS, PrintingPolicy(LO));508  OS << '\'';509  return DB << NameStr;510}511