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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the DeclarationName and DeclarationNameTable 10 // 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/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> 38 39 using namespace clang; 40 41 static int compareInt(unsigned A, unsigned B) { 42 return (A < B ? -1 : (A > B ? 1 : 0)); 43 } 44 45 int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) { 46 if (LHS.getNameKind() != RHS.getNameKind()) 47 return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1); 48 49 switch (LHS.getNameKind()) { 50 case DeclarationName::Identifier: { 51 IdentifierInfo *LII = LHS.castAsIdentifierInfo(); 52 IdentifierInfo *RII = RHS.castAsIdentifierInfo(); 53 if (!LII) 54 return RII ? -1 : 0; 55 if (!RII) 56 return 1; 57 58 return LII->getName().compare(RII->getName()); 59 } 60 61 case DeclarationName::ObjCZeroArgSelector: 62 case DeclarationName::ObjCOneArgSelector: 63 case DeclarationName::ObjCMultiArgSelector: { 64 Selector LHSSelector = LHS.getObjCSelector(); 65 Selector RHSSelector = RHS.getObjCSelector(); 66 // getNumArgs for ZeroArgSelector returns 0, but we still need to compare. 67 if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector && 68 RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) { 69 return LHSSelector.getAsIdentifierInfo()->getName().compare( 70 RHSSelector.getAsIdentifierInfo()->getName()); 71 } 72 unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs(); 73 for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) { 74 switch (LHSSelector.getNameForSlot(I).compare( 75 RHSSelector.getNameForSlot(I))) { 76 case -1: 77 return -1; 78 case 1: 79 return 1; 80 default: 81 break; 82 } 83 } 84 85 return compareInt(LN, RN); 86 } 87 88 case DeclarationName::CXXConstructorName: 89 case DeclarationName::CXXDestructorName: 90 case DeclarationName::CXXConversionFunctionName: 91 if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType())) 92 return -1; 93 if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType())) 94 return 1; 95 return 0; 96 97 case DeclarationName::CXXDeductionGuideName: 98 // We never want to compare deduction guide names for templates from 99 // different scopes, so just compare the template-name. 100 return compare(LHS.getCXXDeductionGuideTemplate()->getDeclName(), 101 RHS.getCXXDeductionGuideTemplate()->getDeclName()); 102 103 case DeclarationName::CXXOperatorName: 104 return compareInt(LHS.getCXXOverloadedOperator(), 105 RHS.getCXXOverloadedOperator()); 106 107 case DeclarationName::CXXLiteralOperatorName: 108 return LHS.getCXXLiteralIdentifier()->getName().compare( 109 RHS.getCXXLiteralIdentifier()->getName()); 110 111 case DeclarationName::CXXUsingDirective: 112 return 0; 113 } 114 115 llvm_unreachable("Invalid DeclarationName Kind!"); 116 } 117 118 static void printCXXConstructorDestructorName(QualType ClassType, 119 raw_ostream &OS, 120 PrintingPolicy Policy) { 121 // We know we're printing C++ here. Ensure we print types properly. 122 Policy.adjustForCPlusPlus(); 123 124 if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) { 125 OS << *ClassRec->getDecl(); 126 return; 127 } 128 if (Policy.SuppressTemplateArgsInCXXConstructors) { 129 if (auto *InjTy = ClassType->getAs<InjectedClassNameType>()) { 130 OS << *InjTy->getDecl(); 131 return; 132 } 133 } 134 ClassType.print(OS, Policy); 135 } 136 137 void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) { 138 switch (getNameKind()) { 139 case DeclarationName::Identifier: 140 if (const IdentifierInfo *II = getAsIdentifierInfo()) 141 OS << II->getName(); 142 return; 143 144 case DeclarationName::ObjCZeroArgSelector: 145 case DeclarationName::ObjCOneArgSelector: 146 case DeclarationName::ObjCMultiArgSelector: 147 getObjCSelector().print(OS); 148 return; 149 150 case DeclarationName::CXXConstructorName: 151 return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy); 152 153 case DeclarationName::CXXDestructorName: 154 OS << '~'; 155 return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy); 156 157 case DeclarationName::CXXDeductionGuideName: 158 OS << "<deduction guide for "; 159 getCXXDeductionGuideTemplate()->getDeclName().print(OS, Policy); 160 OS << '>'; 161 return; 162 163 case DeclarationName::CXXOperatorName: { 164 static const char *const OperatorNames[NUM_OVERLOADED_OPERATORS] = { 165 nullptr, 166 #define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ 167 Spelling, 168 #include "clang/Basic/OperatorKinds.def" 169 }; 170 const char *OpName = OperatorNames[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 205 namespace clang { 206 207 raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) { 208 LangOptions LO; 209 N.print(OS, PrintingPolicy(LO)); 210 return OS; 211 } 212 213 } // namespace clang 214 215 bool 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 228 std::string DeclarationName::getAsString() const { 229 std::string Result; 230 llvm::raw_string_ostream OS(Result); 231 OS << *this; 232 return OS.str(); 233 } 234 235 void *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 254 void 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 277 LLVM_DUMP_METHOD void DeclarationName::dump() const { 278 llvm::errs() << *this << '\n'; 279 } 280 281 DeclarationNameTable::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 287 DeclarationName 288 DeclarationNameTable::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 303 DeclarationName 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 319 DeclarationName 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 335 DeclarationName 336 DeclarationNameTable::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 351 DeclarationName 352 DeclarationNameTable::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 366 DeclarationName 367 DeclarationNameTable::getCXXLiteralOperatorName(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 380 DeclarationNameLoc::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 NamedType.TInfo = nullptr; 389 break; 390 case DeclarationName::CXXOperatorName: 391 CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding(); 392 CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding(); 393 break; 394 case DeclarationName::CXXLiteralOperatorName: 395 CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding(); 396 break; 397 case DeclarationName::ObjCZeroArgSelector: 398 case DeclarationName::ObjCOneArgSelector: 399 case DeclarationName::ObjCMultiArgSelector: 400 // FIXME: ? 401 break; 402 case DeclarationName::CXXUsingDirective: 403 break; 404 } 405 } 406 407 bool DeclarationNameInfo::containsUnexpandedParameterPack() const { 408 switch (Name.getNameKind()) { 409 case DeclarationName::Identifier: 410 case DeclarationName::ObjCZeroArgSelector: 411 case DeclarationName::ObjCOneArgSelector: 412 case DeclarationName::ObjCMultiArgSelector: 413 case DeclarationName::CXXOperatorName: 414 case DeclarationName::CXXLiteralOperatorName: 415 case DeclarationName::CXXUsingDirective: 416 case DeclarationName::CXXDeductionGuideName: 417 return false; 418 419 case DeclarationName::CXXConstructorName: 420 case DeclarationName::CXXDestructorName: 421 case DeclarationName::CXXConversionFunctionName: 422 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) 423 return TInfo->getType()->containsUnexpandedParameterPack(); 424 425 return Name.getCXXNameType()->containsUnexpandedParameterPack(); 426 } 427 llvm_unreachable("All name kinds handled."); 428 } 429 430 bool DeclarationNameInfo::isInstantiationDependent() const { 431 switch (Name.getNameKind()) { 432 case DeclarationName::Identifier: 433 case DeclarationName::ObjCZeroArgSelector: 434 case DeclarationName::ObjCOneArgSelector: 435 case DeclarationName::ObjCMultiArgSelector: 436 case DeclarationName::CXXOperatorName: 437 case DeclarationName::CXXLiteralOperatorName: 438 case DeclarationName::CXXUsingDirective: 439 case DeclarationName::CXXDeductionGuideName: 440 return false; 441 442 case DeclarationName::CXXConstructorName: 443 case DeclarationName::CXXDestructorName: 444 case DeclarationName::CXXConversionFunctionName: 445 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) 446 return TInfo->getType()->isInstantiationDependentType(); 447 448 return Name.getCXXNameType()->isInstantiationDependentType(); 449 } 450 llvm_unreachable("All name kinds handled."); 451 } 452 453 std::string DeclarationNameInfo::getAsString() const { 454 std::string Result; 455 llvm::raw_string_ostream OS(Result); 456 printName(OS); 457 return OS.str(); 458 } 459 460 void DeclarationNameInfo::printName(raw_ostream &OS) const { 461 switch (Name.getNameKind()) { 462 case DeclarationName::Identifier: 463 case DeclarationName::ObjCZeroArgSelector: 464 case DeclarationName::ObjCOneArgSelector: 465 case DeclarationName::ObjCMultiArgSelector: 466 case DeclarationName::CXXOperatorName: 467 case DeclarationName::CXXLiteralOperatorName: 468 case DeclarationName::CXXUsingDirective: 469 case DeclarationName::CXXDeductionGuideName: 470 OS << Name; 471 return; 472 473 case DeclarationName::CXXConstructorName: 474 case DeclarationName::CXXDestructorName: 475 case DeclarationName::CXXConversionFunctionName: 476 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) { 477 if (Name.getNameKind() == DeclarationName::CXXDestructorName) 478 OS << '~'; 479 else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) 480 OS << "operator "; 481 LangOptions LO; 482 LO.CPlusPlus = true; 483 LO.Bool = true; 484 PrintingPolicy PP(LO); 485 PP.SuppressScope = true; 486 OS << TInfo->getType().getAsString(PP); 487 } else 488 OS << Name; 489 return; 490 } 491 llvm_unreachable("Unexpected declaration name kind"); 492 } 493 494 SourceLocation DeclarationNameInfo::getEndLocPrivate() const { 495 switch (Name.getNameKind()) { 496 case DeclarationName::Identifier: 497 case DeclarationName::CXXDeductionGuideName: 498 return NameLoc; 499 500 case DeclarationName::CXXOperatorName: { 501 unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc; 502 return SourceLocation::getFromRawEncoding(raw); 503 } 504 505 case DeclarationName::CXXLiteralOperatorName: { 506 unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc; 507 return SourceLocation::getFromRawEncoding(raw); 508 } 509 510 case DeclarationName::CXXConstructorName: 511 case DeclarationName::CXXDestructorName: 512 case DeclarationName::CXXConversionFunctionName: 513 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) 514 return TInfo->getTypeLoc().getEndLoc(); 515 else 516 return NameLoc; 517 518 // DNInfo work in progress: FIXME. 519 case DeclarationName::ObjCZeroArgSelector: 520 case DeclarationName::ObjCOneArgSelector: 521 case DeclarationName::ObjCMultiArgSelector: 522 case DeclarationName::CXXUsingDirective: 523 return NameLoc; 524 } 525 llvm_unreachable("Unexpected declaration name kind"); 526 } 527