clang 20.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
117 if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) {
118 ClassRec->getDecl()->printName(OS, Policy);
119 return;
120 }
122 if (auto *InjTy = ClassType->getAs<InjectedClassNameType>()) {
123 InjTy->getDecl()->printName(OS, Policy);
124 return;
125 }
126 }
127 ClassType.print(OS, Policy);
128}
129
130void DeclarationName::print(raw_ostream &OS,
131 const PrintingPolicy &Policy) const {
132 switch (getNameKind()) {
134 if (const IdentifierInfo *II = getAsIdentifierInfo()) {
135 StringRef Name = II->getName();
136 // If this is a mangled OpenMP variant name we strip off the mangling for
137 // printing. It should not be visible to the user at all.
138 if (II->isMangledOpenMPVariantName()) {
139 std::pair<StringRef, StringRef> NameContextPair =
141 OS << NameContextPair.first << "["
142 << OMPTraitInfo(NameContextPair.second) << "]";
143 } else {
144 OS << Name;
145 }
146 }
147 return;
148
153 return;
154
157
159 OS << '~';
161
163 OS << "<deduction guide for ";
165 OS << '>';
166 return;
167
169 const char *OpName = getOperatorSpelling(getCXXOverloadedOperator());
170 assert(OpName && "not an overloaded operator");
171
172 OS << "operator";
173 if (OpName[0] >= 'a' && OpName[0] <= 'z')
174 OS << ' ';
175 OS << OpName;
176 return;
177 }
178
180 OS << "operator\"\"" << getCXXLiteralIdentifier()->getName();
181 return;
182
184 OS << "operator ";
186 if (const RecordType *Rec = Type->getAs<RecordType>()) {
187 OS << *Rec->getDecl();
188 return;
189 }
190 // We know we're printing C++ here, ensure we print 'bool' properly.
191 PrintingPolicy CXXPolicy = Policy;
192 CXXPolicy.adjustForCPlusPlus();
193 Type.print(OS, CXXPolicy);
194 return;
195 }
197 OS << "<using-directive>";
198 return;
199 }
200
201 llvm_unreachable("Unexpected declaration name kind");
202}
203
204namespace clang {
205
206raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) {
207 LangOptions LO;
208 N.print(OS, PrintingPolicy(LO));
209 return OS;
210}
211
212} // namespace clang
213
216 if (!T.isNull() && T->isDependentType())
217 return true;
218
219 // A class-scope deduction guide in a dependent context has a dependent name.
220 auto *TD = getCXXDeductionGuideTemplate();
221 if (TD && TD->getDeclContext()->isDependentContext())
222 return true;
223
224 return false;
225}
226
227std::string DeclarationName::getAsString() const {
228 std::string Result;
229 llvm::raw_string_ostream OS(Result);
230 OS << *this;
231 return Result;
232}
233
234void *DeclarationName::getFETokenInfoSlow() const {
235 switch (getNameKind()) {
236 case Identifier:
237 llvm_unreachable("case Identifier already handled by getFETokenInfo!");
241 return castAsCXXSpecialNameExtra()->FETokenInfo;
242 case CXXOperatorName:
243 return castAsCXXOperatorIdName()->FETokenInfo;
245 return castAsCXXDeductionGuideNameExtra()->FETokenInfo;
247 return castAsCXXLiteralOperatorIdName()->FETokenInfo;
248 default:
249 llvm_unreachable("DeclarationName has no FETokenInfo!");
250 }
251}
252
253void DeclarationName::setFETokenInfoSlow(void *T) {
254 switch (getNameKind()) {
255 case Identifier:
256 llvm_unreachable("case Identifier already handled by setFETokenInfo!");
260 castAsCXXSpecialNameExtra()->FETokenInfo = T;
261 break;
262 case CXXOperatorName:
263 castAsCXXOperatorIdName()->FETokenInfo = T;
264 break;
266 castAsCXXDeductionGuideNameExtra()->FETokenInfo = T;
267 break;
269 castAsCXXLiteralOperatorIdName()->FETokenInfo = T;
270 break;
271 default:
272 llvm_unreachable("DeclarationName has no FETokenInfo!");
273 }
274}
275
276LLVM_DUMP_METHOD void DeclarationName::dump() const {
277 llvm::errs() << *this << '\n';
278}
279
281 // Initialize the overloaded operator names.
282 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op)
283 CXXOperatorNames[Op].Kind = static_cast<OverloadedOperatorKind>(Op);
284}
285
288 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
289
290 llvm::FoldingSetNodeID ID;
291 ID.AddPointer(Template);
292
293 void *InsertPos = nullptr;
294 if (auto *Name = CXXDeductionGuideNames.FindNodeOrInsertPos(ID, InsertPos))
295 return DeclarationName(Name);
296
297 auto *Name = new (Ctx) detail::CXXDeductionGuideNameExtra(Template);
298 CXXDeductionGuideNames.InsertNode(Name, InsertPos);
299 return DeclarationName(Name);
300}
301
303 // The type of constructors is unqualified.
304 Ty = Ty.getUnqualifiedType();
305 // Do we already have this C++ constructor name ?
306 llvm::FoldingSetNodeID ID;
307 ID.AddPointer(Ty.getAsOpaquePtr());
308 void *InsertPos = nullptr;
309 if (auto *Name = CXXConstructorNames.FindNodeOrInsertPos(ID, InsertPos))
310 return {Name, DeclarationName::StoredCXXConstructorName};
311
312 // We have to create it.
313 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
314 CXXConstructorNames.InsertNode(SpecialName, InsertPos);
315 return {SpecialName, DeclarationName::StoredCXXConstructorName};
316}
317
319 // The type of destructors is unqualified.
320 Ty = Ty.getUnqualifiedType();
321 // Do we already have this C++ destructor name ?
322 llvm::FoldingSetNodeID ID;
323 ID.AddPointer(Ty.getAsOpaquePtr());
324 void *InsertPos = nullptr;
325 if (auto *Name = CXXDestructorNames.FindNodeOrInsertPos(ID, InsertPos))
326 return {Name, DeclarationName::StoredCXXDestructorName};
327
328 // We have to create it.
329 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
330 CXXDestructorNames.InsertNode(SpecialName, InsertPos);
331 return {SpecialName, DeclarationName::StoredCXXDestructorName};
332}
333
336 // Do we already have this C++ conversion function name ?
337 llvm::FoldingSetNodeID ID;
338 ID.AddPointer(Ty.getAsOpaquePtr());
339 void *InsertPos = nullptr;
340 if (auto *Name =
341 CXXConversionFunctionNames.FindNodeOrInsertPos(ID, InsertPos))
342 return {Name, DeclarationName::StoredCXXConversionFunctionName};
343
344 // We have to create it.
345 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
346 CXXConversionFunctionNames.InsertNode(SpecialName, InsertPos);
347 return {SpecialName, DeclarationName::StoredCXXConversionFunctionName};
348}
349
352 CanQualType Ty) {
353 switch (Kind) {
355 return getCXXConstructorName(Ty);
357 return getCXXDestructorName(Ty);
360 default:
361 llvm_unreachable("Invalid kind in getCXXSpecialName!");
362 }
363}
364
367 llvm::FoldingSetNodeID ID;
368 ID.AddPointer(II);
369
370 void *InsertPos = nullptr;
371 if (auto *Name = CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos))
372 return DeclarationName(Name);
373
374 auto *LiteralName = new (Ctx) detail::CXXLiteralOperatorIdName(II);
375 CXXLiteralOperatorNames.InsertNode(LiteralName, InsertPos);
376 return DeclarationName(LiteralName);
377}
378
380 switch (Name.getNameKind()) {
383 break;
387 setNamedTypeLoc(nullptr);
388 break;
390 setCXXOperatorNameRange(SourceRange());
391 break;
393 setCXXLiteralOperatorNameLoc(SourceLocation());
394 break;
398 // FIXME: ?
399 break;
401 break;
402 }
403}
404
406 switch (Name.getNameKind()) {
415 return false;
416
420 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
421 return TInfo->getType()->containsUnexpandedParameterPack();
422
424 }
425 llvm_unreachable("All name kinds handled.");
426}
427
429 switch (Name.getNameKind()) {
438 return false;
439
443 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
444 return TInfo->getType()->isInstantiationDependentType();
445
447 }
448 llvm_unreachable("All name kinds handled.");
449}
450
452 std::string Result;
453 llvm::raw_string_ostream OS(Result);
454 OS << *this;
455 return Result;
456}
457
458raw_ostream &clang::operator<<(raw_ostream &OS, DeclarationNameInfo DNInfo) {
459 LangOptions LO;
460 DNInfo.printName(OS, PrintingPolicy(LangOptions()));
461 return OS;
462}
463
464void DeclarationNameInfo::printName(raw_ostream &OS, PrintingPolicy Policy) const {
465 switch (Name.getNameKind()) {
474 Name.print(OS, Policy);
475 return;
476
480 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo()) {
482 OS << '~';
484 OS << "operator ";
485 LangOptions LO;
486 Policy.adjustForCPlusPlus();
487 Policy.SuppressScope = true;
488 OS << TInfo->getType().getAsString(Policy);
489 } else
490 Name.print(OS, Policy);
491 return;
492 }
493 llvm_unreachable("Unexpected declaration name kind");
494}
495
496SourceLocation DeclarationNameInfo::getEndLocPrivate() const {
497 switch (Name.getNameKind()) {
500 return NameLoc;
501
503 return LocInfo.getCXXOperatorNameEndLoc();
504
506 return LocInfo.getCXXLiteralOperatorNameLoc();
507
511 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
512 return TInfo->getTypeLoc().getEndLoc();
513 else
514 return NameLoc;
515
516 // DNInfo work in progress: FIXME.
521 return NameLoc;
522 }
523 llvm_unreachable("Unexpected declaration name kind");
524}
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.
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:967
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: Type.h:6793
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:499
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:319
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
A (possibly-)qualified type.
Definition: Type.h:929
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: Type.h:6072
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:399
A container of type source information.
Definition: Type.h:7902
The base class of the type hierarchy.
Definition: Type.h:1828
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition: Type.h:2714
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2706
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition: Type.h:2361
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8731
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:5034
const StreamingDiagnostic & operator<<(const StreamingDiagnostic &DB, const ASTContext::SectionInfo &Section)
Insertion operator for diagnostics.
@ Result
The result type of a method or function.
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