DeclarationName.cpp revision 360784
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
14#include "clang/AST/DeclarationName.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclBase.h"
18#include "clang/AST/DeclCXX.h"
19#include "clang/AST/DeclTemplate.h"
20#include "clang/AST/PrettyPrinter.h"
21#include "clang/AST/Type.h"
22#include "clang/AST/TypeLoc.h"
23#include "clang/AST/TypeOrdering.h"
24#include "clang/Basic/IdentifierTable.h"
25#include "clang/Basic/LLVM.h"
26#include "clang/Basic/LangOptions.h"
27#include "clang/Basic/OperatorKinds.h"
28#include "clang/Basic/SourceLocation.h"
29#include "llvm/ADT/FoldingSet.h"
30#include "llvm/Support/Casting.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 <cstdint>
37#include <string>
38
39using namespace clang;
40
41static int compareInt(unsigned A, unsigned B) {
42  return (A < B ? -1 : (A > B ? 1 : 0));
43}
44
45int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
46  if (LHS.getNameKind() != RHS.getNameKind())
47    return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);
48
49  switch (LHS.getNameKind()) {
50  case DeclarationName::Identifier: {
51    IdentifierInfo *LII = LHS.castAsIdentifierInfo();
52    IdentifierInfo *RII = RHS.castAsIdentifierInfo();
53    if (!LII)
54      return RII ? -1 : 0;
55    if (!RII)
56      return 1;
57
58    return LII->getName().compare(RII->getName());
59  }
60
61  case DeclarationName::ObjCZeroArgSelector:
62  case DeclarationName::ObjCOneArgSelector:
63  case DeclarationName::ObjCMultiArgSelector: {
64    Selector LHSSelector = LHS.getObjCSelector();
65    Selector RHSSelector = RHS.getObjCSelector();
66    // getNumArgs for ZeroArgSelector returns 0, but we still need to compare.
67    if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector &&
68        RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) {
69      return LHSSelector.getAsIdentifierInfo()->getName().compare(
70          RHSSelector.getAsIdentifierInfo()->getName());
71    }
72    unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
73    for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
74      switch (LHSSelector.getNameForSlot(I).compare(
75          RHSSelector.getNameForSlot(I))) {
76      case -1:
77        return -1;
78      case 1:
79        return 1;
80      default:
81        break;
82      }
83    }
84
85    return compareInt(LN, RN);
86  }
87
88  case DeclarationName::CXXConstructorName:
89  case DeclarationName::CXXDestructorName:
90  case DeclarationName::CXXConversionFunctionName:
91    if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))
92      return -1;
93    if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))
94      return 1;
95    return 0;
96
97  case DeclarationName::CXXDeductionGuideName:
98    // We never want to compare deduction guide names for templates from
99    // different scopes, so just compare the template-name.
100    return compare(LHS.getCXXDeductionGuideTemplate()->getDeclName(),
101                   RHS.getCXXDeductionGuideTemplate()->getDeclName());
102
103  case DeclarationName::CXXOperatorName:
104    return compareInt(LHS.getCXXOverloadedOperator(),
105                      RHS.getCXXOverloadedOperator());
106
107  case DeclarationName::CXXLiteralOperatorName:
108    return LHS.getCXXLiteralIdentifier()->getName().compare(
109        RHS.getCXXLiteralIdentifier()->getName());
110
111  case DeclarationName::CXXUsingDirective:
112    return 0;
113  }
114
115  llvm_unreachable("Invalid DeclarationName Kind!");
116}
117
118static void printCXXConstructorDestructorName(QualType ClassType,
119                                              raw_ostream &OS,
120                                              PrintingPolicy Policy) {
121  // We know we're printing C++ here. Ensure we print types properly.
122  Policy.adjustForCPlusPlus();
123
124  if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) {
125    OS << *ClassRec->getDecl();
126    return;
127  }
128  if (Policy.SuppressTemplateArgsInCXXConstructors) {
129    if (auto *InjTy = ClassType->getAs<InjectedClassNameType>()) {
130      OS << *InjTy->getDecl();
131      return;
132    }
133  }
134  ClassType.print(OS, Policy);
135}
136
137void DeclarationName::print(raw_ostream &OS,
138                            const PrintingPolicy &Policy) const {
139  switch (getNameKind()) {
140  case DeclarationName::Identifier:
141    if (const IdentifierInfo *II = getAsIdentifierInfo())
142      OS << II->getName();
143    return;
144
145  case DeclarationName::ObjCZeroArgSelector:
146  case DeclarationName::ObjCOneArgSelector:
147  case DeclarationName::ObjCMultiArgSelector:
148    getObjCSelector().print(OS);
149    return;
150
151  case DeclarationName::CXXConstructorName:
152    return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);
153
154  case DeclarationName::CXXDestructorName:
155    OS << '~';
156    return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);
157
158  case DeclarationName::CXXDeductionGuideName:
159    OS << "<deduction guide for ";
160    getCXXDeductionGuideTemplate()->getDeclName().print(OS, Policy);
161    OS << '>';
162    return;
163
164  case DeclarationName::CXXOperatorName: {
165    const char *OpName = getOperatorSpelling(getCXXOverloadedOperator());
166    assert(OpName && "not an overloaded operator");
167
168    OS << "operator";
169    if (OpName[0] >= 'a' && OpName[0] <= 'z')
170      OS << ' ';
171    OS << OpName;
172    return;
173  }
174
175  case DeclarationName::CXXLiteralOperatorName:
176    OS << "operator\"\"" << getCXXLiteralIdentifier()->getName();
177    return;
178
179  case DeclarationName::CXXConversionFunctionName: {
180    OS << "operator ";
181    QualType Type = getCXXNameType();
182    if (const RecordType *Rec = Type->getAs<RecordType>()) {
183      OS << *Rec->getDecl();
184      return;
185    }
186    // We know we're printing C++ here, ensure we print 'bool' properly.
187    PrintingPolicy CXXPolicy = Policy;
188    CXXPolicy.adjustForCPlusPlus();
189    Type.print(OS, CXXPolicy);
190    return;
191  }
192  case DeclarationName::CXXUsingDirective:
193    OS << "<using-directive>";
194    return;
195  }
196
197  llvm_unreachable("Unexpected declaration name kind");
198}
199
200namespace clang {
201
202raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) {
203  LangOptions LO;
204  N.print(OS, PrintingPolicy(LO));
205  return OS;
206}
207
208} // namespace clang
209
210bool DeclarationName::isDependentName() const {
211  QualType T = getCXXNameType();
212  if (!T.isNull() && T->isDependentType())
213    return true;
214
215  // A class-scope deduction guide in a dependent context has a dependent name.
216  auto *TD = getCXXDeductionGuideTemplate();
217  if (TD && TD->getDeclContext()->isDependentContext())
218    return true;
219
220  return false;
221}
222
223std::string DeclarationName::getAsString() const {
224  std::string Result;
225  llvm::raw_string_ostream OS(Result);
226  OS << *this;
227  return OS.str();
228}
229
230void *DeclarationName::getFETokenInfoSlow() const {
231  switch (getNameKind()) {
232  case Identifier:
233    llvm_unreachable("case Identifier already handled by getFETokenInfo!");
234  case CXXConstructorName:
235  case CXXDestructorName:
236  case CXXConversionFunctionName:
237    return castAsCXXSpecialNameExtra()->FETokenInfo;
238  case CXXOperatorName:
239    return castAsCXXOperatorIdName()->FETokenInfo;
240  case CXXDeductionGuideName:
241    return castAsCXXDeductionGuideNameExtra()->FETokenInfo;
242  case CXXLiteralOperatorName:
243    return castAsCXXLiteralOperatorIdName()->FETokenInfo;
244  default:
245    llvm_unreachable("DeclarationName has no FETokenInfo!");
246  }
247}
248
249void DeclarationName::setFETokenInfoSlow(void *T) {
250  switch (getNameKind()) {
251  case Identifier:
252    llvm_unreachable("case Identifier already handled by setFETokenInfo!");
253  case CXXConstructorName:
254  case CXXDestructorName:
255  case CXXConversionFunctionName:
256    castAsCXXSpecialNameExtra()->FETokenInfo = T;
257    break;
258  case CXXOperatorName:
259    castAsCXXOperatorIdName()->FETokenInfo = T;
260    break;
261  case CXXDeductionGuideName:
262    castAsCXXDeductionGuideNameExtra()->FETokenInfo = T;
263    break;
264  case CXXLiteralOperatorName:
265    castAsCXXLiteralOperatorIdName()->FETokenInfo = T;
266    break;
267  default:
268    llvm_unreachable("DeclarationName has no FETokenInfo!");
269  }
270}
271
272LLVM_DUMP_METHOD void DeclarationName::dump() const {
273  llvm::errs() << *this << '\n';
274}
275
276DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
277  // Initialize the overloaded operator names.
278  for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op)
279    CXXOperatorNames[Op].Kind = static_cast<OverloadedOperatorKind>(Op);
280}
281
282DeclarationName
283DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl *Template) {
284  Template = cast<TemplateDecl>(Template->getCanonicalDecl());
285
286  llvm::FoldingSetNodeID ID;
287  ID.AddPointer(Template);
288
289  void *InsertPos = nullptr;
290  if (auto *Name = CXXDeductionGuideNames.FindNodeOrInsertPos(ID, InsertPos))
291    return DeclarationName(Name);
292
293  auto *Name = new (Ctx) detail::CXXDeductionGuideNameExtra(Template);
294  CXXDeductionGuideNames.InsertNode(Name, InsertPos);
295  return DeclarationName(Name);
296}
297
298DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) {
299  // The type of constructors is unqualified.
300  Ty = Ty.getUnqualifiedType();
301  // Do we already have this C++ constructor name ?
302  llvm::FoldingSetNodeID ID;
303  ID.AddPointer(Ty.getAsOpaquePtr());
304  void *InsertPos = nullptr;
305  if (auto *Name = CXXConstructorNames.FindNodeOrInsertPos(ID, InsertPos))
306    return {Name, DeclarationName::StoredCXXConstructorName};
307
308  // We have to create it.
309  auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
310  CXXConstructorNames.InsertNode(SpecialName, InsertPos);
311  return {SpecialName, DeclarationName::StoredCXXConstructorName};
312}
313
314DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) {
315  // The type of destructors is unqualified.
316  Ty = Ty.getUnqualifiedType();
317  // Do we already have this C++ destructor name ?
318  llvm::FoldingSetNodeID ID;
319  ID.AddPointer(Ty.getAsOpaquePtr());
320  void *InsertPos = nullptr;
321  if (auto *Name = CXXDestructorNames.FindNodeOrInsertPos(ID, InsertPos))
322    return {Name, DeclarationName::StoredCXXDestructorName};
323
324  // We have to create it.
325  auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
326  CXXDestructorNames.InsertNode(SpecialName, InsertPos);
327  return {SpecialName, DeclarationName::StoredCXXDestructorName};
328}
329
330DeclarationName
331DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) {
332  // Do we already have this C++ conversion function name ?
333  llvm::FoldingSetNodeID ID;
334  ID.AddPointer(Ty.getAsOpaquePtr());
335  void *InsertPos = nullptr;
336  if (auto *Name =
337          CXXConversionFunctionNames.FindNodeOrInsertPos(ID, InsertPos))
338    return {Name, DeclarationName::StoredCXXConversionFunctionName};
339
340  // We have to create it.
341  auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
342  CXXConversionFunctionNames.InsertNode(SpecialName, InsertPos);
343  return {SpecialName, DeclarationName::StoredCXXConversionFunctionName};
344}
345
346DeclarationName
347DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
348                                        CanQualType Ty) {
349  switch (Kind) {
350  case DeclarationName::CXXConstructorName:
351    return getCXXConstructorName(Ty);
352  case DeclarationName::CXXDestructorName:
353    return getCXXDestructorName(Ty);
354  case DeclarationName::CXXConversionFunctionName:
355    return getCXXConversionFunctionName(Ty);
356  default:
357    llvm_unreachable("Invalid kind in getCXXSpecialName!");
358  }
359}
360
361DeclarationName
362DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
363  llvm::FoldingSetNodeID ID;
364  ID.AddPointer(II);
365
366  void *InsertPos = nullptr;
367  if (auto *Name = CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos))
368    return DeclarationName(Name);
369
370  auto *LiteralName = new (Ctx) detail::CXXLiteralOperatorIdName(II);
371  CXXLiteralOperatorNames.InsertNode(LiteralName, InsertPos);
372  return DeclarationName(LiteralName);
373}
374
375DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
376  switch (Name.getNameKind()) {
377  case DeclarationName::Identifier:
378  case DeclarationName::CXXDeductionGuideName:
379    break;
380  case DeclarationName::CXXConstructorName:
381  case DeclarationName::CXXDestructorName:
382  case DeclarationName::CXXConversionFunctionName:
383    NamedType.TInfo = nullptr;
384    break;
385  case DeclarationName::CXXOperatorName:
386    CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
387    CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
388    break;
389  case DeclarationName::CXXLiteralOperatorName:
390    CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
391    break;
392  case DeclarationName::ObjCZeroArgSelector:
393  case DeclarationName::ObjCOneArgSelector:
394  case DeclarationName::ObjCMultiArgSelector:
395    // FIXME: ?
396    break;
397  case DeclarationName::CXXUsingDirective:
398    break;
399  }
400}
401
402bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
403  switch (Name.getNameKind()) {
404  case DeclarationName::Identifier:
405  case DeclarationName::ObjCZeroArgSelector:
406  case DeclarationName::ObjCOneArgSelector:
407  case DeclarationName::ObjCMultiArgSelector:
408  case DeclarationName::CXXOperatorName:
409  case DeclarationName::CXXLiteralOperatorName:
410  case DeclarationName::CXXUsingDirective:
411  case DeclarationName::CXXDeductionGuideName:
412    return false;
413
414  case DeclarationName::CXXConstructorName:
415  case DeclarationName::CXXDestructorName:
416  case DeclarationName::CXXConversionFunctionName:
417    if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
418      return TInfo->getType()->containsUnexpandedParameterPack();
419
420    return Name.getCXXNameType()->containsUnexpandedParameterPack();
421  }
422  llvm_unreachable("All name kinds handled.");
423}
424
425bool DeclarationNameInfo::isInstantiationDependent() const {
426  switch (Name.getNameKind()) {
427  case DeclarationName::Identifier:
428  case DeclarationName::ObjCZeroArgSelector:
429  case DeclarationName::ObjCOneArgSelector:
430  case DeclarationName::ObjCMultiArgSelector:
431  case DeclarationName::CXXOperatorName:
432  case DeclarationName::CXXLiteralOperatorName:
433  case DeclarationName::CXXUsingDirective:
434  case DeclarationName::CXXDeductionGuideName:
435    return false;
436
437  case DeclarationName::CXXConstructorName:
438  case DeclarationName::CXXDestructorName:
439  case DeclarationName::CXXConversionFunctionName:
440    if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
441      return TInfo->getType()->isInstantiationDependentType();
442
443    return Name.getCXXNameType()->isInstantiationDependentType();
444  }
445  llvm_unreachable("All name kinds handled.");
446}
447
448std::string DeclarationNameInfo::getAsString() const {
449  std::string Result;
450  llvm::raw_string_ostream OS(Result);
451  OS << *this;
452  return OS.str();
453}
454
455raw_ostream &clang::operator<<(raw_ostream &OS, DeclarationNameInfo DNInfo) {
456  LangOptions LO;
457  DNInfo.printName(OS, PrintingPolicy(LangOptions()));
458  return OS;
459}
460
461void DeclarationNameInfo::printName(raw_ostream &OS, PrintingPolicy Policy) const {
462  switch (Name.getNameKind()) {
463  case DeclarationName::Identifier:
464  case DeclarationName::ObjCZeroArgSelector:
465  case DeclarationName::ObjCOneArgSelector:
466  case DeclarationName::ObjCMultiArgSelector:
467  case DeclarationName::CXXOperatorName:
468  case DeclarationName::CXXLiteralOperatorName:
469  case DeclarationName::CXXUsingDirective:
470  case DeclarationName::CXXDeductionGuideName:
471    Name.print(OS, Policy);
472    return;
473
474  case DeclarationName::CXXConstructorName:
475  case DeclarationName::CXXDestructorName:
476  case DeclarationName::CXXConversionFunctionName:
477    if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) {
478      if (Name.getNameKind() == DeclarationName::CXXDestructorName)
479        OS << '~';
480      else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
481        OS << "operator ";
482      LangOptions LO;
483      Policy.adjustForCPlusPlus();
484      Policy.SuppressScope = true;
485      OS << TInfo->getType().getAsString(Policy);
486    } else
487      Name.print(OS, Policy);
488    return;
489  }
490  llvm_unreachable("Unexpected declaration name kind");
491}
492
493SourceLocation DeclarationNameInfo::getEndLocPrivate() const {
494  switch (Name.getNameKind()) {
495  case DeclarationName::Identifier:
496  case DeclarationName::CXXDeductionGuideName:
497    return NameLoc;
498
499  case DeclarationName::CXXOperatorName: {
500    unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
501    return SourceLocation::getFromRawEncoding(raw);
502  }
503
504  case DeclarationName::CXXLiteralOperatorName: {
505    unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
506    return SourceLocation::getFromRawEncoding(raw);
507  }
508
509  case DeclarationName::CXXConstructorName:
510  case DeclarationName::CXXDestructorName:
511  case DeclarationName::CXXConversionFunctionName:
512    if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
513      return TInfo->getTypeLoc().getEndLoc();
514    else
515      return NameLoc;
516
517    // DNInfo work in progress: FIXME.
518  case DeclarationName::ObjCZeroArgSelector:
519  case DeclarationName::ObjCOneArgSelector:
520  case DeclarationName::ObjCMultiArgSelector:
521  case DeclarationName::CXXUsingDirective:
522    return NameLoc;
523  }
524  llvm_unreachable("Unexpected declaration name kind");
525}
526