1 //===-- DeclarationName.cpp - Declaration names implementation --*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the DeclarationName and DeclarationNameTable
13 //===----------------------------------------------------------------------===//
14 #include "clang/AST/DeclarationName.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/DeclCXX.h"
17 #include "clang/AST/DeclTemplate.h"
18 #include "clang/AST/Type.h"
19 #include "clang/AST/TypeLoc.h"
20 #include "clang/AST/TypeOrdering.h"
21 #include "clang/Basic/IdentifierTable.h"
22 #include "llvm/ADT/FoldingSet.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/raw_ostream.h"
25 using namespace clang;
28 /// CXXSpecialName - Records the type associated with one of the
29 /// "special" kinds of declaration names in C++, e.g., constructors,
30 /// destructors, and conversion functions.
32 : public DeclarationNameExtra, public llvm::FoldingSetNode {
34 /// Type - The type associated with this declaration name.
37 /// FETokenInfo - Extra information associated with this declaration
38 /// name that can be used by the front end.
41 void Profile(llvm::FoldingSetNodeID &ID) {
42 ID.AddInteger(ExtraKindOrNumArgs);
43 ID.AddPointer(Type.getAsOpaquePtr());
47 /// Contains extra information for the name of a C++ deduction guide.
48 class CXXDeductionGuideNameExtra : public DeclarationNameExtra,
49 public llvm::FoldingSetNode {
51 /// The template named by the deduction guide.
52 TemplateDecl *Template;
54 /// FETokenInfo - Extra information associated with this operator
55 /// name that can be used by the front end.
58 void Profile(llvm::FoldingSetNodeID &ID) {
59 ID.AddPointer(Template);
63 /// CXXOperatorIdName - Contains extra information for the name of an
64 /// overloaded operator in C++, such as "operator+.
65 class CXXOperatorIdName : public DeclarationNameExtra {
67 /// FETokenInfo - Extra information associated with this operator
68 /// name that can be used by the front end.
72 /// CXXLiteralOperatorName - Contains the actual identifier that makes up the
75 /// This identifier is stored here rather than directly in DeclarationName so as
76 /// to allow Objective-C selectors, which are about a million times more common,
77 /// to consume minimal memory.
78 class CXXLiteralOperatorIdName
79 : public DeclarationNameExtra, public llvm::FoldingSetNode {
83 /// FETokenInfo - Extra information associated with this operator
84 /// name that can be used by the front end.
87 void Profile(llvm::FoldingSetNodeID &FSID) {
92 static int compareInt(unsigned A, unsigned B) {
93 return (A < B ? -1 : (A > B ? 1 : 0));
96 int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
97 if (LHS.getNameKind() != RHS.getNameKind())
98 return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);
100 switch (LHS.getNameKind()) {
101 case DeclarationName::Identifier: {
102 IdentifierInfo *LII = LHS.getAsIdentifierInfo();
103 IdentifierInfo *RII = RHS.getAsIdentifierInfo();
104 if (!LII) return RII ? -1 : 0;
107 return LII->getName().compare(RII->getName());
110 case DeclarationName::ObjCZeroArgSelector:
111 case DeclarationName::ObjCOneArgSelector:
112 case DeclarationName::ObjCMultiArgSelector: {
113 Selector LHSSelector = LHS.getObjCSelector();
114 Selector RHSSelector = RHS.getObjCSelector();
115 // getNumArgs for ZeroArgSelector returns 0, but we still need to compare.
116 if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector &&
117 RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) {
118 return LHSSelector.getAsIdentifierInfo()->getName().compare(
119 RHSSelector.getAsIdentifierInfo()->getName());
121 unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
122 for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
123 switch (LHSSelector.getNameForSlot(I).compare(
124 RHSSelector.getNameForSlot(I))) {
131 return compareInt(LN, RN);
134 case DeclarationName::CXXConstructorName:
135 case DeclarationName::CXXDestructorName:
136 case DeclarationName::CXXConversionFunctionName:
137 if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))
139 if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))
143 case DeclarationName::CXXDeductionGuideName:
144 // We never want to compare deduction guide names for templates from
145 // different scopes, so just compare the template-name.
146 return compare(LHS.getCXXDeductionGuideTemplate()->getDeclName(),
147 RHS.getCXXDeductionGuideTemplate()->getDeclName());
149 case DeclarationName::CXXOperatorName:
150 return compareInt(LHS.getCXXOverloadedOperator(),
151 RHS.getCXXOverloadedOperator());
153 case DeclarationName::CXXLiteralOperatorName:
154 return LHS.getCXXLiteralIdentifier()->getName().compare(
155 RHS.getCXXLiteralIdentifier()->getName());
157 case DeclarationName::CXXUsingDirective:
161 llvm_unreachable("Invalid DeclarationName Kind!");
164 static void printCXXConstructorDestructorName(QualType ClassType,
166 PrintingPolicy Policy) {
167 // We know we're printing C++ here. Ensure we print types properly.
168 Policy.adjustForCPlusPlus();
170 if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) {
171 OS << *ClassRec->getDecl();
174 if (Policy.SuppressTemplateArgsInCXXConstructors) {
175 if (auto *InjTy = ClassType->getAs<InjectedClassNameType>()) {
176 OS << *InjTy->getDecl();
180 ClassType.print(OS, Policy);
183 void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) {
184 DeclarationName &N = *this;
185 switch (N.getNameKind()) {
186 case DeclarationName::Identifier:
187 if (const IdentifierInfo *II = N.getAsIdentifierInfo())
191 case DeclarationName::ObjCZeroArgSelector:
192 case DeclarationName::ObjCOneArgSelector:
193 case DeclarationName::ObjCMultiArgSelector:
194 N.getObjCSelector().print(OS);
197 case DeclarationName::CXXConstructorName:
198 return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy);
200 case DeclarationName::CXXDestructorName: {
202 return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy);
205 case DeclarationName::CXXDeductionGuideName:
206 OS << "<deduction guide for ";
207 getCXXDeductionGuideTemplate()->getDeclName().print(OS, Policy);
211 case DeclarationName::CXXOperatorName: {
212 static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
214 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
216 #include "clang/Basic/OperatorKinds.def"
218 const char *OpName = OperatorNames[N.getCXXOverloadedOperator()];
219 assert(OpName && "not an overloaded operator");
222 if (OpName[0] >= 'a' && OpName[0] <= 'z')
228 case DeclarationName::CXXLiteralOperatorName:
229 OS << "operator\"\"" << N.getCXXLiteralIdentifier()->getName();
232 case DeclarationName::CXXConversionFunctionName: {
234 QualType Type = N.getCXXNameType();
235 if (const RecordType *Rec = Type->getAs<RecordType>()) {
236 OS << *Rec->getDecl();
239 // We know we're printing C++ here, ensure we print 'bool' properly.
240 PrintingPolicy CXXPolicy = Policy;
241 CXXPolicy.adjustForCPlusPlus();
242 Type.print(OS, CXXPolicy);
245 case DeclarationName::CXXUsingDirective:
246 OS << "<using-directive>";
250 llvm_unreachable("Unexpected declaration name kind");
253 raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) {
255 N.print(OS, PrintingPolicy(LO));
259 } // end namespace clang
261 DeclarationName::NameKind DeclarationName::getNameKind() const {
262 switch (getStoredNameKind()) {
263 case StoredIdentifier: return Identifier;
264 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
265 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
267 case StoredDeclarationNameExtra:
268 switch (getExtra()->ExtraKindOrNumArgs) {
269 case DeclarationNameExtra::CXXConstructor:
270 return CXXConstructorName;
272 case DeclarationNameExtra::CXXDestructor:
273 return CXXDestructorName;
275 case DeclarationNameExtra::CXXDeductionGuide:
276 return CXXDeductionGuideName;
278 case DeclarationNameExtra::CXXConversionFunction:
279 return CXXConversionFunctionName;
281 case DeclarationNameExtra::CXXLiteralOperator:
282 return CXXLiteralOperatorName;
284 case DeclarationNameExtra::CXXUsingDirective:
285 return CXXUsingDirective;
288 // Check if we have one of the CXXOperator* enumeration values.
289 if (getExtra()->ExtraKindOrNumArgs <
290 DeclarationNameExtra::CXXUsingDirective)
291 return CXXOperatorName;
293 return ObjCMultiArgSelector;
297 // Can't actually get here.
298 llvm_unreachable("This should be unreachable!");
301 bool DeclarationName::isDependentName() const {
302 QualType T = getCXXNameType();
303 if (!T.isNull() && T->isDependentType())
306 // A class-scope deduction guide in a dependent context has a dependent name.
307 auto *TD = getCXXDeductionGuideTemplate();
308 if (TD && TD->getDeclContext()->isDependentContext())
314 std::string DeclarationName::getAsString() const {
316 llvm::raw_string_ostream OS(Result);
321 QualType DeclarationName::getCXXNameType() const {
322 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
323 return CXXName->Type;
328 TemplateDecl *DeclarationName::getCXXDeductionGuideTemplate() const {
329 if (auto *Guide = getAsCXXDeductionGuideNameExtra())
330 return Guide->Template;
334 OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
335 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
337 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
338 return static_cast<OverloadedOperatorKind>(value);
344 IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
345 if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
351 void *DeclarationName::getFETokenInfoAsVoidSlow() const {
352 switch (getNameKind()) {
354 llvm_unreachable("Handled by getFETokenInfo()");
356 case CXXConstructorName:
357 case CXXDestructorName:
358 case CXXConversionFunctionName:
359 return getAsCXXSpecialName()->FETokenInfo;
361 case CXXDeductionGuideName:
362 return getAsCXXDeductionGuideNameExtra()->FETokenInfo;
364 case CXXOperatorName:
365 return getAsCXXOperatorIdName()->FETokenInfo;
367 case CXXLiteralOperatorName:
368 return getAsCXXLiteralOperatorIdName()->FETokenInfo;
371 llvm_unreachable("Declaration name has no FETokenInfo");
375 void DeclarationName::setFETokenInfo(void *T) {
376 switch (getNameKind()) {
378 getAsIdentifierInfo()->setFETokenInfo(T);
381 case CXXConstructorName:
382 case CXXDestructorName:
383 case CXXConversionFunctionName:
384 getAsCXXSpecialName()->FETokenInfo = T;
387 case CXXDeductionGuideName:
388 getAsCXXDeductionGuideNameExtra()->FETokenInfo = T;
391 case CXXOperatorName:
392 getAsCXXOperatorIdName()->FETokenInfo = T;
395 case CXXLiteralOperatorName:
396 getAsCXXLiteralOperatorIdName()->FETokenInfo = T;
400 llvm_unreachable("Declaration name has no FETokenInfo");
404 DeclarationName DeclarationName::getUsingDirectiveName() {
405 // Single instance of DeclarationNameExtra for using-directive
406 static const DeclarationNameExtra UDirExtra =
407 { DeclarationNameExtra::CXXUsingDirective };
409 uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
410 Ptr |= StoredDeclarationNameExtra;
412 return DeclarationName(Ptr);
415 LLVM_DUMP_METHOD void DeclarationName::dump() const {
416 llvm::errs() << *this << '\n';
419 DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
420 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
421 CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>;
422 CXXDeductionGuideNames = new llvm::FoldingSet<CXXDeductionGuideNameExtra>;
424 // Initialize the overloaded operator names.
425 CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
426 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
427 CXXOperatorNames[Op].ExtraKindOrNumArgs
428 = Op + DeclarationNameExtra::CXXConversionFunction;
429 CXXOperatorNames[Op].FETokenInfo = nullptr;
433 DeclarationNameTable::~DeclarationNameTable() {
435 static_cast<llvm::FoldingSet<CXXSpecialName> *>(CXXSpecialNamesImpl);
437 static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName> *>(
438 CXXLiteralOperatorNames);
439 auto *DeductionGuideNames =
440 static_cast<llvm::FoldingSet<CXXDeductionGuideNameExtra> *>(
441 CXXDeductionGuideNames);
445 delete DeductionGuideNames;
448 DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) {
449 return getCXXSpecialName(DeclarationName::CXXConstructorName,
450 Ty.getUnqualifiedType());
453 DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) {
454 return getCXXSpecialName(DeclarationName::CXXDestructorName,
455 Ty.getUnqualifiedType());
459 DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl *Template) {
460 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
462 auto *DeductionGuideNames =
463 static_cast<llvm::FoldingSet<CXXDeductionGuideNameExtra> *>(
464 CXXDeductionGuideNames);
466 llvm::FoldingSetNodeID ID;
467 ID.AddPointer(Template);
469 void *InsertPos = nullptr;
470 if (auto *Name = DeductionGuideNames->FindNodeOrInsertPos(ID, InsertPos))
471 return DeclarationName(Name);
473 auto *Name = new (Ctx) CXXDeductionGuideNameExtra;
474 Name->ExtraKindOrNumArgs = DeclarationNameExtra::CXXDeductionGuide;
475 Name->Template = Template;
476 Name->FETokenInfo = nullptr;
478 DeductionGuideNames->InsertNode(Name, InsertPos);
479 return DeclarationName(Name);
483 DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) {
484 return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty);
488 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
490 assert(Kind >= DeclarationName::CXXConstructorName &&
491 Kind <= DeclarationName::CXXConversionFunctionName &&
492 "Kind must be a C++ special name kind");
493 llvm::FoldingSet<CXXSpecialName> *SpecialNames
494 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
496 DeclarationNameExtra::ExtraKind EKind;
498 case DeclarationName::CXXConstructorName:
499 EKind = DeclarationNameExtra::CXXConstructor;
500 assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
502 case DeclarationName::CXXDestructorName:
503 EKind = DeclarationNameExtra::CXXDestructor;
504 assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
506 case DeclarationName::CXXConversionFunctionName:
507 EKind = DeclarationNameExtra::CXXConversionFunction;
510 return DeclarationName();
513 // Unique selector, to guarantee there is one per name.
514 llvm::FoldingSetNodeID ID;
515 ID.AddInteger(EKind);
516 ID.AddPointer(Ty.getAsOpaquePtr());
518 void *InsertPos = nullptr;
519 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
520 return DeclarationName(Name);
522 CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName;
523 SpecialName->ExtraKindOrNumArgs = EKind;
524 SpecialName->Type = Ty;
525 SpecialName->FETokenInfo = nullptr;
527 SpecialNames->InsertNode(SpecialName, InsertPos);
528 return DeclarationName(SpecialName);
532 DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
533 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
537 DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
538 llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
539 = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
540 (CXXLiteralOperatorNames);
542 llvm::FoldingSetNodeID ID;
545 void *InsertPos = nullptr;
546 if (CXXLiteralOperatorIdName *Name =
547 LiteralNames->FindNodeOrInsertPos(ID, InsertPos))
548 return DeclarationName (Name);
550 CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName;
551 LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
552 LiteralName->ID = II;
553 LiteralName->FETokenInfo = nullptr;
555 LiteralNames->InsertNode(LiteralName, InsertPos);
556 return DeclarationName(LiteralName);
559 DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
560 switch (Name.getNameKind()) {
561 case DeclarationName::Identifier:
562 case DeclarationName::CXXDeductionGuideName:
564 case DeclarationName::CXXConstructorName:
565 case DeclarationName::CXXDestructorName:
566 case DeclarationName::CXXConversionFunctionName:
567 NamedType.TInfo = nullptr;
569 case DeclarationName::CXXOperatorName:
570 CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
571 CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
573 case DeclarationName::CXXLiteralOperatorName:
574 CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
576 case DeclarationName::ObjCZeroArgSelector:
577 case DeclarationName::ObjCOneArgSelector:
578 case DeclarationName::ObjCMultiArgSelector:
581 case DeclarationName::CXXUsingDirective:
586 bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
587 switch (Name.getNameKind()) {
588 case DeclarationName::Identifier:
589 case DeclarationName::ObjCZeroArgSelector:
590 case DeclarationName::ObjCOneArgSelector:
591 case DeclarationName::ObjCMultiArgSelector:
592 case DeclarationName::CXXOperatorName:
593 case DeclarationName::CXXLiteralOperatorName:
594 case DeclarationName::CXXUsingDirective:
595 case DeclarationName::CXXDeductionGuideName:
598 case DeclarationName::CXXConstructorName:
599 case DeclarationName::CXXDestructorName:
600 case DeclarationName::CXXConversionFunctionName:
601 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
602 return TInfo->getType()->containsUnexpandedParameterPack();
604 return Name.getCXXNameType()->containsUnexpandedParameterPack();
606 llvm_unreachable("All name kinds handled.");
609 bool DeclarationNameInfo::isInstantiationDependent() const {
610 switch (Name.getNameKind()) {
611 case DeclarationName::Identifier:
612 case DeclarationName::ObjCZeroArgSelector:
613 case DeclarationName::ObjCOneArgSelector:
614 case DeclarationName::ObjCMultiArgSelector:
615 case DeclarationName::CXXOperatorName:
616 case DeclarationName::CXXLiteralOperatorName:
617 case DeclarationName::CXXUsingDirective:
618 case DeclarationName::CXXDeductionGuideName:
621 case DeclarationName::CXXConstructorName:
622 case DeclarationName::CXXDestructorName:
623 case DeclarationName::CXXConversionFunctionName:
624 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
625 return TInfo->getType()->isInstantiationDependentType();
627 return Name.getCXXNameType()->isInstantiationDependentType();
629 llvm_unreachable("All name kinds handled.");
632 std::string DeclarationNameInfo::getAsString() const {
634 llvm::raw_string_ostream OS(Result);
639 void DeclarationNameInfo::printName(raw_ostream &OS) const {
640 switch (Name.getNameKind()) {
641 case DeclarationName::Identifier:
642 case DeclarationName::ObjCZeroArgSelector:
643 case DeclarationName::ObjCOneArgSelector:
644 case DeclarationName::ObjCMultiArgSelector:
645 case DeclarationName::CXXOperatorName:
646 case DeclarationName::CXXLiteralOperatorName:
647 case DeclarationName::CXXUsingDirective:
648 case DeclarationName::CXXDeductionGuideName:
652 case DeclarationName::CXXConstructorName:
653 case DeclarationName::CXXDestructorName:
654 case DeclarationName::CXXConversionFunctionName:
655 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) {
656 if (Name.getNameKind() == DeclarationName::CXXDestructorName)
658 else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
663 PrintingPolicy PP(LO);
664 PP.SuppressScope = true;
665 OS << TInfo->getType().getAsString(PP);
670 llvm_unreachable("Unexpected declaration name kind");
673 SourceLocation DeclarationNameInfo::getEndLoc() const {
674 switch (Name.getNameKind()) {
675 case DeclarationName::Identifier:
676 case DeclarationName::CXXDeductionGuideName:
679 case DeclarationName::CXXOperatorName: {
680 unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
681 return SourceLocation::getFromRawEncoding(raw);
684 case DeclarationName::CXXLiteralOperatorName: {
685 unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
686 return SourceLocation::getFromRawEncoding(raw);
689 case DeclarationName::CXXConstructorName:
690 case DeclarationName::CXXDestructorName:
691 case DeclarationName::CXXConversionFunctionName:
692 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
693 return TInfo->getTypeLoc().getEndLoc();
697 // DNInfo work in progress: FIXME.
698 case DeclarationName::ObjCZeroArgSelector:
699 case DeclarationName::ObjCOneArgSelector:
700 case DeclarationName::ObjCMultiArgSelector:
701 case DeclarationName::CXXUsingDirective:
704 llvm_unreachable("Unexpected declaration name kind");