/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/ASTTypeTraits.cpp
Line | Count | Source (jump to first uncovered line) |
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/ASTContext.h" |
17 | | #include "clang/AST/Attr.h" |
18 | | #include "clang/AST/DeclCXX.h" |
19 | | #include "clang/AST/DeclObjC.h" |
20 | | #include "clang/AST/NestedNameSpecifier.h" |
21 | | #include "clang/AST/OpenMPClause.h" |
22 | | #include "clang/AST/TypeLoc.h" |
23 | | |
24 | | using namespace clang; |
25 | | |
26 | | const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = { |
27 | | {NKI_None, "<None>"}, |
28 | | {NKI_None, "TemplateArgument"}, |
29 | | {NKI_None, "TemplateArgumentLoc"}, |
30 | | {NKI_None, "LambdaCapture"}, |
31 | | {NKI_None, "TemplateName"}, |
32 | | {NKI_None, "NestedNameSpecifierLoc"}, |
33 | | {NKI_None, "QualType"}, |
34 | | #define TYPELOC(CLASS, PARENT) {NKI_##PARENT, #CLASS "TypeLoc"}, |
35 | | #include "clang/AST/TypeLocNodes.def" |
36 | | {NKI_None, "TypeLoc"}, |
37 | | {NKI_None, "CXXBaseSpecifier"}, |
38 | | {NKI_None, "CXXCtorInitializer"}, |
39 | | {NKI_None, "NestedNameSpecifier"}, |
40 | | {NKI_None, "Decl"}, |
41 | | #define DECL(DERIVED, BASE) { NKI_##BASE, #DERIVED "Decl" }, |
42 | | #include "clang/AST/DeclNodes.inc" |
43 | | {NKI_None, "Stmt"}, |
44 | | #define STMT(DERIVED, BASE) { NKI_##BASE, #DERIVED }, |
45 | | #include "clang/AST/StmtNodes.inc" |
46 | | {NKI_None, "Type"}, |
47 | | #define TYPE(DERIVED, BASE) { NKI_##BASE, #DERIVED "Type" }, |
48 | | #include "clang/AST/TypeNodes.inc" |
49 | | {NKI_None, "OMPClause"}, |
50 | | #define GEN_CLANG_CLAUSE_CLASS |
51 | | #define CLAUSE_CLASS(Enum, Str, Class) {NKI_OMPClause, #Class}, |
52 | | #include "llvm/Frontend/OpenMP/OMP.inc" |
53 | | {NKI_None, "Attr"}, |
54 | | #define ATTR(A) {NKI_Attr, #A "Attr"}, |
55 | | #include "clang/Basic/AttrList.inc" |
56 | | {NKI_None, "ObjCProtocolLoc"}, |
57 | | }; |
58 | | |
59 | 12.8M | bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const { |
60 | 12.8M | return isBaseOf(KindId, Other.KindId, Distance); |
61 | 12.8M | } |
62 | | |
63 | | bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived, |
64 | 12.8M | unsigned *Distance) { |
65 | 12.8M | if (Base == NKI_None || Derived == NKI_None12.8M ) return false2 ; |
66 | 12.8M | unsigned Dist = 0; |
67 | 40.2M | while (Derived != Base && Derived != NKI_None31.2M ) { |
68 | 27.4M | Derived = AllKindInfo[Derived].ParentId; |
69 | 27.4M | ++Dist; |
70 | 27.4M | } |
71 | 12.8M | if (Distance) |
72 | 27.4k | *Distance = Dist; |
73 | 12.8M | return Derived == Base; |
74 | 12.8M | } |
75 | | |
76 | 18 | ASTNodeKind ASTNodeKind::getCladeKind() const { |
77 | 18 | NodeKindId LastId = KindId; |
78 | 49 | while (LastId) { |
79 | 48 | NodeKindId ParentId = AllKindInfo[LastId].ParentId; |
80 | 48 | if (ParentId == NKI_None) |
81 | 17 | return LastId; |
82 | 31 | LastId = ParentId; |
83 | 31 | } |
84 | 1 | return NKI_None; |
85 | 18 | } |
86 | | |
87 | 2.76k | StringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; } |
88 | | |
89 | | ASTNodeKind ASTNodeKind::getMostDerivedType(ASTNodeKind Kind1, |
90 | 1.30M | ASTNodeKind Kind2) { |
91 | 1.30M | if (Kind1.isBaseOf(Kind2)) return Kind21.10M ; |
92 | 198k | if (Kind2.isBaseOf(Kind1)) return Kind1198k ; |
93 | 2 | return ASTNodeKind(); |
94 | 198k | } |
95 | | |
96 | | ASTNodeKind ASTNodeKind::getMostDerivedCommonAncestor(ASTNodeKind Kind1, |
97 | 5 | ASTNodeKind Kind2) { |
98 | 5 | NodeKindId Parent = Kind1.KindId; |
99 | 12 | while (!isBaseOf(Parent, Kind2.KindId, nullptr) && Parent != NKI_None8 ) { |
100 | 7 | Parent = AllKindInfo[Parent].ParentId; |
101 | 7 | } |
102 | 5 | return ASTNodeKind(Parent); |
103 | 5 | } |
104 | | |
105 | 1.08M | ASTNodeKind ASTNodeKind::getFromNode(const Decl &D) { |
106 | 1.08M | switch (D.getKind()) { |
107 | 0 | #define DECL(DERIVED, BASE) \ |
108 | 1.08M | case Decl::DERIVED: return ASTNodeKind(NKI_##DERIVED##Decl); |
109 | 0 | #define ABSTRACT_DECL(D) |
110 | 1.08M | #include "clang/AST/DeclNodes.inc"0 |
111 | 1.08M | }; |
112 | 0 | llvm_unreachable("invalid decl kind"); |
113 | 0 | } |
114 | | |
115 | 1.28M | ASTNodeKind ASTNodeKind::getFromNode(const Stmt &S) { |
116 | 1.28M | switch (S.getStmtClass()) { |
117 | 0 | case Stmt::NoStmtClass: return NKI_None; |
118 | 0 | #define STMT(CLASS, PARENT) \ |
119 | 1.28M | case Stmt::CLASS##Class: return ASTNodeKind(NKI_##CLASS); |
120 | 0 | #define ABSTRACT_STMT(S) |
121 | 1.28M | #include "clang/AST/StmtNodes.inc"0 |
122 | 1.28M | } |
123 | 0 | llvm_unreachable("invalid stmt kind"); |
124 | 0 | } |
125 | | |
126 | 57.6k | ASTNodeKind ASTNodeKind::getFromNode(const Type &T) { |
127 | 57.6k | switch (T.getTypeClass()) { |
128 | 0 | #define TYPE(Class, Base) \ |
129 | 57.6k | case Type::Class: return ASTNodeKind(NKI_##Class##Type); |
130 | 0 | #define ABSTRACT_TYPE(Class, Base) |
131 | 57.6k | #include "clang/AST/TypeNodes.inc"0 |
132 | 57.6k | } |
133 | 0 | llvm_unreachable("invalid type kind"); |
134 | 0 | } |
135 | | |
136 | 1.26M | ASTNodeKind ASTNodeKind::getFromNode(const TypeLoc &T) { |
137 | 1.26M | switch (T.getTypeLocClass()) { |
138 | 0 | #define ABSTRACT_TYPELOC(CLASS, PARENT) |
139 | 0 | #define TYPELOC(CLASS, PARENT) \ |
140 | 1.26M | case TypeLoc::CLASS: \ |
141 | 1.26M | return ASTNodeKind(NKI_##CLASS##TypeLoc); |
142 | 1.26M | #include "clang/AST/TypeLocNodes.def"0 |
143 | 1.26M | } |
144 | 0 | llvm_unreachable("invalid typeloc kind"); |
145 | 0 | } |
146 | | |
147 | 420 | ASTNodeKind ASTNodeKind::getFromNode(const OMPClause &C) { |
148 | 420 | switch (C.getClauseKind()) { |
149 | 0 | #define GEN_CLANG_CLAUSE_CLASS |
150 | 0 | #define CLAUSE_CLASS(Enum, Str, Class) \ |
151 | 420 | case llvm::omp::Clause::Enum: \ |
152 | 420 | return ASTNodeKind(NKI_##Class); |
153 | 0 | #define CLAUSE_NO_CLASS(Enum, Str) \ |
154 | 0 | case llvm::omp::Clause::Enum: \ |
155 | 0 | llvm_unreachable("unexpected OpenMP clause kind"); |
156 | 420 | #include "llvm/Frontend/OpenMP/OMP.inc"0 |
157 | 420 | } |
158 | 0 | llvm_unreachable("invalid omp clause kind"); |
159 | 0 | } |
160 | | |
161 | 2.42k | ASTNodeKind ASTNodeKind::getFromNode(const Attr &A) { |
162 | 2.42k | switch (A.getKind()) { |
163 | 0 | #define ATTR(A) \ |
164 | 2.42k | case attr::A: \ |
165 | 2.42k | return ASTNodeKind(NKI_##A##Attr); |
166 | 2.42k | #include "clang/Basic/AttrList.inc"0 |
167 | 2.42k | } |
168 | 0 | llvm_unreachable("invalid attr kind"); |
169 | 0 | } |
170 | | |
171 | | void DynTypedNode::print(llvm::raw_ostream &OS, |
172 | 8 | const PrintingPolicy &PP) const { |
173 | 8 | if (const TemplateArgument *TA = get<TemplateArgument>()) |
174 | 0 | TA->print(PP, OS, /*IncludeType*/ true); |
175 | 8 | else if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>()) |
176 | 0 | TAL->getArgument().print(PP, OS, /*IncludeType*/ true); |
177 | 8 | else if (const TemplateName *TN = get<TemplateName>()) |
178 | 0 | TN->print(OS, PP); |
179 | 8 | else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>()) |
180 | 0 | NNS->print(OS, PP); |
181 | 8 | else if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>()) { |
182 | 0 | if (const NestedNameSpecifier *NNS = NNSL->getNestedNameSpecifier()) |
183 | 0 | NNS->print(OS, PP); |
184 | 0 | else |
185 | 0 | OS << "(empty NestedNameSpecifierLoc)"; |
186 | 8 | } else if (const QualType *QT = get<QualType>()) |
187 | 6 | QT->print(OS, PP); |
188 | 2 | else if (const TypeLoc *TL = get<TypeLoc>()) |
189 | 0 | TL->getType().print(OS, PP); |
190 | 2 | else if (const Decl *D = get<Decl>()) |
191 | 1 | D->print(OS, PP); |
192 | 1 | else if (const Stmt *S = get<Stmt>()) |
193 | 1 | S->printPretty(OS, nullptr, PP); |
194 | 0 | else if (const Type *T = get<Type>()) |
195 | 0 | QualType(T, 0).print(OS, PP); |
196 | 0 | else if (const Attr *A = get<Attr>()) |
197 | 0 | A->printPretty(OS, PP); |
198 | 0 | else if (const ObjCProtocolLoc *P = get<ObjCProtocolLoc>()) |
199 | 0 | P->getProtocol()->print(OS, PP); |
200 | 0 | else |
201 | 0 | OS << "Unable to print values of type " << NodeKind.asStringRef() << "\n"; |
202 | 8 | } |
203 | | |
204 | | void DynTypedNode::dump(llvm::raw_ostream &OS, |
205 | 2 | const ASTContext &Context) const { |
206 | 2 | if (const Decl *D = get<Decl>()) |
207 | 1 | D->dump(OS); |
208 | 1 | else if (const Stmt *S = get<Stmt>()) |
209 | 1 | S->dump(OS, Context); |
210 | 0 | else if (const Type *T = get<Type>()) |
211 | 0 | T->dump(OS, Context); |
212 | 0 | else |
213 | 0 | OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n"; |
214 | 2 | } |
215 | | |
216 | 346 | SourceRange DynTypedNode::getSourceRange() const { |
217 | 346 | if (const CXXCtorInitializer *CCI = get<CXXCtorInitializer>()) |
218 | 0 | return CCI->getSourceRange(); |
219 | 346 | if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>()) |
220 | 1 | return NNSL->getSourceRange(); |
221 | 345 | if (const TypeLoc *TL = get<TypeLoc>()) |
222 | 5 | return TL->getSourceRange(); |
223 | 340 | if (const Decl *D = get<Decl>()) |
224 | 85 | return D->getSourceRange(); |
225 | 255 | if (const Stmt *S = get<Stmt>()) |
226 | 254 | return S->getSourceRange(); |
227 | 1 | if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>()) |
228 | 0 | return TAL->getSourceRange(); |
229 | 1 | if (const auto *C = get<OMPClause>()) |
230 | 0 | return SourceRange(C->getBeginLoc(), C->getEndLoc()); |
231 | 1 | if (const auto *CBS = get<CXXBaseSpecifier>()) |
232 | 0 | return CBS->getSourceRange(); |
233 | 1 | if (const auto *A = get<Attr>()) |
234 | 1 | return A->getRange(); |
235 | 0 | if (const ObjCProtocolLoc *P = get<ObjCProtocolLoc>()) |
236 | 0 | return P->getSourceRange(); |
237 | 0 | return SourceRange(); |
238 | 0 | } |