/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- ASTStructExtractor.cpp --------------------------------------------===// |
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 | | #include "ASTStructExtractor.h" |
10 | | |
11 | | #include "lldb/Utility/Log.h" |
12 | | #include "clang/AST/ASTContext.h" |
13 | | #include "clang/AST/Decl.h" |
14 | | #include "clang/AST/DeclCXX.h" |
15 | | #include "clang/AST/DeclGroup.h" |
16 | | #include "clang/AST/Expr.h" |
17 | | #include "clang/AST/RecordLayout.h" |
18 | | #include "clang/AST/Stmt.h" |
19 | | #include "clang/Parse/Parser.h" |
20 | | #include "clang/Sema/Sema.h" |
21 | | #include "llvm/Support/Casting.h" |
22 | | #include "llvm/Support/raw_ostream.h" |
23 | | #include <cstdlib> |
24 | | |
25 | | using namespace llvm; |
26 | | using namespace clang; |
27 | | using namespace lldb_private; |
28 | | |
29 | | ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough, |
30 | | const char *struct_name, |
31 | | ClangFunctionCaller &function) |
32 | 2.00k | : m_ast_context(nullptr), m_passthrough(passthrough), |
33 | 2.00k | m_passthrough_sema(nullptr), m_sema(nullptr), m_function(function), |
34 | 2.00k | m_struct_name(struct_name) { |
35 | 2.00k | if (!m_passthrough) |
36 | 0 | return; |
37 | | |
38 | 2.00k | m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); |
39 | 2.00k | } |
40 | | |
41 | 1.97k | ASTStructExtractor::~ASTStructExtractor() = default; |
42 | | |
43 | 2.00k | void ASTStructExtractor::Initialize(ASTContext &Context) { |
44 | 2.00k | m_ast_context = &Context; |
45 | | |
46 | 2.00k | if (m_passthrough) |
47 | 2.00k | m_passthrough->Initialize(Context); |
48 | 2.00k | } |
49 | | |
50 | 2.00k | void ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F) { |
51 | 2.00k | if (!F->hasBody()) |
52 | 0 | return; |
53 | | |
54 | 2.00k | Stmt *body_stmt = F->getBody(); |
55 | 2.00k | CompoundStmt *body_compound_stmt = dyn_cast<CompoundStmt>(body_stmt); |
56 | | |
57 | 2.00k | if (!body_compound_stmt) |
58 | 0 | return; // do we have to handle this? |
59 | | |
60 | 2.00k | RecordDecl *struct_decl = nullptr; |
61 | | |
62 | 2.00k | StringRef desired_name(m_struct_name); |
63 | | |
64 | 2.00k | for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(), |
65 | 2.00k | be = body_compound_stmt->body_end(); |
66 | 2.00k | bi != be; ++bi0 ) { |
67 | 2.00k | Stmt *curr_stmt = *bi; |
68 | 2.00k | DeclStmt *curr_decl_stmt = dyn_cast<DeclStmt>(curr_stmt); |
69 | 2.00k | if (!curr_decl_stmt) |
70 | 0 | continue; |
71 | 2.00k | DeclGroupRef decl_group = curr_decl_stmt->getDeclGroup(); |
72 | 2.00k | for (Decl *candidate_decl : decl_group) { |
73 | 2.00k | RecordDecl *candidate_record_decl = dyn_cast<RecordDecl>(candidate_decl); |
74 | 2.00k | if (!candidate_record_decl) |
75 | 0 | continue; |
76 | 2.00k | if (candidate_record_decl->getName() == desired_name) { |
77 | 2.00k | struct_decl = candidate_record_decl; |
78 | 2.00k | break; |
79 | 2.00k | } |
80 | 2.00k | } |
81 | 2.00k | if (struct_decl) |
82 | 2.00k | break; |
83 | 2.00k | } |
84 | | |
85 | 2.00k | if (!struct_decl) |
86 | 0 | return; |
87 | | |
88 | 2.00k | const ASTRecordLayout *struct_layout( |
89 | 2.00k | &m_ast_context->getASTRecordLayout(struct_decl)); |
90 | | |
91 | 2.00k | if (!struct_layout) |
92 | 0 | return; |
93 | | |
94 | 2.00k | m_function.m_struct_size = |
95 | 2.00k | struct_layout->getSize() |
96 | 2.00k | .getQuantity(); // TODO Store m_struct_size as CharUnits |
97 | 2.00k | m_function.m_return_offset = |
98 | 2.00k | struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8; |
99 | 2.00k | m_function.m_return_size = |
100 | 2.00k | struct_layout->getDataSize().getQuantity() - m_function.m_return_offset; |
101 | | |
102 | 2.00k | for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount(); |
103 | 15.7k | field_index < num_fields; ++field_index13.6k ) { |
104 | 13.6k | m_function.m_member_offsets.push_back( |
105 | 13.6k | struct_layout->getFieldOffset(field_index) / 8); |
106 | 13.6k | } |
107 | | |
108 | 2.00k | m_function.m_struct_valid = true; |
109 | 2.00k | } |
110 | | |
111 | 4.01k | void ASTStructExtractor::ExtractFromTopLevelDecl(Decl *D) { |
112 | 4.01k | LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D); |
113 | | |
114 | 4.01k | if (linkage_spec_decl) { |
115 | 2.00k | RecordDecl::decl_iterator decl_iterator; |
116 | | |
117 | 2.00k | for (decl_iterator = linkage_spec_decl->decls_begin(); |
118 | 4.01k | decl_iterator != linkage_spec_decl->decls_end(); ++decl_iterator2.00k ) { |
119 | 2.00k | ExtractFromTopLevelDecl(*decl_iterator); |
120 | 2.00k | } |
121 | 2.00k | } |
122 | | |
123 | 4.01k | FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D); |
124 | | |
125 | 4.01k | if (m_ast_context && function_decl && |
126 | 4.01k | !m_function.m_wrapper_function_name.compare( |
127 | 2.00k | function_decl->getNameAsString())) { |
128 | 2.00k | ExtractFromFunctionDecl(function_decl); |
129 | 2.00k | } |
130 | 4.01k | } |
131 | | |
132 | 2.00k | bool ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D) { |
133 | 2.00k | DeclGroupRef::iterator decl_iterator; |
134 | | |
135 | 4.01k | for (decl_iterator = D.begin(); decl_iterator != D.end(); ++decl_iterator2.00k ) { |
136 | 2.00k | Decl *decl = *decl_iterator; |
137 | | |
138 | 2.00k | ExtractFromTopLevelDecl(decl); |
139 | 2.00k | } |
140 | | |
141 | 2.00k | if (m_passthrough) |
142 | 2.00k | return m_passthrough->HandleTopLevelDecl(D); |
143 | 0 | return true; |
144 | 2.00k | } |
145 | | |
146 | 2.00k | void ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) { |
147 | 2.00k | if (m_passthrough) |
148 | 2.00k | m_passthrough->HandleTranslationUnit(Ctx); |
149 | 2.00k | } |
150 | | |
151 | 2.00k | void ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) { |
152 | 2.00k | if (m_passthrough) |
153 | 2.00k | m_passthrough->HandleTagDeclDefinition(D); |
154 | 2.00k | } |
155 | | |
156 | 0 | void ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) { |
157 | 0 | if (m_passthrough) |
158 | 0 | m_passthrough->CompleteTentativeDefinition(D); |
159 | 0 | } |
160 | | |
161 | 0 | void ASTStructExtractor::HandleVTable(CXXRecordDecl *RD) { |
162 | 0 | if (m_passthrough) |
163 | 0 | m_passthrough->HandleVTable(RD); |
164 | 0 | } |
165 | | |
166 | 0 | void ASTStructExtractor::PrintStats() { |
167 | 0 | if (m_passthrough) |
168 | 0 | m_passthrough->PrintStats(); |
169 | 0 | } |
170 | | |
171 | 2.00k | void ASTStructExtractor::InitializeSema(Sema &S) { |
172 | 2.00k | m_sema = &S; |
173 | | |
174 | 2.00k | if (m_passthrough_sema) |
175 | 0 | m_passthrough_sema->InitializeSema(S); |
176 | 2.00k | } |
177 | | |
178 | 2.00k | void ASTStructExtractor::ForgetSema() { |
179 | 2.00k | m_sema = nullptr; |
180 | | |
181 | 2.00k | if (m_passthrough_sema) |
182 | 0 | m_passthrough_sema->ForgetSema(); |
183 | 2.00k | } |