blob: efad38304addedabb3271d11151cc1f68ce32733 [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
119void
120ASTStructExtractor::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)
134 m_passthrough->HandleTopLevelDecl(D);
135}
136
137void
138ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx)
139{
140 if (m_passthrough)
141 m_passthrough->HandleTranslationUnit(Ctx);
142}
143
144void
145ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D)
146{
147 if (m_passthrough)
148 m_passthrough->HandleTagDeclDefinition(D);
149}
150
151void
152ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D)
153{
154 if (m_passthrough)
155 m_passthrough->CompleteTentativeDefinition(D);
156}
157
158void
159ASTStructExtractor::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)
160{
161 if (m_passthrough)
162 m_passthrough->HandleVTable(RD, DefinitionRequired);
163}
164
165void
166ASTStructExtractor::PrintStats()
167{
168 if (m_passthrough)
169 m_passthrough->PrintStats();
170}
171
172void
173ASTStructExtractor::InitializeSema(Sema &S)
174{
175 m_sema = &S;
176 m_action = reinterpret_cast<Action*>(m_sema);
177
178 if (m_passthrough_sema)
179 m_passthrough_sema->InitializeSema(S);
180}
181
182void
183ASTStructExtractor::ForgetSema()
184{
185 m_sema = NULL;
186 m_action = NULL;
187
188 if (m_passthrough_sema)
189 m_passthrough_sema->ForgetSema();
190}