brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.0 KiB · 84eb777 Raw
284 lines · cpp
1//===--- ASTTypeTraits.cpp --------------------------------------*- C++ -*-===//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//  Provides a dynamic type identifier and a dynamically typed node container10//  that can be used to store an AST base node at runtime in the same storage in11//  a type safe way.12//13//===----------------------------------------------------------------------===//14 15#include "clang/AST/ASTTypeTraits.h"16#include "clang/AST/ASTConcept.h"17#include "clang/AST/ASTContext.h"18#include "clang/AST/Attr.h"19#include "clang/AST/DeclCXX.h"20#include "clang/AST/DeclObjC.h"21#include "clang/AST/NestedNameSpecifier.h"22#include "clang/AST/OpenMPClause.h"23#include "clang/AST/TypeLoc.h"24 25using namespace clang;26 27const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = {28    {NKI_None, "<None>"},29    {NKI_None, "TemplateArgument"},30    {NKI_None, "TemplateArgumentLoc"},31    {NKI_None, "LambdaCapture"},32    {NKI_None, "TemplateName"},33    {NKI_None, "NestedNameSpecifierLoc"},34    {NKI_None, "QualType"},35#define TYPELOC(CLASS, PARENT) {NKI_##PARENT, #CLASS "TypeLoc"},36#include "clang/AST/TypeLocNodes.def"37    {NKI_None, "TypeLoc"},38    {NKI_None, "CXXBaseSpecifier"},39    {NKI_None, "CXXCtorInitializer"},40    {NKI_None, "NestedNameSpecifier"},41    {NKI_None, "Decl"},42#define DECL(DERIVED, BASE) { NKI_##BASE, #DERIVED "Decl" },43#include "clang/AST/DeclNodes.inc"44    {NKI_None, "Stmt"},45#define STMT(DERIVED, BASE) { NKI_##BASE, #DERIVED },46#include "clang/AST/StmtNodes.inc"47    {NKI_None, "Type"},48#define TYPE(DERIVED, BASE) { NKI_##BASE, #DERIVED "Type" },49#include "clang/AST/TypeNodes.inc"50    {NKI_None, "OMPClause"},51#define GEN_CLANG_CLAUSE_CLASS52#define CLAUSE_CLASS(Enum, Str, Class) {NKI_OMPClause, #Class},53#include "llvm/Frontend/OpenMP/OMP.inc"54    {NKI_None, "Attr"},55#define ATTR(A) {NKI_Attr, #A "Attr"},56#include "clang/Basic/AttrList.inc"57    {NKI_None, "ObjCProtocolLoc"},58    {NKI_None, "ConceptReference"},59};60 61bool ASTNodeKind::isBaseOf(ASTNodeKind Other) const {62  return isBaseOf(KindId, Other.KindId);63}64 65bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const {66  return isBaseOf(KindId, Other.KindId, Distance);67}68 69bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived) {70  if (Base == NKI_None || Derived == NKI_None)71    return false;72  while (Derived != Base && Derived != NKI_None) {73    Derived = AllKindInfo[Derived].ParentId;74  }75  return Derived == Base;76}77 78bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived,79                           unsigned *Distance) {80  if (Base == NKI_None || Derived == NKI_None) return false;81  unsigned Dist = 0;82  while (Derived != Base && Derived != NKI_None) {83    Derived = AllKindInfo[Derived].ParentId;84    ++Dist;85  }86  if (Distance)87    *Distance = Dist;88  return Derived == Base;89}90 91ASTNodeKind ASTNodeKind::getCladeKind() const {92  NodeKindId LastId = KindId;93  while (LastId) {94    NodeKindId ParentId = AllKindInfo[LastId].ParentId;95    if (ParentId == NKI_None)96      return LastId;97    LastId = ParentId;98  }99  return NKI_None;100}101 102StringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; }103 104ASTNodeKind ASTNodeKind::getMostDerivedType(ASTNodeKind Kind1,105                                            ASTNodeKind Kind2) {106  if (Kind1.isBaseOf(Kind2)) return Kind2;107  if (Kind2.isBaseOf(Kind1)) return Kind1;108  return ASTNodeKind();109}110 111ASTNodeKind ASTNodeKind::getMostDerivedCommonAncestor(ASTNodeKind Kind1,112                                                      ASTNodeKind Kind2) {113  NodeKindId Parent = Kind1.KindId;114  while (!isBaseOf(Parent, Kind2.KindId) && Parent != NKI_None) {115    Parent = AllKindInfo[Parent].ParentId;116  }117  return ASTNodeKind(Parent);118}119 120ASTNodeKind ASTNodeKind::getFromNode(const Decl &D) {121  switch (D.getKind()) {122#define DECL(DERIVED, BASE)                                                    \123    case Decl::DERIVED: return ASTNodeKind(NKI_##DERIVED##Decl);124#define ABSTRACT_DECL(D)125#include "clang/AST/DeclNodes.inc"126  };127  llvm_unreachable("invalid decl kind");128}129 130ASTNodeKind ASTNodeKind::getFromNode(const Stmt &S) {131  switch (S.getStmtClass()) {132    case Stmt::NoStmtClass: return NKI_None;133#define STMT(CLASS, PARENT)                                                    \134    case Stmt::CLASS##Class: return ASTNodeKind(NKI_##CLASS);135#define ABSTRACT_STMT(S)136#include "clang/AST/StmtNodes.inc"137  }138  llvm_unreachable("invalid stmt kind");139}140 141ASTNodeKind ASTNodeKind::getFromNode(const Type &T) {142  switch (T.getTypeClass()) {143#define TYPE(Class, Base)                                                      \144    case Type::Class: return ASTNodeKind(NKI_##Class##Type);145#define ABSTRACT_TYPE(Class, Base)146#include "clang/AST/TypeNodes.inc"147  }148  llvm_unreachable("invalid type kind");149 }150 151 ASTNodeKind ASTNodeKind::getFromNode(const TypeLoc &T) {152   switch (T.getTypeLocClass()) {153#define ABSTRACT_TYPELOC(CLASS, PARENT)154#define TYPELOC(CLASS, PARENT)                                                 \155  case TypeLoc::CLASS:                                                         \156    return ASTNodeKind(NKI_##CLASS##TypeLoc);157#include "clang/AST/TypeLocNodes.def"158   }159   llvm_unreachable("invalid typeloc kind");160 }161 162ASTNodeKind ASTNodeKind::getFromNode(const OMPClause &C) {163  switch (C.getClauseKind()) {164#define GEN_CLANG_CLAUSE_CLASS165#define CLAUSE_CLASS(Enum, Str, Class)                                         \166  case llvm::omp::Clause::Enum:                                                \167    return ASTNodeKind(NKI_##Class);168#define CLAUSE_NO_CLASS(Enum, Str)                                             \169  case llvm::omp::Clause::Enum:                                                \170    llvm_unreachable("unexpected OpenMP clause kind");171#include "llvm/Frontend/OpenMP/OMP.inc"172  }173  llvm_unreachable("invalid omp clause kind");174}175 176ASTNodeKind ASTNodeKind::getFromNode(const Attr &A) {177  switch (A.getKind()) {178#define ATTR(A)                                                                \179  case attr::A:                                                                \180    return ASTNodeKind(NKI_##A##Attr);181#include "clang/Basic/AttrList.inc"182  }183  llvm_unreachable("invalid attr kind");184}185 186void DynTypedNode::print(llvm::raw_ostream &OS,187                         const PrintingPolicy &PP) const {188  if (const TemplateArgument *TA = get<TemplateArgument>())189    TA->print(PP, OS, /*IncludeType*/ true);190  else if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())191    TAL->getArgument().print(PP, OS, /*IncludeType*/ true);192  else if (const TemplateName *TN = get<TemplateName>())193    TN->print(OS, PP);194  else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>())195    NNS->print(OS, PP);196  else if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>()) {197    if (NestedNameSpecifier NNS = NNSL->getNestedNameSpecifier())198      NNS.print(OS, PP);199    else200      OS << "(empty NestedNameSpecifierLoc)";201  } else if (const QualType *QT = get<QualType>())202    QT->print(OS, PP);203  else if (const TypeLoc *TL = get<TypeLoc>())204    TL->getType().print(OS, PP);205  else if (const Decl *D = get<Decl>())206    D->print(OS, PP);207  else if (const Stmt *S = get<Stmt>())208    S->printPretty(OS, nullptr, PP);209  else if (const Type *T = get<Type>())210    QualType(T, 0).print(OS, PP);211  else if (const Attr *A = get<Attr>())212    A->printPretty(OS, PP);213  else if (const ObjCProtocolLoc *P = get<ObjCProtocolLoc>())214    P->getProtocol()->print(OS, PP);215  else if (const ConceptReference *C = get<ConceptReference>())216    C->print(OS, PP);217  else218    OS << "Unable to print values of type " << NodeKind.asStringRef() << "\n";219}220 221void DynTypedNode::dump(llvm::raw_ostream &OS,222                        const ASTContext &Context) const {223  if (const Decl *D = get<Decl>())224    D->dump(OS);225  else if (const Stmt *S = get<Stmt>())226    S->dump(OS, Context);227  else if (const Type *T = get<Type>())228    T->dump(OS, Context);229  else if (const ConceptReference *C = get<ConceptReference>())230    C->dump(OS);231  else if (const TypeLoc *TL = get<TypeLoc>())232    TL->dump(OS, Context);233  else234    OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n";235}236 237SourceRange DynTypedNode::getSourceRange(bool IncludeQualifier) const {238  if (const CXXCtorInitializer *CCI = get<CXXCtorInitializer>())239    return CCI->getSourceRange();240  if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>())241    return NNSL->getSourceRange();242  if (const TypeLoc *TL = get<TypeLoc>()) {243    if (IncludeQualifier)244      return TL->getSourceRange();245    switch (TL->getTypeLocClass()) {246    case TypeLoc::DependentName:247      return TL->castAs<DependentNameTypeLoc>().getNameLoc();248    case TypeLoc::TemplateSpecialization: {249      auto T = TL->castAs<TemplateSpecializationTypeLoc>();250      return SourceRange(T.getTemplateNameLoc(), T.getEndLoc());251    }252    case TypeLoc::Enum:253    case TypeLoc::Record:254    case TypeLoc::InjectedClassName:255      return TL->castAs<TagTypeLoc>().getNameLoc();256    case TypeLoc::Typedef:257      return TL->castAs<TypedefTypeLoc>().getNameLoc();258    case TypeLoc::UnresolvedUsing:259      return TL->castAs<UnresolvedUsingTypeLoc>().getNameLoc();260    case TypeLoc::Using:261      return TL->castAs<UsingTypeLoc>().getNameLoc();262    default:263      return TL->getSourceRange();264    }265  }266  if (const Decl *D = get<Decl>())267    return D->getSourceRange();268  if (const Stmt *S = get<Stmt>())269    return S->getSourceRange();270  if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())271    return TAL->getSourceRange();272  if (const auto *C = get<OMPClause>())273    return SourceRange(C->getBeginLoc(), C->getEndLoc());274  if (const auto *CBS = get<CXXBaseSpecifier>())275    return CBS->getSourceRange();276  if (const auto *A = get<Attr>())277    return A->getRange();278  if (const ObjCProtocolLoc *P = get<ObjCProtocolLoc>())279    return P->getSourceRange();280  if (const ConceptReference *C = get<ConceptReference>())281    return C->getSourceRange();282  return SourceRange();283}284