blob: 8838fddf8ff1a935d4c95aec384310879026de94 [file] [log] [blame]
Sean Callanan65dafa82010-08-27 01:01:44 +00001//===-- ASTResultSynthesizer.cpp --------------------------------*- C++ -*-===//
Sean Callanan8c6934d2010-07-01 20:08:22 +00002//
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/Stmt.h"
17#include "clang/Parse/Action.h"
18#include "clang/Parse/Parser.h"
19#include "clang/Parse/Scope.h"
20#include "llvm/Support/Casting.h"
21#include "llvm/Support/raw_ostream.h"
22#include "lldb/Core/Log.h"
Sean Callanan65dafa82010-08-27 01:01:44 +000023#include "lldb/Expression/ASTResultSynthesizer.h"
Sean Callanan8c6934d2010-07-01 20:08:22 +000024
25using namespace llvm;
26using namespace clang;
27using namespace lldb_private;
28
Sean Callanan65dafa82010-08-27 01:01:44 +000029ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough) :
Greg Clayton980d0672010-07-12 23:14:00 +000030 m_ast_context (NULL),
31 m_passthrough (passthrough),
32 m_passthrough_sema (NULL),
33 m_sema (NULL),
34 m_action (NULL)
Sean Callanan8c6934d2010-07-01 20:08:22 +000035{
36 if (!m_passthrough)
37 return;
38
39 m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
40}
41
Sean Callanan65dafa82010-08-27 01:01:44 +000042ASTResultSynthesizer::~ASTResultSynthesizer()
Sean Callanan8c6934d2010-07-01 20:08:22 +000043{
44}
45
46void
Sean Callanan65dafa82010-08-27 01:01:44 +000047ASTResultSynthesizer::Initialize(ASTContext &Context)
Sean Callanan8c6934d2010-07-01 20:08:22 +000048{
49 m_ast_context = &Context;
50
51 if (m_passthrough)
52 m_passthrough->Initialize(Context);
53}
54
55void
Sean Callanan65dafa82010-08-27 01:01:44 +000056ASTResultSynthesizer::TransformTopLevelDecl(Decl* D)
Sean Callanan8c6934d2010-07-01 20:08:22 +000057{
58 LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D);
59
60 if (linkage_spec_decl)
61 {
62 RecordDecl::decl_iterator decl_iterator;
63
64 for (decl_iterator = linkage_spec_decl->decls_begin();
65 decl_iterator != linkage_spec_decl->decls_end();
66 ++decl_iterator)
67 {
68 TransformTopLevelDecl(*decl_iterator);
69 }
70 }
71
72 FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D);
73
74 if (m_ast_context &&
75 function_decl &&
76 !strcmp(function_decl->getNameAsCString(),
77 "___clang_expr"))
78 {
Sean Callananbfc33ce2010-08-16 23:01:35 +000079 SynthesizeResult(function_decl);
Sean Callanan8c6934d2010-07-01 20:08:22 +000080 }
81}
82
83void
Sean Callanan65dafa82010-08-27 01:01:44 +000084ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D)
Sean Callanan8c6934d2010-07-01 20:08:22 +000085{
86 DeclGroupRef::iterator decl_iterator;
87
88 for (decl_iterator = D.begin();
89 decl_iterator != D.end();
90 ++decl_iterator)
91 {
92 Decl *decl = *decl_iterator;
93
94 TransformTopLevelDecl(decl);
95 }
96
97 if (m_passthrough)
98 m_passthrough->HandleTopLevelDecl(D);
99}
100
101bool
Sean Callanan65dafa82010-08-27 01:01:44 +0000102ASTResultSynthesizer::SynthesizeResult (FunctionDecl *FunDecl)
Sean Callanan8c6934d2010-07-01 20:08:22 +0000103{
Sean Callananbfc33ce2010-08-16 23:01:35 +0000104 ASTContext &Ctx(*m_ast_context);
105
Sean Callanan8c6934d2010-07-01 20:08:22 +0000106 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
107
108 if (!m_sema)
109 return false;
110
111 FunctionDecl *function_decl = FunDecl;
112
113 if (!function_decl)
114 return false;
115
Sean Callanane8a59a82010-09-13 21:34:21 +0000116 if (log)
117 {
118 std::string s;
119 raw_string_ostream os(s);
120
121 function_decl->print(os);
122
123 os.flush();
124
125 log->Printf("Function AST before transforming:\n%s", s.c_str());
126 }
127
Sean Callanan8c6934d2010-07-01 20:08:22 +0000128 Stmt *function_body = function_decl->getBody();
129 CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body);
130
131 if (!compound_stmt)
132 return false;
133
134 if (compound_stmt->body_empty())
135 return false;
136
137 Stmt **last_stmt_ptr = compound_stmt->body_end() - 1;
138 Stmt *last_stmt = *last_stmt_ptr;
139
Sean Callanane8a59a82010-09-13 21:34:21 +0000140 while (dyn_cast<NullStmt>(last_stmt))
141 {
142 if (last_stmt_ptr != compound_stmt->body_begin())
143 {
144 last_stmt_ptr--;
145 last_stmt = *last_stmt_ptr;
146 }
147 }
148
Sean Callanan8c6934d2010-07-01 20:08:22 +0000149 Expr *last_expr = dyn_cast<Expr>(last_stmt);
150
151 if (!last_expr)
152 // No auxiliary variable necessary; expression returns void
153 return true;
154
155 QualType expr_qual_type = last_expr->getType();
156 clang::Type *expr_type = expr_qual_type.getTypePtr();
157
158 if (!expr_type)
159 return false;
160
161 if (expr_type->isVoidType())
162 return true;
163
164 if (log)
165 {
166 std::string s = expr_qual_type.getAsString();
167
168 log->Printf("Last statement's type: %s", s.c_str());
169 }
170
171 IdentifierInfo &result_id = Ctx.Idents.get("___clang_expr_result");
Sean Callanan45839272010-07-24 01:37:44 +0000172
Sean Callanan8c6934d2010-07-01 20:08:22 +0000173 clang::VarDecl *result_decl = VarDecl::Create(Ctx,
174 function_decl,
175 SourceLocation(),
176 &result_id,
177 expr_qual_type,
178 NULL,
179 VarDecl::Static,
180 VarDecl::Static);
181
182 if (!result_decl)
183 return false;
184
185 function_decl->addDecl(result_decl);
186
187 ///////////////////////////////
188 // call AddInitializerToDecl
189 //
190
191 Parser::DeclPtrTy result_decl_ptr;
192 result_decl_ptr.set(result_decl);
193
194 m_action->AddInitializerToDecl(result_decl_ptr, Parser::ExprArg(*m_action, last_expr));
195
196 /////////////////////////////////
197 // call ConvertDeclToDeclGroup
198 //
199
200 Parser::DeclGroupPtrTy result_decl_group_ptr;
201
202 result_decl_group_ptr = m_action->ConvertDeclToDeclGroup(result_decl_ptr);
203
204 ////////////////////////
205 // call ActOnDeclStmt
206 //
207
208 Parser::OwningStmtResult result_initialization_stmt_result(m_action->ActOnDeclStmt(result_decl_group_ptr,
209 SourceLocation(),
210 SourceLocation()));
211
Sean Callanan8c6934d2010-07-01 20:08:22 +0000212 ////////////////////////////////////////////////
213 // replace the old statement with the new one
214 //
215
Sean Callanan45839272010-07-24 01:37:44 +0000216 *last_stmt_ptr = reinterpret_cast<Stmt*>(result_initialization_stmt_result.take());
Sean Callanan8c6934d2010-07-01 20:08:22 +0000217
218 if (log)
219 {
220 std::string s;
221 raw_string_ostream os(s);
222
223 function_decl->print(os);
224
225 os.flush();
226
227 log->Printf("Transformed function AST:\n%s", s.c_str());
228 }
229
230 return true;
231}
232
233void
Sean Callanan65dafa82010-08-27 01:01:44 +0000234ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx)
Sean Callanan8c6934d2010-07-01 20:08:22 +0000235{
236 if (m_passthrough)
237 m_passthrough->HandleTranslationUnit(Ctx);
238}
239
240void
Sean Callanan65dafa82010-08-27 01:01:44 +0000241ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
Sean Callanan8c6934d2010-07-01 20:08:22 +0000242{
243 if (m_passthrough)
244 m_passthrough->HandleTagDeclDefinition(D);
245}
246
247void
Sean Callanan65dafa82010-08-27 01:01:44 +0000248ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D)
Sean Callanan8c6934d2010-07-01 20:08:22 +0000249{
250 if (m_passthrough)
251 m_passthrough->CompleteTentativeDefinition(D);
252}
253
254void
Sean Callanan65dafa82010-08-27 01:01:44 +0000255ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)
Sean Callanan8c6934d2010-07-01 20:08:22 +0000256{
257 if (m_passthrough)
258 m_passthrough->HandleVTable(RD, DefinitionRequired);
259}
260
261void
Sean Callanan65dafa82010-08-27 01:01:44 +0000262ASTResultSynthesizer::PrintStats()
Sean Callanan8c6934d2010-07-01 20:08:22 +0000263{
264 if (m_passthrough)
265 m_passthrough->PrintStats();
266}
267
268void
Sean Callanan65dafa82010-08-27 01:01:44 +0000269ASTResultSynthesizer::InitializeSema(Sema &S)
Sean Callanan8c6934d2010-07-01 20:08:22 +0000270{
271 m_sema = &S;
272 m_action = reinterpret_cast<Action*>(m_sema);
273
274 if (m_passthrough_sema)
275 m_passthrough_sema->InitializeSema(S);
276}
277
278void
Sean Callanan65dafa82010-08-27 01:01:44 +0000279ASTResultSynthesizer::ForgetSema()
Sean Callanan8c6934d2010-07-01 20:08:22 +0000280{
281 m_sema = NULL;
282 m_action = NULL;
283
284 if (m_passthrough_sema)
285 m_passthrough_sema->ForgetSema();
286}