Clang Project

clang_source_code/lib/AST/DeclarationName.cpp
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 Aunsigned B) {
42  return (A < B ? -1 : (A > B ? 1 : 0));
43}
44
45int DeclarationName::compare(DeclarationName LHSDeclarationName 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 = 0N = std::min(LNRN); 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(LNRN);
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(OSPolicy);
135}
136
137void DeclarationName::print(raw_ostream &OSconst PrintingPolicy &Policy) {
138  switch (getNameKind()) {
139  case DeclarationName::Identifier:
140    if (const IdentifierInfo *II = getAsIdentifierInfo())
141      OS << II->getName();
142    return;
143
144  case DeclarationName::ObjCZeroArgSelector:
145  case DeclarationName::ObjCOneArgSelector:
146  case DeclarationName::ObjCMultiArgSelector:
147    getObjCSelector().print(OS);
148    return;
149
150  case DeclarationName::CXXConstructorName:
151    return printCXXConstructorDestructorName(getCXXNameType(), OSPolicy);
152
153  case DeclarationName::CXXDestructorName:
154    OS << '~';
155    return printCXXConstructorDestructorName(getCXXNameType(), OSPolicy);
156
157  case DeclarationName::CXXDeductionGuideName:
158    OS << "<deduction guide for ";
159    getCXXDeductionGuideTemplate()->getDeclName().print(OSPolicy);
160    OS << '>';
161    return;
162
163  case DeclarationName::CXXOperatorName: {
164    static const char *const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
165        nullptr,
166#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly)  \
167  Spelling,
168#include "clang/Basic/OperatorKinds.def"
169    };
170    const char *OpName = OperatorNames[getCXXOverloadedOperator()];
171     (0) . __assert_fail ("OpName && \"not an overloaded operator\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/DeclarationName.cpp", 171, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(OpName && "not an overloaded operator");
172
173    OS << "operator";
174    if (OpName[0] >= 'a' && OpName[0] <= 'z')
175      OS << ' ';
176    OS << OpName;
177    return;
178  }
179
180  case DeclarationName::CXXLiteralOperatorName:
181    OS << "operator\"\"" << getCXXLiteralIdentifier()->getName();
182    return;
183
184  case DeclarationName::CXXConversionFunctionName: {
185    OS << "operator ";
186    QualType Type = getCXXNameType();
187    if (const RecordType *Rec = Type->getAs<RecordType>()) {
188      OS << *Rec->getDecl();
189      return;
190    }
191    // We know we're printing C++ here, ensure we print 'bool' properly.
192    PrintingPolicy CXXPolicy = Policy;
193    CXXPolicy.adjustForCPlusPlus();
194    Type.print(OSCXXPolicy);
195    return;
196  }
197  case DeclarationName::CXXUsingDirective:
198    OS << "<using-directive>";
199    return;
200  }
201
202  llvm_unreachable("Unexpected declaration name kind");
203}
204
205namespace clang {
206
207raw_ostream &operator<<(raw_ostream &OSDeclarationName N) {
208  LangOptions LO;
209  N.print(OSPrintingPolicy(LO));
210  return OS;
211}
212
213// namespace clang
214
215bool DeclarationName::isDependentName() const {
216  QualType T = getCXXNameType();
217  if (!T.isNull() && T->isDependentType())
218    return true;
219
220  // A class-scope deduction guide in a dependent context has a dependent name.
221  auto *TD = getCXXDeductionGuideTemplate();
222  if (TD && TD->getDeclContext()->isDependentContext())
223    return true;
224
225  return false;
226}
227
228std::string DeclarationName::getAsString() const {
229  std::string Result;
230  llvm::raw_string_ostream OS(Result);
231  OS << *this;
232  return OS.str();
233}
234
235void *DeclarationName::getFETokenInfoSlow() const {
236  switch (getNameKind()) {
237  case Identifier:
238    llvm_unreachable("case Identifier already handled by getFETokenInfo!");
239  case CXXConstructorName:
240  case CXXDestructorName:
241  case CXXConversionFunctionName:
242    return castAsCXXSpecialNameExtra()->FETokenInfo;
243  case CXXOperatorName:
244    return castAsCXXOperatorIdName()->FETokenInfo;
245  case CXXDeductionGuideName:
246    return castAsCXXDeductionGuideNameExtra()->FETokenInfo;
247  case CXXLiteralOperatorName:
248    return castAsCXXLiteralOperatorIdName()->FETokenInfo;
249  default:
250    llvm_unreachable("DeclarationName has no FETokenInfo!");
251  }
252}
253
254void DeclarationName::setFETokenInfoSlow(void *T) {
255  switch (getNameKind()) {
256  case Identifier:
257    llvm_unreachable("case Identifier already handled by setFETokenInfo!");
258  case CXXConstructorName:
259  case CXXDestructorName:
260  case CXXConversionFunctionName:
261    castAsCXXSpecialNameExtra()->FETokenInfo = T;
262    break;
263  case CXXOperatorName:
264    castAsCXXOperatorIdName()->FETokenInfo = T;
265    break;
266  case CXXDeductionGuideName:
267    castAsCXXDeductionGuideNameExtra()->FETokenInfo = T;
268    break;
269  case CXXLiteralOperatorName:
270    castAsCXXLiteralOperatorIdName()->FETokenInfo = T;
271    break;
272  default:
273    llvm_unreachable("DeclarationName has no FETokenInfo!");
274  }
275}
276
277LLVM_DUMP_METHOD void DeclarationName::dump() const {
278  llvm::errs() << *this << '\n';
279}
280
281DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
282  // Initialize the overloaded operator names.
283  for (unsigned Op = 0Op < NUM_OVERLOADED_OPERATORS; ++Op)
284    CXXOperatorNames[Op].Kind = static_cast<OverloadedOperatorKind>(Op);
285}
286
287DeclarationName
288DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl *Template) {
289  Template = cast<TemplateDecl>(Template->getCanonicalDecl());
290
291  llvm::FoldingSetNodeID ID;
292  ID.AddPointer(Template);
293
294  void *InsertPos = nullptr;
295  if (auto *Name = CXXDeductionGuideNames.FindNodeOrInsertPos(ID, InsertPos))
296    return DeclarationName(Name);
297
298  auto *Name = new (Ctx) detail::CXXDeductionGuideNameExtra(Template);
299  CXXDeductionGuideNames.InsertNode(Name, InsertPos);
300  return DeclarationName(Name);
301}
302
303DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) {
304  // The type of constructors is unqualified.
305  Ty = Ty.getUnqualifiedType();
306  // Do we already have this C++ constructor name ?
307  llvm::FoldingSetNodeID ID;
308  ID.AddPointer(Ty.getAsOpaquePtr());
309  void *InsertPos = nullptr;
310  if (auto *Name = CXXConstructorNames.FindNodeOrInsertPos(ID, InsertPos))
311    return {Name, DeclarationName::StoredCXXConstructorName};
312
313  // We have to create it.
314  auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
315  CXXConstructorNames.InsertNode(SpecialName, InsertPos);
316  return {SpecialName, DeclarationName::StoredCXXConstructorName};
317}
318
319DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) {
320  // The type of destructors is unqualified.
321  Ty = Ty.getUnqualifiedType();
322  // Do we already have this C++ destructor name ?
323  llvm::FoldingSetNodeID ID;
324  ID.AddPointer(Ty.getAsOpaquePtr());
325  void *InsertPos = nullptr;
326  if (auto *Name = CXXDestructorNames.FindNodeOrInsertPos(ID, InsertPos))
327    return {Name, DeclarationName::StoredCXXDestructorName};
328
329  // We have to create it.
330  auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
331  CXXDestructorNames.InsertNode(SpecialName, InsertPos);
332  return {SpecialName, DeclarationName::StoredCXXDestructorName};
333}
334
335DeclarationName
336DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) {
337  // Do we already have this C++ conversion function name ?
338  llvm::FoldingSetNodeID ID;
339  ID.AddPointer(Ty.getAsOpaquePtr());
340  void *InsertPos = nullptr;
341  if (auto *Name =
342          CXXConversionFunctionNames.FindNodeOrInsertPos(ID, InsertPos))
343    return {Name, DeclarationName::StoredCXXConversionFunctionName};
344
345  // We have to create it.
346  auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
347  CXXConversionFunctionNames.InsertNode(SpecialName, InsertPos);
348  return {SpecialName, DeclarationName::StoredCXXConversionFunctionName};
349}
350
351DeclarationName
352DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
353                                        CanQualType Ty) {
354  switch (Kind) {
355  case DeclarationName::CXXConstructorName:
356    return getCXXConstructorName(Ty);
357  case DeclarationName::CXXDestructorName:
358    return getCXXDestructorName(Ty);
359  case DeclarationName::CXXConversionFunctionName:
360    return getCXXConversionFunctionName(Ty);
361  default:
362    llvm_unreachable("Invalid kind in getCXXSpecialName!");
363  }
364}
365
366DeclarationName
367DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
368  llvm::FoldingSetNodeID ID;
369  ID.AddPointer(II);
370
371  void *InsertPos = nullptr;
372  if (auto *Name = CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos))
373    return DeclarationName(Name);
374
375  auto *LiteralName = new (Ctx) detail::CXXLiteralOperatorIdName(II);
376  CXXLiteralOperatorNames.InsertNode(LiteralName, InsertPos);
377  return DeclarationName(LiteralName);
378}
379
380DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
381  switch (Name.getNameKind()) {
382  case DeclarationName::Identifier:
383  case DeclarationName::CXXDeductionGuideName:
384    break;
385  case DeclarationName::CXXConstructorName:
386  case DeclarationName::CXXDestructorName:
387  case DeclarationName::CXXConversionFunctionName:
388    NamedType.TInfo = nullptr;
389    break;
390  case DeclarationName::CXXOperatorName:
391    CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
392    CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
393    break;
394  case DeclarationName::CXXLiteralOperatorName:
395    CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
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.NamedType.TInfo)
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.NamedType.TInfo)
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  printName(OS);
457  return OS.str();
458}
459
460void DeclarationNameInfo::printName(raw_ostream &OSconst {
461  switch (Name.getNameKind()) {
462  case DeclarationName::Identifier:
463  case DeclarationName::ObjCZeroArgSelector:
464  case DeclarationName::ObjCOneArgSelector:
465  case DeclarationName::ObjCMultiArgSelector:
466  case DeclarationName::CXXOperatorName:
467  case DeclarationName::CXXLiteralOperatorName:
468  case DeclarationName::CXXUsingDirective:
469  case DeclarationName::CXXDeductionGuideName:
470    OS << Name;
471    return;
472
473  case DeclarationName::CXXConstructorName:
474  case DeclarationName::CXXDestructorName:
475  case DeclarationName::CXXConversionFunctionName:
476    if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) {
477      if (Name.getNameKind() == DeclarationName::CXXDestructorName)
478        OS << '~';
479      else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
480        OS << "operator ";
481      LangOptions LO;
482      LO.CPlusPlus = true;
483      LO.Bool = true;
484      PrintingPolicy PP(LO);
485      PP.SuppressScope = true;
486      OS << TInfo->getType().getAsString(PP);
487    } else
488      OS << Name;
489    return;
490  }
491  llvm_unreachable("Unexpected declaration name kind");
492}
493
494SourceLocation DeclarationNameInfo::getEndLocPrivate() const {
495  switch (Name.getNameKind()) {
496  case DeclarationName::Identifier:
497  case DeclarationName::CXXDeductionGuideName:
498    return NameLoc;
499
500  case DeclarationName::CXXOperatorName: {
501    unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
502    return SourceLocation::getFromRawEncoding(raw);
503  }
504
505  case DeclarationName::CXXLiteralOperatorName: {
506    unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
507    return SourceLocation::getFromRawEncoding(raw);
508  }
509
510  case DeclarationName::CXXConstructorName:
511  case DeclarationName::CXXDestructorName:
512  case DeclarationName::CXXConversionFunctionName:
513    if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
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
clang::DeclarationName::compare
clang::DeclarationName::print
clang::DeclarationName::isDependentName
clang::DeclarationName::getAsString
clang::DeclarationName::getFETokenInfoSlow
clang::DeclarationName::setFETokenInfoSlow
clang::DeclarationName::dump
clang::DeclarationNameTable::getCXXDeductionGuideName
clang::DeclarationNameTable::getCXXConstructorName
clang::DeclarationNameTable::getCXXDestructorName
clang::DeclarationNameTable::getCXXConversionFunctionName
clang::DeclarationNameTable::getCXXSpecialName
clang::DeclarationNameTable::getCXXLiteralOperatorName
clang::DeclarationNameInfo::containsUnexpandedParameterPack
clang::DeclarationNameInfo::isInstantiationDependent
clang::DeclarationNameInfo::getAsString
clang::DeclarationNameInfo::printName
clang::DeclarationNameInfo::getEndLocPrivate