Path: blob/main/contrib/llvm-project/clang/lib/AST/DeclarationName.cpp
35260 views
//===- DeclarationName.cpp - Declaration names implementation -------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the DeclarationName and DeclarationNameTable9// classes.10//11//===----------------------------------------------------------------------===//1213#include "clang/AST/DeclarationName.h"14#include "clang/AST/ASTContext.h"15#include "clang/AST/Decl.h"16#include "clang/AST/DeclBase.h"17#include "clang/AST/DeclCXX.h"18#include "clang/AST/DeclTemplate.h"19#include "clang/AST/OpenMPClause.h"20#include "clang/AST/PrettyPrinter.h"21#include "clang/AST/Type.h"22#include "clang/AST/TypeLoc.h"23#include "clang/AST/TypeOrdering.h"24#include "clang/Basic/IdentifierTable.h"25#include "clang/Basic/LLVM.h"26#include "clang/Basic/LangOptions.h"27#include "clang/Basic/OperatorKinds.h"28#include "clang/Basic/SourceLocation.h"29#include "llvm/ADT/FoldingSet.h"30#include "llvm/Support/Casting.h"31#include "llvm/Support/Compiler.h"32#include "llvm/Support/ErrorHandling.h"33#include "llvm/Support/raw_ostream.h"34#include <algorithm>35#include <cassert>36#include <cstdint>37#include <string>3839using namespace clang;4041static int compareInt(unsigned A, unsigned B) {42return (A < B ? -1 : (A > B ? 1 : 0));43}4445int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {46if (LHS.getNameKind() != RHS.getNameKind())47return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);4849switch (LHS.getNameKind()) {50case DeclarationName::Identifier: {51IdentifierInfo *LII = LHS.castAsIdentifierInfo();52IdentifierInfo *RII = RHS.castAsIdentifierInfo();53if (!LII)54return RII ? -1 : 0;55if (!RII)56return 1;5758return LII->getName().compare(RII->getName());59}6061case DeclarationName::ObjCZeroArgSelector:62case DeclarationName::ObjCOneArgSelector:63case DeclarationName::ObjCMultiArgSelector: {64Selector LHSSelector = LHS.getObjCSelector();65Selector RHSSelector = RHS.getObjCSelector();66// getNumArgs for ZeroArgSelector returns 0, but we still need to compare.67if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector &&68RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) {69return LHSSelector.getAsIdentifierInfo()->getName().compare(70RHSSelector.getAsIdentifierInfo()->getName());71}72unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();73for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {74if (int Compare = LHSSelector.getNameForSlot(I).compare(75RHSSelector.getNameForSlot(I)))76return Compare;77}7879return compareInt(LN, RN);80}8182case DeclarationName::CXXConstructorName:83case DeclarationName::CXXDestructorName:84case DeclarationName::CXXConversionFunctionName:85if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))86return -1;87if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))88return 1;89return 0;9091case DeclarationName::CXXDeductionGuideName:92// We never want to compare deduction guide names for templates from93// different scopes, so just compare the template-name.94return compare(LHS.getCXXDeductionGuideTemplate()->getDeclName(),95RHS.getCXXDeductionGuideTemplate()->getDeclName());9697case DeclarationName::CXXOperatorName:98return compareInt(LHS.getCXXOverloadedOperator(),99RHS.getCXXOverloadedOperator());100101case DeclarationName::CXXLiteralOperatorName:102return LHS.getCXXLiteralIdentifier()->getName().compare(103RHS.getCXXLiteralIdentifier()->getName());104105case DeclarationName::CXXUsingDirective:106return 0;107}108109llvm_unreachable("Invalid DeclarationName Kind!");110}111112static void printCXXConstructorDestructorName(QualType ClassType,113raw_ostream &OS,114PrintingPolicy Policy) {115// We know we're printing C++ here. Ensure we print types properly.116Policy.adjustForCPlusPlus();117118if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) {119ClassRec->getDecl()->printName(OS, Policy);120return;121}122if (Policy.SuppressTemplateArgsInCXXConstructors) {123if (auto *InjTy = ClassType->getAs<InjectedClassNameType>()) {124InjTy->getDecl()->printName(OS, Policy);125return;126}127}128ClassType.print(OS, Policy);129}130131void DeclarationName::print(raw_ostream &OS,132const PrintingPolicy &Policy) const {133switch (getNameKind()) {134case DeclarationName::Identifier:135if (const IdentifierInfo *II = getAsIdentifierInfo()) {136StringRef Name = II->getName();137// If this is a mangled OpenMP variant name we strip off the mangling for138// printing. It should not be visible to the user at all.139if (II->isMangledOpenMPVariantName()) {140std::pair<StringRef, StringRef> NameContextPair =141Name.split(getOpenMPVariantManglingSeparatorStr());142OS << NameContextPair.first << "["143<< OMPTraitInfo(NameContextPair.second) << "]";144} else {145OS << Name;146}147}148return;149150case DeclarationName::ObjCZeroArgSelector:151case DeclarationName::ObjCOneArgSelector:152case DeclarationName::ObjCMultiArgSelector:153getObjCSelector().print(OS);154return;155156case DeclarationName::CXXConstructorName:157return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);158159case DeclarationName::CXXDestructorName:160OS << '~';161return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);162163case DeclarationName::CXXDeductionGuideName:164OS << "<deduction guide for ";165getCXXDeductionGuideTemplate()->getDeclName().print(OS, Policy);166OS << '>';167return;168169case DeclarationName::CXXOperatorName: {170const char *OpName = getOperatorSpelling(getCXXOverloadedOperator());171assert(OpName && "not an overloaded operator");172173OS << "operator";174if (OpName[0] >= 'a' && OpName[0] <= 'z')175OS << ' ';176OS << OpName;177return;178}179180case DeclarationName::CXXLiteralOperatorName:181OS << "operator\"\"" << getCXXLiteralIdentifier()->getName();182return;183184case DeclarationName::CXXConversionFunctionName: {185OS << "operator ";186QualType Type = getCXXNameType();187if (const RecordType *Rec = Type->getAs<RecordType>()) {188OS << *Rec->getDecl();189return;190}191// We know we're printing C++ here, ensure we print 'bool' properly.192PrintingPolicy CXXPolicy = Policy;193CXXPolicy.adjustForCPlusPlus();194Type.print(OS, CXXPolicy);195return;196}197case DeclarationName::CXXUsingDirective:198OS << "<using-directive>";199return;200}201202llvm_unreachable("Unexpected declaration name kind");203}204205namespace clang {206207raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) {208LangOptions LO;209N.print(OS, PrintingPolicy(LO));210return OS;211}212213} // namespace clang214215bool DeclarationName::isDependentName() const {216QualType T = getCXXNameType();217if (!T.isNull() && T->isDependentType())218return true;219220// A class-scope deduction guide in a dependent context has a dependent name.221auto *TD = getCXXDeductionGuideTemplate();222if (TD && TD->getDeclContext()->isDependentContext())223return true;224225return false;226}227228std::string DeclarationName::getAsString() const {229std::string Result;230llvm::raw_string_ostream OS(Result);231OS << *this;232return Result;233}234235void *DeclarationName::getFETokenInfoSlow() const {236switch (getNameKind()) {237case Identifier:238llvm_unreachable("case Identifier already handled by getFETokenInfo!");239case CXXConstructorName:240case CXXDestructorName:241case CXXConversionFunctionName:242return castAsCXXSpecialNameExtra()->FETokenInfo;243case CXXOperatorName:244return castAsCXXOperatorIdName()->FETokenInfo;245case CXXDeductionGuideName:246return castAsCXXDeductionGuideNameExtra()->FETokenInfo;247case CXXLiteralOperatorName:248return castAsCXXLiteralOperatorIdName()->FETokenInfo;249default:250llvm_unreachable("DeclarationName has no FETokenInfo!");251}252}253254void DeclarationName::setFETokenInfoSlow(void *T) {255switch (getNameKind()) {256case Identifier:257llvm_unreachable("case Identifier already handled by setFETokenInfo!");258case CXXConstructorName:259case CXXDestructorName:260case CXXConversionFunctionName:261castAsCXXSpecialNameExtra()->FETokenInfo = T;262break;263case CXXOperatorName:264castAsCXXOperatorIdName()->FETokenInfo = T;265break;266case CXXDeductionGuideName:267castAsCXXDeductionGuideNameExtra()->FETokenInfo = T;268break;269case CXXLiteralOperatorName:270castAsCXXLiteralOperatorIdName()->FETokenInfo = T;271break;272default:273llvm_unreachable("DeclarationName has no FETokenInfo!");274}275}276277LLVM_DUMP_METHOD void DeclarationName::dump() const {278llvm::errs() << *this << '\n';279}280281DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {282// Initialize the overloaded operator names.283for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op)284CXXOperatorNames[Op].Kind = static_cast<OverloadedOperatorKind>(Op);285}286287DeclarationName288DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl *Template) {289Template = cast<TemplateDecl>(Template->getCanonicalDecl());290291llvm::FoldingSetNodeID ID;292ID.AddPointer(Template);293294void *InsertPos = nullptr;295if (auto *Name = CXXDeductionGuideNames.FindNodeOrInsertPos(ID, InsertPos))296return DeclarationName(Name);297298auto *Name = new (Ctx) detail::CXXDeductionGuideNameExtra(Template);299CXXDeductionGuideNames.InsertNode(Name, InsertPos);300return DeclarationName(Name);301}302303DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) {304// The type of constructors is unqualified.305Ty = Ty.getUnqualifiedType();306// Do we already have this C++ constructor name ?307llvm::FoldingSetNodeID ID;308ID.AddPointer(Ty.getAsOpaquePtr());309void *InsertPos = nullptr;310if (auto *Name = CXXConstructorNames.FindNodeOrInsertPos(ID, InsertPos))311return {Name, DeclarationName::StoredCXXConstructorName};312313// We have to create it.314auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);315CXXConstructorNames.InsertNode(SpecialName, InsertPos);316return {SpecialName, DeclarationName::StoredCXXConstructorName};317}318319DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) {320// The type of destructors is unqualified.321Ty = Ty.getUnqualifiedType();322// Do we already have this C++ destructor name ?323llvm::FoldingSetNodeID ID;324ID.AddPointer(Ty.getAsOpaquePtr());325void *InsertPos = nullptr;326if (auto *Name = CXXDestructorNames.FindNodeOrInsertPos(ID, InsertPos))327return {Name, DeclarationName::StoredCXXDestructorName};328329// We have to create it.330auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);331CXXDestructorNames.InsertNode(SpecialName, InsertPos);332return {SpecialName, DeclarationName::StoredCXXDestructorName};333}334335DeclarationName336DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) {337// Do we already have this C++ conversion function name ?338llvm::FoldingSetNodeID ID;339ID.AddPointer(Ty.getAsOpaquePtr());340void *InsertPos = nullptr;341if (auto *Name =342CXXConversionFunctionNames.FindNodeOrInsertPos(ID, InsertPos))343return {Name, DeclarationName::StoredCXXConversionFunctionName};344345// We have to create it.346auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);347CXXConversionFunctionNames.InsertNode(SpecialName, InsertPos);348return {SpecialName, DeclarationName::StoredCXXConversionFunctionName};349}350351DeclarationName352DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,353CanQualType Ty) {354switch (Kind) {355case DeclarationName::CXXConstructorName:356return getCXXConstructorName(Ty);357case DeclarationName::CXXDestructorName:358return getCXXDestructorName(Ty);359case DeclarationName::CXXConversionFunctionName:360return getCXXConversionFunctionName(Ty);361default:362llvm_unreachable("Invalid kind in getCXXSpecialName!");363}364}365366DeclarationName367DeclarationNameTable::getCXXLiteralOperatorName(const IdentifierInfo *II) {368llvm::FoldingSetNodeID ID;369ID.AddPointer(II);370371void *InsertPos = nullptr;372if (auto *Name = CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos))373return DeclarationName(Name);374375auto *LiteralName = new (Ctx) detail::CXXLiteralOperatorIdName(II);376CXXLiteralOperatorNames.InsertNode(LiteralName, InsertPos);377return DeclarationName(LiteralName);378}379380DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {381switch (Name.getNameKind()) {382case DeclarationName::Identifier:383case DeclarationName::CXXDeductionGuideName:384break;385case DeclarationName::CXXConstructorName:386case DeclarationName::CXXDestructorName:387case DeclarationName::CXXConversionFunctionName:388setNamedTypeLoc(nullptr);389break;390case DeclarationName::CXXOperatorName:391setCXXOperatorNameRange(SourceRange());392break;393case DeclarationName::CXXLiteralOperatorName:394setCXXLiteralOperatorNameLoc(SourceLocation());395break;396case DeclarationName::ObjCZeroArgSelector:397case DeclarationName::ObjCOneArgSelector:398case DeclarationName::ObjCMultiArgSelector:399// FIXME: ?400break;401case DeclarationName::CXXUsingDirective:402break;403}404}405406bool DeclarationNameInfo::containsUnexpandedParameterPack() const {407switch (Name.getNameKind()) {408case DeclarationName::Identifier:409case DeclarationName::ObjCZeroArgSelector:410case DeclarationName::ObjCOneArgSelector:411case DeclarationName::ObjCMultiArgSelector:412case DeclarationName::CXXOperatorName:413case DeclarationName::CXXLiteralOperatorName:414case DeclarationName::CXXUsingDirective:415case DeclarationName::CXXDeductionGuideName:416return false;417418case DeclarationName::CXXConstructorName:419case DeclarationName::CXXDestructorName:420case DeclarationName::CXXConversionFunctionName:421if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())422return TInfo->getType()->containsUnexpandedParameterPack();423424return Name.getCXXNameType()->containsUnexpandedParameterPack();425}426llvm_unreachable("All name kinds handled.");427}428429bool DeclarationNameInfo::isInstantiationDependent() const {430switch (Name.getNameKind()) {431case DeclarationName::Identifier:432case DeclarationName::ObjCZeroArgSelector:433case DeclarationName::ObjCOneArgSelector:434case DeclarationName::ObjCMultiArgSelector:435case DeclarationName::CXXOperatorName:436case DeclarationName::CXXLiteralOperatorName:437case DeclarationName::CXXUsingDirective:438case DeclarationName::CXXDeductionGuideName:439return false;440441case DeclarationName::CXXConstructorName:442case DeclarationName::CXXDestructorName:443case DeclarationName::CXXConversionFunctionName:444if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())445return TInfo->getType()->isInstantiationDependentType();446447return Name.getCXXNameType()->isInstantiationDependentType();448}449llvm_unreachable("All name kinds handled.");450}451452std::string DeclarationNameInfo::getAsString() const {453std::string Result;454llvm::raw_string_ostream OS(Result);455OS << *this;456return Result;457}458459raw_ostream &clang::operator<<(raw_ostream &OS, DeclarationNameInfo DNInfo) {460LangOptions LO;461DNInfo.printName(OS, PrintingPolicy(LangOptions()));462return OS;463}464465void DeclarationNameInfo::printName(raw_ostream &OS, PrintingPolicy Policy) const {466switch (Name.getNameKind()) {467case DeclarationName::Identifier:468case DeclarationName::ObjCZeroArgSelector:469case DeclarationName::ObjCOneArgSelector:470case DeclarationName::ObjCMultiArgSelector:471case DeclarationName::CXXOperatorName:472case DeclarationName::CXXLiteralOperatorName:473case DeclarationName::CXXUsingDirective:474case DeclarationName::CXXDeductionGuideName:475Name.print(OS, Policy);476return;477478case DeclarationName::CXXConstructorName:479case DeclarationName::CXXDestructorName:480case DeclarationName::CXXConversionFunctionName:481if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo()) {482if (Name.getNameKind() == DeclarationName::CXXDestructorName)483OS << '~';484else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)485OS << "operator ";486LangOptions LO;487Policy.adjustForCPlusPlus();488Policy.SuppressScope = true;489OS << TInfo->getType().getAsString(Policy);490} else491Name.print(OS, Policy);492return;493}494llvm_unreachable("Unexpected declaration name kind");495}496497SourceLocation DeclarationNameInfo::getEndLocPrivate() const {498switch (Name.getNameKind()) {499case DeclarationName::Identifier:500case DeclarationName::CXXDeductionGuideName:501return NameLoc;502503case DeclarationName::CXXOperatorName:504return LocInfo.getCXXOperatorNameEndLoc();505506case DeclarationName::CXXLiteralOperatorName:507return LocInfo.getCXXLiteralOperatorNameLoc();508509case DeclarationName::CXXConstructorName:510case DeclarationName::CXXDestructorName:511case DeclarationName::CXXConversionFunctionName:512if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())513return TInfo->getTypeLoc().getEndLoc();514else515return NameLoc;516517// DNInfo work in progress: FIXME.518case DeclarationName::ObjCZeroArgSelector:519case DeclarationName::ObjCOneArgSelector:520case DeclarationName::ObjCMultiArgSelector:521case DeclarationName::CXXUsingDirective:522return NameLoc;523}524llvm_unreachable("Unexpected declaration name kind");525}526527528