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