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, 138 const PrintingPolicy &Policy) const { 139 switch (getNameKind()) { 140 case DeclarationName::Identifier: 141 if (const IdentifierInfo *II = getAsIdentifierInfo()) 142 OS << II->getName(); 143 return; 144 145 case DeclarationName::ObjCZeroArgSelector: 146 case DeclarationName::ObjCOneArgSelector: 147 case DeclarationName::ObjCMultiArgSelector: 148 getObjCSelector().print(OS); 149 return; 150 151 case DeclarationName::CXXConstructorName: 152 return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy); 153 154 case DeclarationName::CXXDestructorName: 155 OS << '~'; 156 return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy); 157 158 case DeclarationName::CXXDeductionGuideName: 159 OS << "<deduction guide for "; 160 getCXXDeductionGuideTemplate()->getDeclName().print(OS, Policy); 161 OS << '>'; 162 return; 163 164 case DeclarationName::CXXOperatorName: { 165 const char *OpName = getOperatorSpelling(getCXXOverloadedOperator()); 166 assert(OpName && "not an overloaded operator"); 167 168 OS << "operator"; 169 if (OpName[0] >= 'a' && OpName[0] <= 'z') 170 OS << ' '; 171 OS << OpName; 172 return; 173 } 174 175 case DeclarationName::CXXLiteralOperatorName: 176 OS << "operator\"\"" << getCXXLiteralIdentifier()->getName(); 177 return; 178 179 case DeclarationName::CXXConversionFunctionName: { 180 OS << "operator "; 181 QualType Type = getCXXNameType(); 182 if (const RecordType *Rec = Type->getAs<RecordType>()) { 183 OS << *Rec->getDecl(); 184 return; 185 } 186 // We know we're printing C++ here, ensure we print 'bool' properly. 187 PrintingPolicy CXXPolicy = Policy; 188 CXXPolicy.adjustForCPlusPlus(); 189 Type.print(OS, CXXPolicy); 190 return; 191 } 192 case DeclarationName::CXXUsingDirective: 193 OS << "<using-directive>"; 194 return; 195 } 196 197 llvm_unreachable("Unexpected declaration name kind"); 198 } 199 200 namespace clang { 201 202 raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) { 203 LangOptions LO; 204 N.print(OS, PrintingPolicy(LO)); 205 return OS; 206 } 207 208 } // namespace clang 209 210 bool DeclarationName::isDependentName() const { 211 QualType T = getCXXNameType(); 212 if (!T.isNull() && T->isDependentType()) 213 return true; 214 215 // A class-scope deduction guide in a dependent context has a dependent name. 216 auto *TD = getCXXDeductionGuideTemplate(); 217 if (TD && TD->getDeclContext()->isDependentContext()) 218 return true; 219 220 return false; 221 } 222 223 std::string DeclarationName::getAsString() const { 224 std::string Result; 225 llvm::raw_string_ostream OS(Result); 226 OS << *this; 227 return OS.str(); 228 } 229 230 void *DeclarationName::getFETokenInfoSlow() const { 231 switch (getNameKind()) { 232 case Identifier: 233 llvm_unreachable("case Identifier already handled by getFETokenInfo!"); 234 case CXXConstructorName: 235 case CXXDestructorName: 236 case CXXConversionFunctionName: 237 return castAsCXXSpecialNameExtra()->FETokenInfo; 238 case CXXOperatorName: 239 return castAsCXXOperatorIdName()->FETokenInfo; 240 case CXXDeductionGuideName: 241 return castAsCXXDeductionGuideNameExtra()->FETokenInfo; 242 case CXXLiteralOperatorName: 243 return castAsCXXLiteralOperatorIdName()->FETokenInfo; 244 default: 245 llvm_unreachable("DeclarationName has no FETokenInfo!"); 246 } 247 } 248 249 void DeclarationName::setFETokenInfoSlow(void *T) { 250 switch (getNameKind()) { 251 case Identifier: 252 llvm_unreachable("case Identifier already handled by setFETokenInfo!"); 253 case CXXConstructorName: 254 case CXXDestructorName: 255 case CXXConversionFunctionName: 256 castAsCXXSpecialNameExtra()->FETokenInfo = T; 257 break; 258 case CXXOperatorName: 259 castAsCXXOperatorIdName()->FETokenInfo = T; 260 break; 261 case CXXDeductionGuideName: 262 castAsCXXDeductionGuideNameExtra()->FETokenInfo = T; 263 break; 264 case CXXLiteralOperatorName: 265 castAsCXXLiteralOperatorIdName()->FETokenInfo = T; 266 break; 267 default: 268 llvm_unreachable("DeclarationName has no FETokenInfo!"); 269 } 270 } 271 272 LLVM_DUMP_METHOD void DeclarationName::dump() const { 273 llvm::errs() << *this << '\n'; 274 } 275 276 DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) { 277 // Initialize the overloaded operator names. 278 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) 279 CXXOperatorNames[Op].Kind = static_cast<OverloadedOperatorKind>(Op); 280 } 281 282 DeclarationName 283 DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl *Template) { 284 Template = cast<TemplateDecl>(Template->getCanonicalDecl()); 285 286 llvm::FoldingSetNodeID ID; 287 ID.AddPointer(Template); 288 289 void *InsertPos = nullptr; 290 if (auto *Name = CXXDeductionGuideNames.FindNodeOrInsertPos(ID, InsertPos)) 291 return DeclarationName(Name); 292 293 auto *Name = new (Ctx) detail::CXXDeductionGuideNameExtra(Template); 294 CXXDeductionGuideNames.InsertNode(Name, InsertPos); 295 return DeclarationName(Name); 296 } 297 298 DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) { 299 // The type of constructors is unqualified. 300 Ty = Ty.getUnqualifiedType(); 301 // Do we already have this C++ constructor name ? 302 llvm::FoldingSetNodeID ID; 303 ID.AddPointer(Ty.getAsOpaquePtr()); 304 void *InsertPos = nullptr; 305 if (auto *Name = CXXConstructorNames.FindNodeOrInsertPos(ID, InsertPos)) 306 return {Name, DeclarationName::StoredCXXConstructorName}; 307 308 // We have to create it. 309 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty); 310 CXXConstructorNames.InsertNode(SpecialName, InsertPos); 311 return {SpecialName, DeclarationName::StoredCXXConstructorName}; 312 } 313 314 DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) { 315 // The type of destructors is unqualified. 316 Ty = Ty.getUnqualifiedType(); 317 // Do we already have this C++ destructor name ? 318 llvm::FoldingSetNodeID ID; 319 ID.AddPointer(Ty.getAsOpaquePtr()); 320 void *InsertPos = nullptr; 321 if (auto *Name = CXXDestructorNames.FindNodeOrInsertPos(ID, InsertPos)) 322 return {Name, DeclarationName::StoredCXXDestructorName}; 323 324 // We have to create it. 325 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty); 326 CXXDestructorNames.InsertNode(SpecialName, InsertPos); 327 return {SpecialName, DeclarationName::StoredCXXDestructorName}; 328 } 329 330 DeclarationName 331 DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) { 332 // Do we already have this C++ conversion function name ? 333 llvm::FoldingSetNodeID ID; 334 ID.AddPointer(Ty.getAsOpaquePtr()); 335 void *InsertPos = nullptr; 336 if (auto *Name = 337 CXXConversionFunctionNames.FindNodeOrInsertPos(ID, InsertPos)) 338 return {Name, DeclarationName::StoredCXXConversionFunctionName}; 339 340 // We have to create it. 341 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty); 342 CXXConversionFunctionNames.InsertNode(SpecialName, InsertPos); 343 return {SpecialName, DeclarationName::StoredCXXConversionFunctionName}; 344 } 345 346 DeclarationName 347 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind, 348 CanQualType Ty) { 349 switch (Kind) { 350 case DeclarationName::CXXConstructorName: 351 return getCXXConstructorName(Ty); 352 case DeclarationName::CXXDestructorName: 353 return getCXXDestructorName(Ty); 354 case DeclarationName::CXXConversionFunctionName: 355 return getCXXConversionFunctionName(Ty); 356 default: 357 llvm_unreachable("Invalid kind in getCXXSpecialName!"); 358 } 359 } 360 361 DeclarationName 362 DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) { 363 llvm::FoldingSetNodeID ID; 364 ID.AddPointer(II); 365 366 void *InsertPos = nullptr; 367 if (auto *Name = CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos)) 368 return DeclarationName(Name); 369 370 auto *LiteralName = new (Ctx) detail::CXXLiteralOperatorIdName(II); 371 CXXLiteralOperatorNames.InsertNode(LiteralName, InsertPos); 372 return DeclarationName(LiteralName); 373 } 374 375 DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) { 376 switch (Name.getNameKind()) { 377 case DeclarationName::Identifier: 378 case DeclarationName::CXXDeductionGuideName: 379 break; 380 case DeclarationName::CXXConstructorName: 381 case DeclarationName::CXXDestructorName: 382 case DeclarationName::CXXConversionFunctionName: 383 NamedType.TInfo = nullptr; 384 break; 385 case DeclarationName::CXXOperatorName: 386 CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding(); 387 CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding(); 388 break; 389 case DeclarationName::CXXLiteralOperatorName: 390 CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding(); 391 break; 392 case DeclarationName::ObjCZeroArgSelector: 393 case DeclarationName::ObjCOneArgSelector: 394 case DeclarationName::ObjCMultiArgSelector: 395 // FIXME: ? 396 break; 397 case DeclarationName::CXXUsingDirective: 398 break; 399 } 400 } 401 402 bool DeclarationNameInfo::containsUnexpandedParameterPack() const { 403 switch (Name.getNameKind()) { 404 case DeclarationName::Identifier: 405 case DeclarationName::ObjCZeroArgSelector: 406 case DeclarationName::ObjCOneArgSelector: 407 case DeclarationName::ObjCMultiArgSelector: 408 case DeclarationName::CXXOperatorName: 409 case DeclarationName::CXXLiteralOperatorName: 410 case DeclarationName::CXXUsingDirective: 411 case DeclarationName::CXXDeductionGuideName: 412 return false; 413 414 case DeclarationName::CXXConstructorName: 415 case DeclarationName::CXXDestructorName: 416 case DeclarationName::CXXConversionFunctionName: 417 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) 418 return TInfo->getType()->containsUnexpandedParameterPack(); 419 420 return Name.getCXXNameType()->containsUnexpandedParameterPack(); 421 } 422 llvm_unreachable("All name kinds handled."); 423 } 424 425 bool DeclarationNameInfo::isInstantiationDependent() const { 426 switch (Name.getNameKind()) { 427 case DeclarationName::Identifier: 428 case DeclarationName::ObjCZeroArgSelector: 429 case DeclarationName::ObjCOneArgSelector: 430 case DeclarationName::ObjCMultiArgSelector: 431 case DeclarationName::CXXOperatorName: 432 case DeclarationName::CXXLiteralOperatorName: 433 case DeclarationName::CXXUsingDirective: 434 case DeclarationName::CXXDeductionGuideName: 435 return false; 436 437 case DeclarationName::CXXConstructorName: 438 case DeclarationName::CXXDestructorName: 439 case DeclarationName::CXXConversionFunctionName: 440 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) 441 return TInfo->getType()->isInstantiationDependentType(); 442 443 return Name.getCXXNameType()->isInstantiationDependentType(); 444 } 445 llvm_unreachable("All name kinds handled."); 446 } 447 448 std::string DeclarationNameInfo::getAsString() const { 449 std::string Result; 450 llvm::raw_string_ostream OS(Result); 451 OS << *this; 452 return OS.str(); 453 } 454 455 raw_ostream &clang::operator<<(raw_ostream &OS, DeclarationNameInfo DNInfo) { 456 LangOptions LO; 457 DNInfo.printName(OS, PrintingPolicy(LangOptions())); 458 return OS; 459 } 460 461 void DeclarationNameInfo::printName(raw_ostream &OS, PrintingPolicy Policy) const { 462 switch (Name.getNameKind()) { 463 case DeclarationName::Identifier: 464 case DeclarationName::ObjCZeroArgSelector: 465 case DeclarationName::ObjCOneArgSelector: 466 case DeclarationName::ObjCMultiArgSelector: 467 case DeclarationName::CXXOperatorName: 468 case DeclarationName::CXXLiteralOperatorName: 469 case DeclarationName::CXXUsingDirective: 470 case DeclarationName::CXXDeductionGuideName: 471 Name.print(OS, Policy); 472 return; 473 474 case DeclarationName::CXXConstructorName: 475 case DeclarationName::CXXDestructorName: 476 case DeclarationName::CXXConversionFunctionName: 477 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) { 478 if (Name.getNameKind() == DeclarationName::CXXDestructorName) 479 OS << '~'; 480 else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) 481 OS << "operator "; 482 LangOptions LO; 483 Policy.adjustForCPlusPlus(); 484 Policy.SuppressScope = true; 485 OS << TInfo->getType().getAsString(Policy); 486 } else 487 Name.print(OS, Policy); 488 return; 489 } 490 llvm_unreachable("Unexpected declaration name kind"); 491 } 492 493 SourceLocation DeclarationNameInfo::getEndLocPrivate() const { 494 switch (Name.getNameKind()) { 495 case DeclarationName::Identifier: 496 case DeclarationName::CXXDeductionGuideName: 497 return NameLoc; 498 499 case DeclarationName::CXXOperatorName: { 500 unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc; 501 return SourceLocation::getFromRawEncoding(raw); 502 } 503 504 case DeclarationName::CXXLiteralOperatorName: { 505 unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc; 506 return SourceLocation::getFromRawEncoding(raw); 507 } 508 509 case DeclarationName::CXXConstructorName: 510 case DeclarationName::CXXDestructorName: 511 case DeclarationName::CXXConversionFunctionName: 512 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) 513 return TInfo->getTypeLoc().getEndLoc(); 514 else 515 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