brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.2 KiB · 9a89a66 Raw
526 lines · 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-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the DeclarationName and DeclarationNameTable10// 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/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 44int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {45  if (LHS.getNameKind() != RHS.getNameKind())46    return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);47 48  switch (LHS.getNameKind()) {49  case DeclarationName::Identifier: {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 60  case DeclarationName::ObjCZeroArgSelector:61  case DeclarationName::ObjCOneArgSelector:62  case DeclarationName::ObjCMultiArgSelector: {63    Selector LHSSelector = LHS.getObjCSelector();64    Selector RHSSelector = RHS.getObjCSelector();65    // getNumArgs for ZeroArgSelector returns 0, but we still need to compare.66    if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector &&67        RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) {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 81  case DeclarationName::CXXConstructorName:82  case DeclarationName::CXXDestructorName:83  case DeclarationName::CXXConversionFunctionName:84    if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))85      return -1;86    if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))87      return 1;88    return 0;89 90  case DeclarationName::CXXDeductionGuideName:91    // We never want to compare deduction guide names for templates from92    // different scopes, so just compare the template-name.93    return compare(LHS.getCXXDeductionGuideTemplate()->getDeclName(),94                   RHS.getCXXDeductionGuideTemplate()->getDeclName());95 96  case DeclarationName::CXXOperatorName:97    return compareInt(LHS.getCXXOverloadedOperator(),98                      RHS.getCXXOverloadedOperator());99 100  case DeclarationName::CXXLiteralOperatorName:101    return LHS.getCXXLiteralIdentifier()->getName().compare(102        RHS.getCXXLiteralIdentifier()->getName());103 104  case DeclarationName::CXXUsingDirective:105    return 0;106  }107 108  llvm_unreachable("Invalid DeclarationName Kind!");109}110 111static void printCXXConstructorDestructorName(QualType ClassType,112                                              raw_ostream &OS,113                                              PrintingPolicy Policy) {114  // We know we're printing C++ here. Ensure we print types properly.115  Policy.adjustForCPlusPlus();116  Policy.SuppressScope = true;117 118  if (const RecordType *ClassRec = ClassType->getAsCanonical<RecordType>()) {119    ClassRec->getDecl()->printName(OS, Policy);120    return;121  }122  if (Policy.SuppressTemplateArgsInCXXConstructors) {123    if (auto *InjTy = ClassType->getAsCanonical<InjectedClassNameType>()) {124      InjTy->getDecl()->printName(OS, Policy);125      return;126    }127  }128  ClassType.print(OS, Policy);129}130 131void DeclarationName::print(raw_ostream &OS,132                            const PrintingPolicy &Policy) const {133  switch (getNameKind()) {134  case DeclarationName::Identifier:135    if (const IdentifierInfo *II = getAsIdentifierInfo()) {136      StringRef Name = II->getName();137      // If this is a mangled OpenMP variant name we strip off the mangling for138      // printing. It should not be visible to the user at all.139      if (II->isMangledOpenMPVariantName()) {140        std::pair<StringRef, StringRef> NameContextPair =141            Name.split(getOpenMPVariantManglingSeparatorStr());142        OS << NameContextPair.first << "["143           << OMPTraitInfo(NameContextPair.second) << "]";144      } else {145        OS << Name;146      }147    }148    return;149 150  case DeclarationName::ObjCZeroArgSelector:151  case DeclarationName::ObjCOneArgSelector:152  case DeclarationName::ObjCMultiArgSelector:153    getObjCSelector().print(OS);154    return;155 156  case DeclarationName::CXXConstructorName:157    return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);158 159  case DeclarationName::CXXDestructorName:160    OS << '~';161    return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);162 163  case DeclarationName::CXXDeductionGuideName:164    OS << "<deduction guide for ";165    getCXXDeductionGuideTemplate()->getDeclName().print(OS, Policy);166    OS << '>';167    return;168 169  case DeclarationName::CXXOperatorName: {170    const char *OpName = getOperatorSpelling(getCXXOverloadedOperator());171    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(OS, CXXPolicy);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 &OS, DeclarationName N) {208  LangOptions LO;209  N.print(OS, PrintingPolicy(LO));210  return OS;211}212 213} // namespace clang214 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 Result;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 = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op)284    CXXOperatorNames[Op].Kind = static_cast<OverloadedOperatorKind>(Op);285}286 287DeclarationName288DeclarationNameTable::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 335DeclarationName336DeclarationNameTable::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 351DeclarationName352DeclarationNameTable::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 366DeclarationName367DeclarationNameTable::getCXXLiteralOperatorName(const 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    setNamedTypeLoc(nullptr);389    break;390  case DeclarationName::CXXOperatorName:391    setCXXOperatorNameRange(SourceRange());392    break;393  case DeclarationName::CXXLiteralOperatorName:394    setCXXLiteralOperatorNameLoc(SourceLocation());395    break;396  case DeclarationName::ObjCZeroArgSelector:397  case DeclarationName::ObjCOneArgSelector:398  case DeclarationName::ObjCMultiArgSelector:399    // FIXME: ?400    break;401  case DeclarationName::CXXUsingDirective:402    break;403  }404}405 406bool DeclarationNameInfo::containsUnexpandedParameterPack() const {407  switch (Name.getNameKind()) {408  case DeclarationName::Identifier:409  case DeclarationName::ObjCZeroArgSelector:410  case DeclarationName::ObjCOneArgSelector:411  case DeclarationName::ObjCMultiArgSelector:412  case DeclarationName::CXXOperatorName:413  case DeclarationName::CXXLiteralOperatorName:414  case DeclarationName::CXXUsingDirective:415  case DeclarationName::CXXDeductionGuideName:416    return false;417 418  case DeclarationName::CXXConstructorName:419  case DeclarationName::CXXDestructorName:420  case DeclarationName::CXXConversionFunctionName:421    if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())422      return TInfo->getType()->containsUnexpandedParameterPack();423 424    return Name.getCXXNameType()->containsUnexpandedParameterPack();425  }426  llvm_unreachable("All name kinds handled.");427}428 429bool DeclarationNameInfo::isInstantiationDependent() const {430  switch (Name.getNameKind()) {431  case DeclarationName::Identifier:432  case DeclarationName::ObjCZeroArgSelector:433  case DeclarationName::ObjCOneArgSelector:434  case DeclarationName::ObjCMultiArgSelector:435  case DeclarationName::CXXOperatorName:436  case DeclarationName::CXXLiteralOperatorName:437  case DeclarationName::CXXUsingDirective:438  case DeclarationName::CXXDeductionGuideName:439    return false;440 441  case DeclarationName::CXXConstructorName:442  case DeclarationName::CXXDestructorName:443  case DeclarationName::CXXConversionFunctionName:444    if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())445      return TInfo->getType()->isInstantiationDependentType();446 447    return Name.getCXXNameType()->isInstantiationDependentType();448  }449  llvm_unreachable("All name kinds handled.");450}451 452std::string DeclarationNameInfo::getAsString() const {453  std::string Result;454  llvm::raw_string_ostream OS(Result);455  OS << *this;456  return Result;457}458 459raw_ostream &clang::operator<<(raw_ostream &OS, DeclarationNameInfo DNInfo) {460  LangOptions LO;461  DNInfo.printName(OS, PrintingPolicy(LangOptions()));462  return OS;463}464 465void DeclarationNameInfo::printName(raw_ostream &OS, PrintingPolicy Policy) const {466  switch (Name.getNameKind()) {467  case DeclarationName::Identifier:468  case DeclarationName::ObjCZeroArgSelector:469  case DeclarationName::ObjCOneArgSelector:470  case DeclarationName::ObjCMultiArgSelector:471  case DeclarationName::CXXOperatorName:472  case DeclarationName::CXXLiteralOperatorName:473  case DeclarationName::CXXUsingDirective:474  case DeclarationName::CXXDeductionGuideName:475    Name.print(OS, Policy);476    return;477 478  case DeclarationName::CXXConstructorName:479  case DeclarationName::CXXDestructorName:480  case DeclarationName::CXXConversionFunctionName:481    if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo()) {482      if (Name.getNameKind() == DeclarationName::CXXDestructorName)483        OS << '~';484      else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)485        OS << "operator ";486      LangOptions LO;487      Policy.adjustForCPlusPlus();488      Policy.SuppressScope = true;489      OS << TInfo->getType().getAsString(Policy);490    } else491      Name.print(OS, Policy);492    return;493  }494  llvm_unreachable("Unexpected declaration name kind");495}496 497SourceLocation DeclarationNameInfo::getEndLocPrivate() const {498  switch (Name.getNameKind()) {499  case DeclarationName::Identifier:500  case DeclarationName::CXXDeductionGuideName:501    return NameLoc;502 503  case DeclarationName::CXXOperatorName:504    return LocInfo.getCXXOperatorNameEndLoc();505 506  case DeclarationName::CXXLiteralOperatorName:507    return LocInfo.getCXXLiteralOperatorNameLoc();508 509  case DeclarationName::CXXConstructorName:510  case DeclarationName::CXXDestructorName:511  case DeclarationName::CXXConversionFunctionName:512    if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())513      return TInfo->getTypeLoc().getEndLoc();514    else515      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