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/OpenMPClause.h"
21#include "clang/AST/PrettyPrinter.h"
22#include "clang/AST/Type.h"
23#include "clang/AST/TypeLoc.h"
24#include "clang/AST/TypeOrdering.h"
25#include "clang/Basic/IdentifierTable.h"
26#include "clang/Basic/LLVM.h"
27#include "clang/Basic/LangOptions.h"
28#include "clang/Basic/OperatorKinds.h"
29#include "clang/Basic/SourceLocation.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
46int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
47  if (LHS.getNameKind() != RHS.getNameKind())
48    return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);
49
50  switch (LHS.getNameKind()) {
51  case DeclarationName::Identifier: {
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
62  case DeclarationName::ObjCZeroArgSelector:
63  case DeclarationName::ObjCOneArgSelector:
64  case DeclarationName::ObjCMultiArgSelector: {
65    Selector LHSSelector = LHS.getObjCSelector();
66    Selector RHSSelector = RHS.getObjCSelector();
67    // getNumArgs for ZeroArgSelector returns 0, but we still need to compare.
68    if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector &&
69        RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) {
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
83  case DeclarationName::CXXConstructorName:
84  case DeclarationName::CXXDestructorName:
85  case DeclarationName::CXXConversionFunctionName:
86    if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))
87      return -1;
88    if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))
89      return 1;
90    return 0;
91
92  case DeclarationName::CXXDeductionGuideName:
93    // We never want to compare deduction guide names for templates from
94    // different scopes, so just compare the template-name.
95    return compare(LHS.getCXXDeductionGuideTemplate()->getDeclName(),
96                   RHS.getCXXDeductionGuideTemplate()->getDeclName());
97
98  case DeclarationName::CXXOperatorName:
99    return compareInt(LHS.getCXXOverloadedOperator(),
100                      RHS.getCXXOverloadedOperator());
101
102  case DeclarationName::CXXLiteralOperatorName:
103    return LHS.getCXXLiteralIdentifier()->getName().compare(
104        RHS.getCXXLiteralIdentifier()->getName());
105
106  case DeclarationName::CXXUsingDirective:
107    return 0;
108  }
109
110  llvm_unreachable("Invalid DeclarationName Kind!");
111}
112
113static void printCXXConstructorDestructorName(QualType ClassType,
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  }
123  if (Policy.SuppressTemplateArgsInCXXConstructors) {
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()) {
135  case DeclarationName::Identifier:
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 =
142            Name.split(getOpenMPVariantManglingSeparatorStr());
143        OS << NameContextPair.first << "["
144           << OMPTraitInfo(NameContextPair.second) << "]";
145      } else {
146        OS << Name;
147      }
148    }
149    return;
150
151  case DeclarationName::ObjCZeroArgSelector:
152  case DeclarationName::ObjCOneArgSelector:
153  case DeclarationName::ObjCMultiArgSelector:
154    getObjCSelector().print(OS);
155    return;
156
157  case DeclarationName::CXXConstructorName:
158    return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);
159
160  case DeclarationName::CXXDestructorName:
161    OS << '~';
162    return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);
163
164  case DeclarationName::CXXDeductionGuideName:
165    OS << "<deduction guide for ";
166    getCXXDeductionGuideTemplate()->getDeclName().print(OS, Policy);
167    OS << '>';
168    return;
169
170  case DeclarationName::CXXOperatorName: {
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
181  case DeclarationName::CXXLiteralOperatorName:
182    OS << "operator\"\"" << getCXXLiteralIdentifier()->getName();
183    return;
184
185  case DeclarationName::CXXConversionFunctionName: {
186    OS << "operator ";
187    QualType Type = getCXXNameType();
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  }
198  case DeclarationName::CXXUsingDirective:
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
216bool DeclarationName::isDependentName() const {
217  QualType T = getCXXNameType();
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!");
240  case CXXConstructorName:
241  case CXXDestructorName:
242  case CXXConversionFunctionName:
243    return castAsCXXSpecialNameExtra()->FETokenInfo;
244  case CXXOperatorName:
245    return castAsCXXOperatorIdName()->FETokenInfo;
246  case CXXDeductionGuideName:
247    return castAsCXXDeductionGuideNameExtra()->FETokenInfo;
248  case CXXLiteralOperatorName:
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!");
259  case CXXConstructorName:
260  case CXXDestructorName:
261  case CXXConversionFunctionName:
262    castAsCXXSpecialNameExtra()->FETokenInfo = T;
263    break;
264  case CXXOperatorName:
265    castAsCXXOperatorIdName()->FETokenInfo = T;
266    break;
267  case CXXDeductionGuideName:
268    castAsCXXDeductionGuideNameExtra()->FETokenInfo = T;
269    break;
270  case CXXLiteralOperatorName:
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
282DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
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
288DeclarationName
289DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl *Template) {
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
304DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) {
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
320DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) {
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
336DeclarationName
337DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) {
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
352DeclarationName
353DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
354                                        CanQualType Ty) {
355  switch (Kind) {
356  case DeclarationName::CXXConstructorName:
357    return getCXXConstructorName(Ty);
358  case DeclarationName::CXXDestructorName:
359    return getCXXDestructorName(Ty);
360  case DeclarationName::CXXConversionFunctionName:
361    return getCXXConversionFunctionName(Ty);
362  default:
363    llvm_unreachable("Invalid kind in getCXXSpecialName!");
364  }
365}
366
367DeclarationName
368DeclarationNameTable::getCXXLiteralOperatorName(const IdentifierInfo *II) {
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
381DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
382  switch (Name.getNameKind()) {
383  case DeclarationName::Identifier:
384  case DeclarationName::CXXDeductionGuideName:
385    break;
386  case DeclarationName::CXXConstructorName:
387  case DeclarationName::CXXDestructorName:
388  case DeclarationName::CXXConversionFunctionName:
389    setNamedTypeLoc(nullptr);
390    break;
391  case DeclarationName::CXXOperatorName:
392    setCXXOperatorNameRange(SourceRange());
393    break;
394  case DeclarationName::CXXLiteralOperatorName:
395    setCXXLiteralOperatorNameLoc(SourceLocation());
396    break;
397  case DeclarationName::ObjCZeroArgSelector:
398  case DeclarationName::ObjCOneArgSelector:
399  case DeclarationName::ObjCMultiArgSelector:
400    // FIXME: ?
401    break;
402  case DeclarationName::CXXUsingDirective:
403    break;
404  }
405}
406
407bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
408  switch (Name.getNameKind()) {
409  case DeclarationName::Identifier:
410  case DeclarationName::ObjCZeroArgSelector:
411  case DeclarationName::ObjCOneArgSelector:
412  case DeclarationName::ObjCMultiArgSelector:
413  case DeclarationName::CXXOperatorName:
414  case DeclarationName::CXXLiteralOperatorName:
415  case DeclarationName::CXXUsingDirective:
416  case DeclarationName::CXXDeductionGuideName:
417    return false;
418
419  case DeclarationName::CXXConstructorName:
420  case DeclarationName::CXXDestructorName:
421  case DeclarationName::CXXConversionFunctionName:
422    if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
423      return TInfo->getType()->containsUnexpandedParameterPack();
424
425    return Name.getCXXNameType()->containsUnexpandedParameterPack();
426  }
427  llvm_unreachable("All name kinds handled.");
428}
429
430bool DeclarationNameInfo::isInstantiationDependent() const {
431  switch (Name.getNameKind()) {
432  case DeclarationName::Identifier:
433  case DeclarationName::ObjCZeroArgSelector:
434  case DeclarationName::ObjCOneArgSelector:
435  case DeclarationName::ObjCMultiArgSelector:
436  case DeclarationName::CXXOperatorName:
437  case DeclarationName::CXXLiteralOperatorName:
438  case DeclarationName::CXXUsingDirective:
439  case DeclarationName::CXXDeductionGuideName:
440    return false;
441
442  case DeclarationName::CXXConstructorName:
443  case DeclarationName::CXXDestructorName:
444  case DeclarationName::CXXConversionFunctionName:
445    if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
446      return TInfo->getType()->isInstantiationDependentType();
447
448    return Name.getCXXNameType()->isInstantiationDependentType();
449  }
450  llvm_unreachable("All name kinds handled.");
451}
452
453std::string DeclarationNameInfo::getAsString() const {
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()) {
468  case DeclarationName::Identifier:
469  case DeclarationName::ObjCZeroArgSelector:
470  case DeclarationName::ObjCOneArgSelector:
471  case DeclarationName::ObjCMultiArgSelector:
472  case DeclarationName::CXXOperatorName:
473  case DeclarationName::CXXLiteralOperatorName:
474  case DeclarationName::CXXUsingDirective:
475  case DeclarationName::CXXDeductionGuideName:
476    Name.print(OS, Policy);
477    return;
478
479  case DeclarationName::CXXConstructorName:
480  case DeclarationName::CXXDestructorName:
481  case DeclarationName::CXXConversionFunctionName:
482    if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo()) {
483      if (Name.getNameKind() == DeclarationName::CXXDestructorName)
484        OS << '~';
485      else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
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()) {
500  case DeclarationName::Identifier:
501  case DeclarationName::CXXDeductionGuideName:
502    return NameLoc;
503
504  case DeclarationName::CXXOperatorName:
505    return LocInfo.getCXXOperatorNameEndLoc();
506
507  case DeclarationName::CXXLiteralOperatorName:
508    return LocInfo.getCXXLiteralOperatorNameLoc();
509
510  case DeclarationName::CXXConstructorName:
511  case DeclarationName::CXXDestructorName:
512  case DeclarationName::CXXConversionFunctionName:
513    if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
514      return TInfo->getTypeLoc().getEndLoc();
515    else
516      return NameLoc;
517
518    // DNInfo work in progress: FIXME.
519  case DeclarationName::ObjCZeroArgSelector:
520  case DeclarationName::ObjCOneArgSelector:
521  case DeclarationName::ObjCMultiArgSelector:
522  case DeclarationName::CXXUsingDirective:
523    return NameLoc;
524  }
525  llvm_unreachable("Unexpected declaration name kind");
526}
527