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 25 using namespace clang; 26 27 const 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 61 bool ASTNodeKind::isBaseOf(ASTNodeKind Other) const { 62 return isBaseOf(KindId, Other.KindId); 63 } 64 65 bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const { 66 return isBaseOf(KindId, Other.KindId, Distance); 67 } 68 69 bool 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 78 bool 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 91 ASTNodeKind 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 102 StringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; } 103 104 ASTNodeKind 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 111 ASTNodeKind 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 120 ASTNodeKind 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 130 ASTNodeKind 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 141 ASTNodeKind 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 162 ASTNodeKind 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 176 ASTNodeKind 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 186 void 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 221 void 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 else 234 OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n"; 235 } 236 237 SourceRange DynTypedNode::getSourceRange() 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 return TL->getSourceRange(); 244 if (const Decl *D = get<Decl>()) 245 return D->getSourceRange(); 246 if (const Stmt *S = get<Stmt>()) 247 return S->getSourceRange(); 248 if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>()) 249 return TAL->getSourceRange(); 250 if (const auto *C = get<OMPClause>()) 251 return SourceRange(C->getBeginLoc(), C->getEndLoc()); 252 if (const auto *CBS = get<CXXBaseSpecifier>()) 253 return CBS->getSourceRange(); 254 if (const auto *A = get<Attr>()) 255 return A->getRange(); 256 if (const ObjCProtocolLoc *P = get<ObjCProtocolLoc>()) 257 return P->getSourceRange(); 258 if (const ConceptReference *C = get<ConceptReference>()) 259 return C->getSourceRange(); 260 return SourceRange(); 261 } 262