1 //===-- ASTStructExtractor.cpp --------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "ASTStructExtractor.h"
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"
26 using namespace clang
;
27 using namespace lldb_private
;
29 ASTStructExtractor::ASTStructExtractor(ASTConsumer
*passthrough
,
30 const char *struct_name
,
31 ClangFunctionCaller
&function
)
32 : m_ast_context(nullptr), m_passthrough(passthrough
),
33 m_passthrough_sema(nullptr), m_sema(nullptr), m_function(function
),
34 m_struct_name(struct_name
) {
38 m_passthrough_sema
= dyn_cast
<SemaConsumer
>(passthrough
);
41 ASTStructExtractor::~ASTStructExtractor() = default;
43 void ASTStructExtractor::Initialize(ASTContext
&Context
) {
44 m_ast_context
= &Context
;
47 m_passthrough
->Initialize(Context
);
50 void ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl
*F
) {
54 Stmt
*body_stmt
= F
->getBody();
55 CompoundStmt
*body_compound_stmt
= dyn_cast
<CompoundStmt
>(body_stmt
);
57 if (!body_compound_stmt
)
58 return; // do we have to handle this?
60 RecordDecl
*struct_decl
= nullptr;
62 StringRef
desired_name(m_struct_name
);
64 for (CompoundStmt::const_body_iterator bi
= body_compound_stmt
->body_begin(),
65 be
= body_compound_stmt
->body_end();
67 Stmt
*curr_stmt
= *bi
;
68 DeclStmt
*curr_decl_stmt
= dyn_cast
<DeclStmt
>(curr_stmt
);
71 DeclGroupRef decl_group
= curr_decl_stmt
->getDeclGroup();
72 for (Decl
*candidate_decl
: decl_group
) {
73 RecordDecl
*candidate_record_decl
= dyn_cast
<RecordDecl
>(candidate_decl
);
74 if (!candidate_record_decl
)
76 if (candidate_record_decl
->getName() == desired_name
) {
77 struct_decl
= candidate_record_decl
;
88 const ASTRecordLayout
*struct_layout(
89 &m_ast_context
->getASTRecordLayout(struct_decl
));
94 m_function
.m_struct_size
=
95 struct_layout
->getSize()
96 .getQuantity(); // TODO Store m_struct_size as CharUnits
97 m_function
.m_return_offset
=
98 struct_layout
->getFieldOffset(struct_layout
->getFieldCount() - 1) / 8;
99 m_function
.m_return_size
=
100 struct_layout
->getDataSize().getQuantity() - m_function
.m_return_offset
;
102 for (unsigned field_index
= 0, num_fields
= struct_layout
->getFieldCount();
103 field_index
< num_fields
; ++field_index
) {
104 m_function
.m_member_offsets
.push_back(
105 struct_layout
->getFieldOffset(field_index
) / 8);
108 m_function
.m_struct_valid
= true;
111 void ASTStructExtractor::ExtractFromTopLevelDecl(Decl
*D
) {
112 LinkageSpecDecl
*linkage_spec_decl
= dyn_cast
<LinkageSpecDecl
>(D
);
114 if (linkage_spec_decl
) {
115 RecordDecl::decl_iterator decl_iterator
;
117 for (decl_iterator
= linkage_spec_decl
->decls_begin();
118 decl_iterator
!= linkage_spec_decl
->decls_end(); ++decl_iterator
) {
119 ExtractFromTopLevelDecl(*decl_iterator
);
123 FunctionDecl
*function_decl
= dyn_cast
<FunctionDecl
>(D
);
125 if (m_ast_context
&& function_decl
&&
126 !m_function
.m_wrapper_function_name
.compare(
127 function_decl
->getNameAsString())) {
128 ExtractFromFunctionDecl(function_decl
);
132 bool ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D
) {
133 DeclGroupRef::iterator decl_iterator
;
135 for (decl_iterator
= D
.begin(); decl_iterator
!= D
.end(); ++decl_iterator
) {
136 Decl
*decl
= *decl_iterator
;
138 ExtractFromTopLevelDecl(decl
);
142 return m_passthrough
->HandleTopLevelDecl(D
);
146 void ASTStructExtractor::HandleTranslationUnit(ASTContext
&Ctx
) {
148 m_passthrough
->HandleTranslationUnit(Ctx
);
151 void ASTStructExtractor::HandleTagDeclDefinition(TagDecl
*D
) {
153 m_passthrough
->HandleTagDeclDefinition(D
);
156 void ASTStructExtractor::CompleteTentativeDefinition(VarDecl
*D
) {
158 m_passthrough
->CompleteTentativeDefinition(D
);
161 void ASTStructExtractor::HandleVTable(CXXRecordDecl
*RD
) {
163 m_passthrough
->HandleVTable(RD
);
166 void ASTStructExtractor::PrintStats() {
168 m_passthrough
->PrintStats();
171 void ASTStructExtractor::InitializeSema(Sema
&S
) {
174 if (m_passthrough_sema
)
175 m_passthrough_sema
->InitializeSema(S
);
178 void ASTStructExtractor::ForgetSema() {
181 if (m_passthrough_sema
)
182 m_passthrough_sema
->ForgetSema();