blob: 7bc31a5d815b32304b68ad062da131f17346a614 [file] [log] [blame]
Sean Callanan65dafa82010-08-27 01:01:44 +00001//===-- ASTStructExtractor.cpp ----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "stdlib.h"
11#include "clang/AST/ASTContext.h"
12#include "clang/AST/Decl.h"
13#include "clang/AST/DeclCXX.h"
14#include "clang/AST/DeclGroup.h"
15#include "clang/AST/Expr.h"
16#include "clang/AST/RecordLayout.h"
17#include "clang/AST/Stmt.h"
Sean Callanan65dafa82010-08-27 01:01:44 +000018#include "clang/Parse/Parser.h"
Sean Callanan47a5c4c2010-09-23 03:01:22 +000019#include "clang/Sema/Sema.h"
Sean Callanan65dafa82010-08-27 01:01:44 +000020#include "llvm/Support/Casting.h"
21#include "llvm/Support/raw_ostream.h"
22#include "lldb/Core/Log.h"
23#include "lldb/Expression/ASTStructExtractor.h"
24
25using namespace llvm;
26using namespace clang;
27using namespace lldb_private;
28
29ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough,
30 const char *struct_name,
31 ClangFunction &function) :
32 m_ast_context (NULL),
33 m_passthrough (passthrough),
34 m_passthrough_sema (NULL),
35 m_sema (NULL),
36 m_action (NULL),
Stephen Wilsondbeb3e12011-04-11 19:41:40 +000037 m_function (function),
38 m_struct_name (struct_name)
Sean Callanan65dafa82010-08-27 01:01:44 +000039{
40 if (!m_passthrough)
41 return;
42
43 m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
44}
45
46ASTStructExtractor::~ASTStructExtractor()
47{
48}
49
50void
51ASTStructExtractor::Initialize(ASTContext &Context)
52{
53 m_ast_context = &Context;
54
55 if (m_passthrough)
56 m_passthrough->Initialize(Context);
57}
58
59void
60ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F)
61{
62 DeclarationName struct_name(&m_ast_context->Idents.get(m_struct_name.c_str()));
63 RecordDecl::lookup_result struct_lookup = F->lookup(struct_name);
64
65 if (struct_lookup.first == struct_lookup.second)
66 return;
67
68 RecordDecl *struct_decl = dyn_cast<RecordDecl>(*(struct_lookup.first));
69
70 if (!struct_decl)
71 return;
72
73 const ASTRecordLayout* struct_layout(&m_ast_context->getASTRecordLayout (struct_decl));
74
75 if (!struct_layout)
76 return;
77
Sean Callanan279584c2011-03-15 00:17:19 +000078 m_function.m_struct_size = struct_layout->getSize().getQuantity(); // TODO Store m_struct_size as CharUnits
Sean Callanan65dafa82010-08-27 01:01:44 +000079 m_function.m_return_offset = struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8;
Sean Callanan279584c2011-03-15 00:17:19 +000080 m_function.m_return_size = struct_layout->getDataSize().getQuantity() - m_function.m_return_offset;
Sean Callanan65dafa82010-08-27 01:01:44 +000081
82 for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount();
83 field_index < num_fields;
84 ++field_index)
85 {
86 m_function.m_member_offsets.push_back(struct_layout->getFieldOffset(field_index) / 8);
87 }
88
89 m_function.m_struct_valid = true;
90}
91
92void
93ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D)
94{
95 LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D);
96
97 if (linkage_spec_decl)
98 {
99 RecordDecl::decl_iterator decl_iterator;
100
101 for (decl_iterator = linkage_spec_decl->decls_begin();
102 decl_iterator != linkage_spec_decl->decls_end();
103 ++decl_iterator)
104 {
105 ExtractFromTopLevelDecl(*decl_iterator);
106 }
107 }
108
109 FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D);
110
111 if (m_ast_context &&
112 function_decl &&
Sean Callanan47a5c4c2010-09-23 03:01:22 +0000113 !m_function.m_wrapper_function_name.compare(function_decl->getNameAsString().c_str()))
Sean Callanan65dafa82010-08-27 01:01:44 +0000114 {
115 ExtractFromFunctionDecl(function_decl);
116 }
117}
118
Sean Callananfecc09c2011-11-19 02:54:21 +0000119bool
Sean Callanan65dafa82010-08-27 01:01:44 +0000120ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D)
121{
122 DeclGroupRef::iterator decl_iterator;
123
124 for (decl_iterator = D.begin();
125 decl_iterator != D.end();
126 ++decl_iterator)
127 {
128 Decl *decl = *decl_iterator;
129
130 ExtractFromTopLevelDecl(decl);
131 }
132
133 if (m_passthrough)
Sean Callananfecc09c2011-11-19 02:54:21 +0000134 return m_passthrough->HandleTopLevelDecl(D);
135 return true;
Sean Callanan65dafa82010-08-27 01:01:44 +0000136}
137
138void
139ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx)
140{
141 if (m_passthrough)
142 m_passthrough->HandleTranslationUnit(Ctx);
143}
144
145void
146ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D)
147{
148 if (m_passthrough)
149 m_passthrough->HandleTagDeclDefinition(D);
150}
151
152void
153ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D)
154{
155 if (m_passthrough)
156 m_passthrough->CompleteTentativeDefinition(D);
157}
158
159void
160ASTStructExtractor::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)
161{
162 if (m_passthrough)
163 m_passthrough->HandleVTable(RD, DefinitionRequired);
164}
165
166void
167ASTStructExtractor::PrintStats()
168{
169 if (m_passthrough)
170 m_passthrough->PrintStats();
171}
172
173void
174ASTStructExtractor::InitializeSema(Sema &S)
175{
176 m_sema = &S;
177 m_action = reinterpret_cast<Action*>(m_sema);
178
179 if (m_passthrough_sema)
180 m_passthrough_sema->InitializeSema(S);
181}
182
183void
184ASTStructExtractor::ForgetSema()
185{
186 m_sema = NULL;
187 m_action = NULL;
188
189 if (m_passthrough_sema)
190 m_passthrough_sema->ForgetSema();
191}