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