526 lines · cpp
1//===- DeclarationName.cpp - Declaration names implementation -------------===//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 implements the DeclarationName and DeclarationNameTable10// classes.11//12//===----------------------------------------------------------------------===//13 14#include "clang/AST/DeclarationName.h"15#include "clang/AST/ASTContext.h"16#include "clang/AST/Decl.h"17#include "clang/AST/DeclBase.h"18#include "clang/AST/DeclCXX.h"19#include "clang/AST/DeclTemplate.h"20#include "clang/AST/OpenMPClause.h"21#include "clang/AST/PrettyPrinter.h"22#include "clang/AST/Type.h"23#include "clang/AST/TypeLoc.h"24#include "clang/AST/TypeOrdering.h"25#include "clang/Basic/IdentifierTable.h"26#include "clang/Basic/LLVM.h"27#include "clang/Basic/LangOptions.h"28#include "clang/Basic/OperatorKinds.h"29#include "clang/Basic/SourceLocation.h"30#include "llvm/ADT/FoldingSet.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 <string>37 38using namespace clang;39 40static int compareInt(unsigned A, unsigned B) {41 return (A < B ? -1 : (A > B ? 1 : 0));42}43 44int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {45 if (LHS.getNameKind() != RHS.getNameKind())46 return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);47 48 switch (LHS.getNameKind()) {49 case DeclarationName::Identifier: {50 IdentifierInfo *LII = LHS.castAsIdentifierInfo();51 IdentifierInfo *RII = RHS.castAsIdentifierInfo();52 if (!LII)53 return RII ? -1 : 0;54 if (!RII)55 return 1;56 57 return LII->getName().compare(RII->getName());58 }59 60 case DeclarationName::ObjCZeroArgSelector:61 case DeclarationName::ObjCOneArgSelector:62 case DeclarationName::ObjCMultiArgSelector: {63 Selector LHSSelector = LHS.getObjCSelector();64 Selector RHSSelector = RHS.getObjCSelector();65 // getNumArgs for ZeroArgSelector returns 0, but we still need to compare.66 if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector &&67 RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) {68 return LHSSelector.getAsIdentifierInfo()->getName().compare(69 RHSSelector.getAsIdentifierInfo()->getName());70 }71 unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();72 for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {73 if (int Compare = LHSSelector.getNameForSlot(I).compare(74 RHSSelector.getNameForSlot(I)))75 return Compare;76 }77 78 return compareInt(LN, RN);79 }80 81 case DeclarationName::CXXConstructorName:82 case DeclarationName::CXXDestructorName:83 case DeclarationName::CXXConversionFunctionName:84 if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))85 return -1;86 if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))87 return 1;88 return 0;89 90 case DeclarationName::CXXDeductionGuideName:91 // We never want to compare deduction guide names for templates from92 // different scopes, so just compare the template-name.93 return compare(LHS.getCXXDeductionGuideTemplate()->getDeclName(),94 RHS.getCXXDeductionGuideTemplate()->getDeclName());95 96 case DeclarationName::CXXOperatorName:97 return compareInt(LHS.getCXXOverloadedOperator(),98 RHS.getCXXOverloadedOperator());99 100 case DeclarationName::CXXLiteralOperatorName:101 return LHS.getCXXLiteralIdentifier()->getName().compare(102 RHS.getCXXLiteralIdentifier()->getName());103 104 case DeclarationName::CXXUsingDirective:105 return 0;106 }107 108 llvm_unreachable("Invalid DeclarationName Kind!");109}110 111static void printCXXConstructorDestructorName(QualType ClassType,112 raw_ostream &OS,113 PrintingPolicy Policy) {114 // We know we're printing C++ here. Ensure we print types properly.115 Policy.adjustForCPlusPlus();116 Policy.SuppressScope = true;117 118 if (const RecordType *ClassRec = ClassType->getAsCanonical<RecordType>()) {119 ClassRec->getDecl()->printName(OS, Policy);120 return;121 }122 if (Policy.SuppressTemplateArgsInCXXConstructors) {123 if (auto *InjTy = ClassType->getAsCanonical<InjectedClassNameType>()) {124 InjTy->getDecl()->printName(OS, Policy);125 return;126 }127 }128 ClassType.print(OS, Policy);129}130 131void DeclarationName::print(raw_ostream &OS,132 const PrintingPolicy &Policy) const {133 switch (getNameKind()) {134 case DeclarationName::Identifier:135 if (const IdentifierInfo *II = getAsIdentifierInfo()) {136 StringRef 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.139 if (II->isMangledOpenMPVariantName()) {140 std::pair<StringRef, StringRef> NameContextPair =141 Name.split(getOpenMPVariantManglingSeparatorStr());142 OS << NameContextPair.first << "["143 << OMPTraitInfo(NameContextPair.second) << "]";144 } else {145 OS << Name;146 }147 }148 return;149 150 case DeclarationName::ObjCZeroArgSelector:151 case DeclarationName::ObjCOneArgSelector:152 case DeclarationName::ObjCMultiArgSelector:153 getObjCSelector().print(OS);154 return;155 156 case DeclarationName::CXXConstructorName:157 return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);158 159 case DeclarationName::CXXDestructorName:160 OS << '~';161 return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);162 163 case DeclarationName::CXXDeductionGuideName:164 OS << "<deduction guide for ";165 getCXXDeductionGuideTemplate()->getDeclName().print(OS, Policy);166 OS << '>';167 return;168 169 case DeclarationName::CXXOperatorName: {170 const char *OpName = getOperatorSpelling(getCXXOverloadedOperator());171 assert(OpName && "not an overloaded operator");172 173 OS << "operator";174 if (OpName[0] >= 'a' && OpName[0] <= 'z')175 OS << ' ';176 OS << OpName;177 return;178 }179 180 case DeclarationName::CXXLiteralOperatorName:181 OS << "operator\"\"" << getCXXLiteralIdentifier()->getName();182 return;183 184 case DeclarationName::CXXConversionFunctionName: {185 OS << "operator ";186 QualType Type = getCXXNameType();187 if (const RecordType *Rec = Type->getAs<RecordType>()) {188 OS << *Rec->getDecl();189 return;190 }191 // We know we're printing C++ here, ensure we print 'bool' properly.192 PrintingPolicy CXXPolicy = Policy;193 CXXPolicy.adjustForCPlusPlus();194 Type.print(OS, CXXPolicy);195 return;196 }197 case DeclarationName::CXXUsingDirective:198 OS << "<using-directive>";199 return;200 }201 202 llvm_unreachable("Unexpected declaration name kind");203}204 205namespace clang {206 207raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) {208 LangOptions LO;209 N.print(OS, PrintingPolicy(LO));210 return OS;211}212 213} // namespace clang214 215bool DeclarationName::isDependentName() const {216 QualType T = getCXXNameType();217 if (!T.isNull() && T->isDependentType())218 return true;219 220 // A class-scope deduction guide in a dependent context has a dependent name.221 auto *TD = getCXXDeductionGuideTemplate();222 if (TD && TD->getDeclContext()->isDependentContext())223 return true;224 225 return false;226}227 228std::string DeclarationName::getAsString() const {229 std::string Result;230 llvm::raw_string_ostream OS(Result);231 OS << *this;232 return Result;233}234 235void *DeclarationName::getFETokenInfoSlow() const {236 switch (getNameKind()) {237 case Identifier:238 llvm_unreachable("case Identifier already handled by getFETokenInfo!");239 case CXXConstructorName:240 case CXXDestructorName:241 case CXXConversionFunctionName:242 return castAsCXXSpecialNameExtra()->FETokenInfo;243 case CXXOperatorName:244 return castAsCXXOperatorIdName()->FETokenInfo;245 case CXXDeductionGuideName:246 return castAsCXXDeductionGuideNameExtra()->FETokenInfo;247 case CXXLiteralOperatorName:248 return castAsCXXLiteralOperatorIdName()->FETokenInfo;249 default:250 llvm_unreachable("DeclarationName has no FETokenInfo!");251 }252}253 254void DeclarationName::setFETokenInfoSlow(void *T) {255 switch (getNameKind()) {256 case Identifier:257 llvm_unreachable("case Identifier already handled by setFETokenInfo!");258 case CXXConstructorName:259 case CXXDestructorName:260 case CXXConversionFunctionName:261 castAsCXXSpecialNameExtra()->FETokenInfo = T;262 break;263 case CXXOperatorName:264 castAsCXXOperatorIdName()->FETokenInfo = T;265 break;266 case CXXDeductionGuideName:267 castAsCXXDeductionGuideNameExtra()->FETokenInfo = T;268 break;269 case CXXLiteralOperatorName:270 castAsCXXLiteralOperatorIdName()->FETokenInfo = T;271 break;272 default:273 llvm_unreachable("DeclarationName has no FETokenInfo!");274 }275}276 277LLVM_DUMP_METHOD void DeclarationName::dump() const {278 llvm::errs() << *this << '\n';279}280 281DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {282 // Initialize the overloaded operator names.283 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op)284 CXXOperatorNames[Op].Kind = static_cast<OverloadedOperatorKind>(Op);285}286 287DeclarationName288DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl *Template) {289 Template = cast<TemplateDecl>(Template->getCanonicalDecl());290 291 llvm::FoldingSetNodeID ID;292 ID.AddPointer(Template);293 294 void *InsertPos = nullptr;295 if (auto *Name = CXXDeductionGuideNames.FindNodeOrInsertPos(ID, InsertPos))296 return DeclarationName(Name);297 298 auto *Name = new (Ctx) detail::CXXDeductionGuideNameExtra(Template);299 CXXDeductionGuideNames.InsertNode(Name, InsertPos);300 return DeclarationName(Name);301}302 303DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) {304 // The type of constructors is unqualified.305 Ty = Ty.getUnqualifiedType();306 // Do we already have this C++ constructor name ?307 llvm::FoldingSetNodeID ID;308 ID.AddPointer(Ty.getAsOpaquePtr());309 void *InsertPos = nullptr;310 if (auto *Name = CXXConstructorNames.FindNodeOrInsertPos(ID, InsertPos))311 return {Name, DeclarationName::StoredCXXConstructorName};312 313 // We have to create it.314 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);315 CXXConstructorNames.InsertNode(SpecialName, InsertPos);316 return {SpecialName, DeclarationName::StoredCXXConstructorName};317}318 319DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) {320 // The type of destructors is unqualified.321 Ty = Ty.getUnqualifiedType();322 // Do we already have this C++ destructor name ?323 llvm::FoldingSetNodeID ID;324 ID.AddPointer(Ty.getAsOpaquePtr());325 void *InsertPos = nullptr;326 if (auto *Name = CXXDestructorNames.FindNodeOrInsertPos(ID, InsertPos))327 return {Name, DeclarationName::StoredCXXDestructorName};328 329 // We have to create it.330 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);331 CXXDestructorNames.InsertNode(SpecialName, InsertPos);332 return {SpecialName, DeclarationName::StoredCXXDestructorName};333}334 335DeclarationName336DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) {337 // Do we already have this C++ conversion function name ?338 llvm::FoldingSetNodeID ID;339 ID.AddPointer(Ty.getAsOpaquePtr());340 void *InsertPos = nullptr;341 if (auto *Name =342 CXXConversionFunctionNames.FindNodeOrInsertPos(ID, InsertPos))343 return {Name, DeclarationName::StoredCXXConversionFunctionName};344 345 // We have to create it.346 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);347 CXXConversionFunctionNames.InsertNode(SpecialName, InsertPos);348 return {SpecialName, DeclarationName::StoredCXXConversionFunctionName};349}350 351DeclarationName352DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,353 CanQualType Ty) {354 switch (Kind) {355 case DeclarationName::CXXConstructorName:356 return getCXXConstructorName(Ty);357 case DeclarationName::CXXDestructorName:358 return getCXXDestructorName(Ty);359 case DeclarationName::CXXConversionFunctionName:360 return getCXXConversionFunctionName(Ty);361 default:362 llvm_unreachable("Invalid kind in getCXXSpecialName!");363 }364}365 366DeclarationName367DeclarationNameTable::getCXXLiteralOperatorName(const IdentifierInfo *II) {368 llvm::FoldingSetNodeID ID;369 ID.AddPointer(II);370 371 void *InsertPos = nullptr;372 if (auto *Name = CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos))373 return DeclarationName(Name);374 375 auto *LiteralName = new (Ctx) detail::CXXLiteralOperatorIdName(II);376 CXXLiteralOperatorNames.InsertNode(LiteralName, InsertPos);377 return DeclarationName(LiteralName);378}379 380DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {381 switch (Name.getNameKind()) {382 case DeclarationName::Identifier:383 case DeclarationName::CXXDeductionGuideName:384 break;385 case DeclarationName::CXXConstructorName:386 case DeclarationName::CXXDestructorName:387 case DeclarationName::CXXConversionFunctionName:388 setNamedTypeLoc(nullptr);389 break;390 case DeclarationName::CXXOperatorName:391 setCXXOperatorNameRange(SourceRange());392 break;393 case DeclarationName::CXXLiteralOperatorName:394 setCXXLiteralOperatorNameLoc(SourceLocation());395 break;396 case DeclarationName::ObjCZeroArgSelector:397 case DeclarationName::ObjCOneArgSelector:398 case DeclarationName::ObjCMultiArgSelector:399 // FIXME: ?400 break;401 case DeclarationName::CXXUsingDirective:402 break;403 }404}405 406bool DeclarationNameInfo::containsUnexpandedParameterPack() const {407 switch (Name.getNameKind()) {408 case DeclarationName::Identifier:409 case DeclarationName::ObjCZeroArgSelector:410 case DeclarationName::ObjCOneArgSelector:411 case DeclarationName::ObjCMultiArgSelector:412 case DeclarationName::CXXOperatorName:413 case DeclarationName::CXXLiteralOperatorName:414 case DeclarationName::CXXUsingDirective:415 case DeclarationName::CXXDeductionGuideName:416 return false;417 418 case DeclarationName::CXXConstructorName:419 case DeclarationName::CXXDestructorName:420 case DeclarationName::CXXConversionFunctionName:421 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())422 return TInfo->getType()->containsUnexpandedParameterPack();423 424 return Name.getCXXNameType()->containsUnexpandedParameterPack();425 }426 llvm_unreachable("All name kinds handled.");427}428 429bool DeclarationNameInfo::isInstantiationDependent() const {430 switch (Name.getNameKind()) {431 case DeclarationName::Identifier:432 case DeclarationName::ObjCZeroArgSelector:433 case DeclarationName::ObjCOneArgSelector:434 case DeclarationName::ObjCMultiArgSelector:435 case DeclarationName::CXXOperatorName:436 case DeclarationName::CXXLiteralOperatorName:437 case DeclarationName::CXXUsingDirective:438 case DeclarationName::CXXDeductionGuideName:439 return false;440 441 case DeclarationName::CXXConstructorName:442 case DeclarationName::CXXDestructorName:443 case DeclarationName::CXXConversionFunctionName:444 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())445 return TInfo->getType()->isInstantiationDependentType();446 447 return Name.getCXXNameType()->isInstantiationDependentType();448 }449 llvm_unreachable("All name kinds handled.");450}451 452std::string DeclarationNameInfo::getAsString() const {453 std::string Result;454 llvm::raw_string_ostream OS(Result);455 OS << *this;456 return Result;457}458 459raw_ostream &clang::operator<<(raw_ostream &OS, DeclarationNameInfo DNInfo) {460 LangOptions LO;461 DNInfo.printName(OS, PrintingPolicy(LangOptions()));462 return OS;463}464 465void DeclarationNameInfo::printName(raw_ostream &OS, PrintingPolicy Policy) const {466 switch (Name.getNameKind()) {467 case DeclarationName::Identifier:468 case DeclarationName::ObjCZeroArgSelector:469 case DeclarationName::ObjCOneArgSelector:470 case DeclarationName::ObjCMultiArgSelector:471 case DeclarationName::CXXOperatorName:472 case DeclarationName::CXXLiteralOperatorName:473 case DeclarationName::CXXUsingDirective:474 case DeclarationName::CXXDeductionGuideName:475 Name.print(OS, Policy);476 return;477 478 case DeclarationName::CXXConstructorName:479 case DeclarationName::CXXDestructorName:480 case DeclarationName::CXXConversionFunctionName:481 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo()) {482 if (Name.getNameKind() == DeclarationName::CXXDestructorName)483 OS << '~';484 else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)485 OS << "operator ";486 LangOptions LO;487 Policy.adjustForCPlusPlus();488 Policy.SuppressScope = true;489 OS << TInfo->getType().getAsString(Policy);490 } else491 Name.print(OS, Policy);492 return;493 }494 llvm_unreachable("Unexpected declaration name kind");495}496 497SourceLocation DeclarationNameInfo::getEndLocPrivate() const {498 switch (Name.getNameKind()) {499 case DeclarationName::Identifier:500 case DeclarationName::CXXDeductionGuideName:501 return NameLoc;502 503 case DeclarationName::CXXOperatorName:504 return LocInfo.getCXXOperatorNameEndLoc();505 506 case DeclarationName::CXXLiteralOperatorName:507 return LocInfo.getCXXLiteralOperatorNameLoc();508 509 case DeclarationName::CXXConstructorName:510 case DeclarationName::CXXDestructorName:511 case DeclarationName::CXXConversionFunctionName:512 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())513 return TInfo->getTypeLoc().getEndLoc();514 else515 return NameLoc;516 517 // DNInfo work in progress: FIXME.518 case DeclarationName::ObjCZeroArgSelector:519 case DeclarationName::ObjCOneArgSelector:520 case DeclarationName::ObjCMultiArgSelector:521 case DeclarationName::CXXUsingDirective:522 return NameLoc;523 }524 llvm_unreachable("Unexpected declaration name kind");525}526