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)