clang 22.0.0git
DeclarationName.cpp
Go to the documentation of this file.
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
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclBase.h"
18#include "clang/AST/DeclCXX.h"
22#include "clang/AST/Type.h"
23#include "clang/AST/TypeLoc.h"
26#include "clang/Basic/LLVM.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
45 if (LHS.getNameKind() != RHS.getNameKind())
46 return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);
47
48 switch (LHS.getNameKind()) {
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
63 Selector LHSSelector = LHS.getObjCSelector();
64 Selector RHSSelector = RHS.getObjCSelector();
65 // getNumArgs for ZeroArgSelector returns 0, but we still need to compare.
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
85 return -1;
87 return 1;
88 return 0;
89
91 // We never want to compare deduction guide names for templates from
92 // different scopes, so just compare the template-name.
95
99
101 return LHS.getCXXLiteralIdentifier()->getName().compare(
103
105 return 0;
106 }
107
108 llvm_unreachable("Invalid DeclarationName Kind!");
109}
110
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->getOriginalDecl()->printName(OS, Policy);
120 return;
121 }
123 if (auto *InjTy = ClassType->getAsCanonical<InjectedClassNameType>()) {
124 InjTy->getOriginalDecl()->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()) {
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 for
138 // printing. It should not be visible to the user at all.
139 if (II->isMangledOpenMPVariantName()) {
140 std::pair<StringRef, StringRef> NameContextPair =
142 OS << NameContextPair.first << "["
143 << OMPTraitInfo(NameContextPair.second) << "]";
144 } else {
145 OS << Name;
146 }
147 }
148 return;
149
154 return;
155
158
160 OS << '~';
162
164 OS << "<deduction guide for ";
166 OS << '>';
167 return;
168
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
181 OS << "operator\"\"" << getCXXLiteralIdentifier()->getName();
182 return;
183
185 OS << "operator ";
187 if (const RecordType *Rec = Type->getAs<RecordType>()) {
188 OS << *Rec->getOriginalDecl();
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 }
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 clang
214
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!");
242 return castAsCXXSpecialNameExtra()->FETokenInfo;
243 case CXXOperatorName:
244 return castAsCXXOperatorIdName()->FETokenInfo;
246 return castAsCXXDeductionGuideNameExtra()->FETokenInfo;
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!");
261 castAsCXXSpecialNameExtra()->FETokenInfo = T;
262 break;
263 case CXXOperatorName:
264 castAsCXXOperatorIdName()->FETokenInfo = T;
265 break;
267 castAsCXXDeductionGuideNameExtra()->FETokenInfo = T;
268 break;
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
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
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
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
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
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
353 CanQualType Ty) {
354 switch (Kind) {
356 return getCXXConstructorName(Ty);
358 return getCXXDestructorName(Ty);
361 default:
362 llvm_unreachable("Invalid kind in getCXXSpecialName!");
363 }
364}
365
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
381 switch (Name.getNameKind()) {
384 break;
388 setNamedTypeLoc(nullptr);
389 break;
391 setCXXOperatorNameRange(SourceRange());
392 break;
394 setCXXLiteralOperatorNameLoc(SourceLocation());
395 break;
399 // FIXME: ?
400 break;
402 break;
403 }
404}
405
407 switch (Name.getNameKind()) {
416 return false;
417
421 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
422 return TInfo->getType()->containsUnexpandedParameterPack();
423
425 }
426 llvm_unreachable("All name kinds handled.");
427}
428
430 switch (Name.getNameKind()) {
439 return false;
440
444 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
445 return TInfo->getType()->isInstantiationDependentType();
446
448 }
449 llvm_unreachable("All name kinds handled.");
450}
451
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()) {
475 Name.print(OS, Policy);
476 return;
477
481 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo()) {
483 OS << '~';
485 OS << "operator ";
486 LangOptions LO;
487 Policy.adjustForCPlusPlus();
488 Policy.SuppressScope = true;
489 OS << TInfo->getType().getAsString(Policy);
490 } else
491 Name.print(OS, Policy);
492 return;
493 }
494 llvm_unreachable("Unexpected declaration name kind");
495}
496
497SourceLocation DeclarationNameInfo::getEndLocPrivate() const {
498 switch (Name.getNameKind()) {
501 return NameLoc;
502
504 return LocInfo.getCXXOperatorNameEndLoc();
505
507 return LocInfo.getCXXLiteralOperatorNameLoc();
508
512 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
513 return TInfo->getTypeLoc().getEndLoc();
514 else
515 return NameLoc;
516
517 // DNInfo work in progress: FIXME.
522 return NameLoc;
523 }
524 llvm_unreachable("Unexpected declaration name kind");
525}
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
static void printCXXConstructorDestructorName(QualType ClassType, raw_ostream &OS, PrintingPolicy Policy)
static int compareInt(unsigned A, unsigned B)
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::LangOptions interface.
This file defines OpenMP AST classes for clauses.
Defines an enumeration for C++ overloaded operators.
Defines the clang::SourceLocation class and associated facilities.
Defines the clang::TypeLoc interface and its subclasses.
Allows QualTypes to be sorted and hence used in maps and sets.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
void * getAsOpaquePtr() const
Retrieve the internal representation of this canonical type.
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
SourceLocation getCXXLiteralOperatorNameLoc() const
Return the location of the literal operator name (without the operator keyword).
TypeSourceInfo * getNamedTypeInfo() const
Returns the source type info.
SourceLocation getCXXOperatorNameEndLoc() const
Return the end location of the getCXXOperatorNameRange() range.
DeclarationNameTable(const ASTContext &C)
DeclarationName getCXXConversionFunctionName(CanQualType Ty)
Returns the name of a C++ conversion function for the given Type.
DeclarationName getCXXDestructorName(CanQualType Ty)
Returns the name of a C++ destructor for the given Type.
DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind, CanQualType Ty)
Returns a declaration name for special kind of C++ name, e.g., for a constructor, destructor,...
DeclarationName getCXXDeductionGuideName(TemplateDecl *TD)
Returns the name of a C++ deduction guide for the given template.
DeclarationName getCXXConstructorName(CanQualType Ty)
Returns the name of a C++ constructor for the given Type.
DeclarationName getCXXLiteralOperatorName(const IdentifierInfo *II)
Get the name of the literal operator function with II as the identifier.
The name of a declaration.
static int compare(DeclarationName LHS, DeclarationName RHS)
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
bool isDependentName() const
Determines whether the name itself is dependent, e.g., because it involves a C++ type that is itself ...
TemplateDecl * getCXXDeductionGuideTemplate() const
If this name is the name of a C++ deduction guide, return the template associated with that name.
void print(raw_ostream &OS, const PrintingPolicy &Policy) const
std::string getAsString() const
Retrieve the human-readable string for this name.
const IdentifierInfo * getCXXLiteralIdentifier() const
If this name is the name of a literal operator, retrieve the identifier associated with it.
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
NameKind
The kind of the name stored in this DeclarationName.
QualType getCXXNameType() const
If this name is one of the C++ names (of a constructor, destructor, or conversion function),...
Selector getObjCSelector() const
Get the Objective-C selector stored in this declaration name.
NameKind getNameKind() const
Determine what kind of name this is.
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
The injected class name of a C++ class template or class template partial specialization.
Definition: TypeBase.h:6553
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:434
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:339
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
A (possibly-)qualified type.
Definition: TypeBase.h:937
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: TypeBase.h:6502
Smart pointer class that efficiently represents Objective-C method names.
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
void print(llvm::raw_ostream &OS) const
Prints the full selector name (e.g. "foo:bar:").
unsigned getNumArgs() const
Encodes a location in the source.
A trivial tuple used to represent a source range.
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:396
A container of type source information.
Definition: TypeBase.h:8314
The base class of the type hierarchy.
Definition: TypeBase.h:1833
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition: TypeBase.h:2808
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: TypeBase.h:2800
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition: TypeBase.h:2423
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition: TypeBase.h:2939
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
Contains extra information for the name of a C++ deduction guide.
Contains the actual identifier that makes up the name of a C++ literal operator.
CXXSpecialNameExtra records the type associated with one of the "special" kinds of declaration names ...
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
Definition: OperatorKinds.h:21
@ NUM_OVERLOADED_OPERATORS
Definition: OperatorKinds.h:26
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
Definition: Decl.h:5343
const StreamingDiagnostic & operator<<(const StreamingDiagnostic &DB, const ASTContext::SectionInfo &Section)
Insertion operator for diagnostics.
@ Result
The result type of a method or function.
@ Template
We are parsing a template declaration.
const FunctionProtoType * T
const char * getOperatorSpelling(OverloadedOperatorKind Operator)
Retrieve the spelling of the given overloaded operator, without the preceding "operator" keyword.
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
bool isInstantiationDependent() const
Determine whether this name involves a template parameter.
void printName(raw_ostream &OS, PrintingPolicy Policy) const
printName - Print the human-readable name to a stream.
std::string getAsString() const
getAsString - Retrieve the human-readable string for this name.
bool containsUnexpandedParameterPack() const
Determine whether this name contains an unexpanded parameter pack.
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:57
void adjustForCPlusPlus()
Adjust this printing policy for cases where it's known that we're printing C++ code (for instance,...
Definition: PrettyPrinter.h:88
unsigned SuppressScope
Suppresses printing of scope specifiers.
unsigned SuppressTemplateArgsInCXXConstructors
When true, suppresses printing template arguments in names of C++ constructors.
Function object that provides a total ordering on QualType values.
Definition: TypeOrdering.h:28