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/Casting.h"
32#include "llvm/Support/Compiler.h"
33#include "llvm/Support/ErrorHandling.h"
34#include "llvm/Support/raw_ostream.h"
35#include <algorithm>
36#include <cassert>
37#include <cstdint>
38#include <string>
39
40using namespace clang;
41
42static int compareInt(unsigned A, unsigned B) {
43 return (A < B ? -1 : (A > B ? 1 : 0));
44}
45
47 if (LHS.getNameKind() != RHS.getNameKind())
48 return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);
49
50 switch (LHS.getNameKind()) {
52 IdentifierInfo *LII = LHS.castAsIdentifierInfo();
53 IdentifierInfo *RII = RHS.castAsIdentifierInfo();
54 if (!LII)
55 return RII ? -1 : 0;
56 if (!RII)
57 return 1;
58
59 return LII->getName().compare(RII->getName());
60 }
61
65 Selector LHSSelector = LHS.getObjCSelector();
66 Selector RHSSelector = RHS.getObjCSelector();
67 // getNumArgs for ZeroArgSelector returns 0, but we still need to compare.
70 return LHSSelector.getAsIdentifierInfo()->getName().compare(
71 RHSSelector.getAsIdentifierInfo()->getName());
72 }
73 unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
74 for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
75 if (int Compare = LHSSelector.getNameForSlot(I).compare(
76 RHSSelector.getNameForSlot(I)))
77 return Compare;
78 }
79
80 return compareInt(LN, RN);
81 }
82
87 return -1;
89 return 1;
90 return 0;
91
93 // We never want to compare deduction guide names for templates from
94 // different scopes, so just compare the template-name.
97
101
103 return LHS.getCXXLiteralIdentifier()->getName().compare(
105
107 return 0;
108 }
109
110 llvm_unreachable("Invalid DeclarationName Kind!");
111}
112
114 raw_ostream &OS,
115 PrintingPolicy Policy) {
116 // We know we're printing C++ here. Ensure we print types properly.
117 Policy.adjustForCPlusPlus();
118
119 if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) {
120 ClassRec->getDecl()->printName(OS, Policy);
121 return;
122 }
124 if (auto *InjTy = ClassType->getAs<InjectedClassNameType>()) {
125 InjTy->getDecl()->printName(OS, Policy);
126 return;
127 }
128 }
129 ClassType.print(OS, Policy);
130}
131
132void DeclarationName::print(raw_ostream &OS,
133 const PrintingPolicy &Policy) const {
134 switch (getNameKind()) {
136 if (const IdentifierInfo *II = getAsIdentifierInfo()) {
137 StringRef Name = II->getName();
138 // If this is a mangled OpenMP variant name we strip off the mangling for
139 // printing. It should not be visible to the user at all.
140 if (II->isMangledOpenMPVariantName()) {
141 std::pair<StringRef, StringRef> NameContextPair =
143 OS << NameContextPair.first << "["
144 << OMPTraitInfo(NameContextPair.second) << "]";
145 } else {
146 OS << Name;
147 }
148 }
149 return;
150
155 return;
156
159
161 OS << '~';
163
165 OS << "<deduction guide for ";
167 OS << '>';
168 return;
169
171 const char *OpName = getOperatorSpelling(getCXXOverloadedOperator());
172 assert(OpName && "not an overloaded operator");
173
174 OS << "operator";
175 if (OpName[0] >= 'a' && OpName[0] <= 'z')
176 OS << ' ';
177 OS << OpName;
178 return;
179 }
180
182 OS << "operator\"\"" << getCXXLiteralIdentifier()->getName();
183 return;
184
186 OS << "operator ";
188 if (const RecordType *Rec = Type->getAs<RecordType>()) {
189 OS << *Rec->getDecl();
190 return;
191 }
192 // We know we're printing C++ here, ensure we print 'bool' properly.
193 PrintingPolicy CXXPolicy = Policy;
194 CXXPolicy.adjustForCPlusPlus();
195 Type.print(OS, CXXPolicy);
196 return;
197 }
199 OS << "<using-directive>";
200 return;
201 }
202
203 llvm_unreachable("Unexpected declaration name kind");
204}
205
206namespace clang {
207
208raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) {
209 LangOptions LO;
210 N.print(OS, PrintingPolicy(LO));
211 return OS;
212}
213
214} // namespace clang
215
218 if (!T.isNull() && T->isDependentType())
219 return true;
220
221 // A class-scope deduction guide in a dependent context has a dependent name.
222 auto *TD = getCXXDeductionGuideTemplate();
223 if (TD && TD->getDeclContext()->isDependentContext())
224 return true;
225
226 return false;
227}
228
229std::string DeclarationName::getAsString() const {
230 std::string Result;
231 llvm::raw_string_ostream OS(Result);
232 OS << *this;
233 return Result;
234}
235
236void *DeclarationName::getFETokenInfoSlow() const {
237 switch (getNameKind()) {
238 case Identifier:
239 llvm_unreachable("case Identifier already handled by getFETokenInfo!");
243 return castAsCXXSpecialNameExtra()->FETokenInfo;
244 case CXXOperatorName:
245 return castAsCXXOperatorIdName()->FETokenInfo;
247 return castAsCXXDeductionGuideNameExtra()->FETokenInfo;
249 return castAsCXXLiteralOperatorIdName()->FETokenInfo;
250 default:
251 llvm_unreachable("DeclarationName has no FETokenInfo!");
252 }
253}
254
255void DeclarationName::setFETokenInfoSlow(void *T) {
256 switch (getNameKind()) {
257 case Identifier:
258 llvm_unreachable("case Identifier already handled by setFETokenInfo!");
262 castAsCXXSpecialNameExtra()->FETokenInfo = T;
263 break;
264 case CXXOperatorName:
265 castAsCXXOperatorIdName()->FETokenInfo = T;
266 break;
268 castAsCXXDeductionGuideNameExtra()->FETokenInfo = T;
269 break;
271 castAsCXXLiteralOperatorIdName()->FETokenInfo = T;
272 break;
273 default:
274 llvm_unreachable("DeclarationName has no FETokenInfo!");
275 }
276}
277
278LLVM_DUMP_METHOD void DeclarationName::dump() const {
279 llvm::errs() << *this << '\n';
280}
281
283 // Initialize the overloaded operator names.
284 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op)
285 CXXOperatorNames[Op].Kind = static_cast<OverloadedOperatorKind>(Op);
286}
287
290 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
291
292 llvm::FoldingSetNodeID ID;
293 ID.AddPointer(Template);
294
295 void *InsertPos = nullptr;
296 if (auto *Name = CXXDeductionGuideNames.FindNodeOrInsertPos(ID, InsertPos))
297 return DeclarationName(Name);
298
299 auto *Name = new (Ctx) detail::CXXDeductionGuideNameExtra(Template);
300 CXXDeductionGuideNames.InsertNode(Name, InsertPos);
301 return DeclarationName(Name);
302}
303
305 // The type of constructors is unqualified.
306 Ty = Ty.getUnqualifiedType();
307 // Do we already have this C++ constructor name ?
308 llvm::FoldingSetNodeID ID;
309 ID.AddPointer(Ty.getAsOpaquePtr());
310 void *InsertPos = nullptr;
311 if (auto *Name = CXXConstructorNames.FindNodeOrInsertPos(ID, InsertPos))
312 return {Name, DeclarationName::StoredCXXConstructorName};
313
314 // We have to create it.
315 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
316 CXXConstructorNames.InsertNode(SpecialName, InsertPos);
317 return {SpecialName, DeclarationName::StoredCXXConstructorName};
318}
319
321 // The type of destructors is unqualified.
322 Ty = Ty.getUnqualifiedType();
323 // Do we already have this C++ destructor name ?
324 llvm::FoldingSetNodeID ID;
325 ID.AddPointer(Ty.getAsOpaquePtr());
326 void *InsertPos = nullptr;
327 if (auto *Name = CXXDestructorNames.FindNodeOrInsertPos(ID, InsertPos))
328 return {Name, DeclarationName::StoredCXXDestructorName};
329
330 // We have to create it.
331 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
332 CXXDestructorNames.InsertNode(SpecialName, InsertPos);
333 return {SpecialName, DeclarationName::StoredCXXDestructorName};
334}
335
338 // Do we already have this C++ conversion function name ?
339 llvm::FoldingSetNodeID ID;
340 ID.AddPointer(Ty.getAsOpaquePtr());
341 void *InsertPos = nullptr;
342 if (auto *Name =
343 CXXConversionFunctionNames.FindNodeOrInsertPos(ID, InsertPos))
344 return {Name, DeclarationName::StoredCXXConversionFunctionName};
345
346 // We have to create it.
347 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
348 CXXConversionFunctionNames.InsertNode(SpecialName, InsertPos);
349 return {SpecialName, DeclarationName::StoredCXXConversionFunctionName};
350}
351
354 CanQualType Ty) {
355 switch (Kind) {
357 return getCXXConstructorName(Ty);
359 return getCXXDestructorName(Ty);
362 default:
363 llvm_unreachable("Invalid kind in getCXXSpecialName!");
364 }
365}
366
369 llvm::FoldingSetNodeID ID;
370 ID.AddPointer(II);
371
372 void *InsertPos = nullptr;
373 if (auto *Name = CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos))
374 return DeclarationName(Name);
375
376 auto *LiteralName = new (Ctx) detail::CXXLiteralOperatorIdName(II);
377 CXXLiteralOperatorNames.InsertNode(LiteralName, InsertPos);
378 return DeclarationName(LiteralName);
379}
380
382 switch (Name.getNameKind()) {
385 break;
389 setNamedTypeLoc(nullptr);
390 break;
392 setCXXOperatorNameRange(SourceRange());
393 break;
395 setCXXLiteralOperatorNameLoc(SourceLocation());
396 break;
400 // FIXME: ?
401 break;
403 break;
404 }
405}
406
408 switch (Name.getNameKind()) {
417 return false;
418
422 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
423 return TInfo->getType()->containsUnexpandedParameterPack();
424
426 }
427 llvm_unreachable("All name kinds handled.");
428}
429
431 switch (Name.getNameKind()) {
440 return false;
441
445 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
446 return TInfo->getType()->isInstantiationDependentType();
447
449 }
450 llvm_unreachable("All name kinds handled.");
451}
452
454 std::string Result;
455 llvm::raw_string_ostream OS(Result);
456 OS << *this;
457 return Result;
458}
459
460raw_ostream &clang::operator<<(raw_ostream &OS, DeclarationNameInfo DNInfo) {
461 LangOptions LO;
462 DNInfo.printName(OS, PrintingPolicy(LangOptions()));
463 return OS;
464}
465
466void DeclarationNameInfo::printName(raw_ostream &OS, PrintingPolicy Policy) const {
467 switch (Name.getNameKind()) {
476 Name.print(OS, Policy);
477 return;
478
482 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo()) {
484 OS << '~';
486 OS << "operator ";
487 LangOptions LO;
488 Policy.adjustForCPlusPlus();
489 Policy.SuppressScope = true;
490 OS << TInfo->getType().getAsString(Policy);
491 } else
492 Name.print(OS, Policy);
493 return;
494 }
495 llvm_unreachable("Unexpected declaration name kind");
496}
497
498SourceLocation DeclarationNameInfo::getEndLocPrivate() const {
499 switch (Name.getNameKind()) {
502 return NameLoc;
503
505 return LocInfo.getCXXOperatorNameEndLoc();
506
508 return LocInfo.getCXXLiteralOperatorNameLoc();
509
513 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
514 return TInfo->getTypeLoc().getEndLoc();
515 else
516 return NameLoc;
517
518 // DNInfo work in progress: FIXME.
523 return NameLoc;
524 }
525 llvm_unreachable("Unexpected declaration name kind");
526}
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:187
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:968
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:6617
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:476
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:315
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
A (possibly-)qualified type.
Definition: Type.h:941
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:5970
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:394
A container of type source information.
Definition: Type.h:7726
The base class of the type hierarchy.
Definition: Type.h:1829
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition: Type.h:2708
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2700
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition: Type.h:2359
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8545
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:5031
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:86
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