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