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-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// Provides a dynamic type identifier and a dynamically typed node container 10// that can be used to store an AST base node at runtime in the same storage in 11// 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_CLASS 52#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_CLASS 165#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 (const NestedNameSpecifier *NNS = NNSL->getNestedNameSpecifier()) 198 NNS->print(OS, PP); 199 else 200 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 else 218 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 232 OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n"; 233} 234 235SourceRange DynTypedNode::getSourceRange() const { 236 if (const CXXCtorInitializer *CCI = get<CXXCtorInitializer>()) 237 return CCI->getSourceRange(); 238 if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>()) 239 return NNSL->getSourceRange(); 240 if (const TypeLoc *TL = get<TypeLoc>()) 241 return TL->getSourceRange(); 242 if (const Decl *D = get<Decl>()) 243 return D->getSourceRange(); 244 if (const Stmt *S = get<Stmt>()) 245 return S->getSourceRange(); 246 if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>()) 247 return TAL->getSourceRange(); 248 if (const auto *C = get<OMPClause>()) 249 return SourceRange(C->getBeginLoc(), C->getEndLoc()); 250 if (const auto *CBS = get<CXXBaseSpecifier>()) 251 return CBS->getSourceRange(); 252 if (const auto *A = get<Attr>()) 253 return A->getRange(); 254 if (const ObjCProtocolLoc *P = get<ObjCProtocolLoc>()) 255 return P->getSourceRange(); 256 if (const ConceptReference *C = get<ConceptReference>()) 257 return C->getSourceRange(); 258 return SourceRange(); 259} 260