blob: b3922ee5ce449300abd59ac8625e4490e5c6b5da [file] [log] [blame]
Sean Callanan8c6934d2010-07-01 20:08:22 +00001//===-- ClangResultSynthesizer.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/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"
23#include "lldb/Expression/ClangResultSynthesizer.h"
24
25using namespace llvm;
26using namespace clang;
27using namespace lldb_private;
28
29ClangResultSynthesizer::ClangResultSynthesizer(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
42ClangResultSynthesizer::~ClangResultSynthesizer()
43{
44}
45
46void
47ClangResultSynthesizer::Initialize(ASTContext &Context)
48{
49 m_ast_context = &Context;
50
51 if (m_passthrough)
52 m_passthrough->Initialize(Context);
53}
54
55void
56ClangResultSynthesizer::TransformTopLevelDecl(Decl* D)
57{
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
84ClangResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D)
85{
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 Callananbfc33ce2010-08-16 23:01:35 +0000102ClangResultSynthesizer::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
116 Stmt *function_body = function_decl->getBody();
117 CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body);
118
119 if (!compound_stmt)
120 return false;
121
122 if (compound_stmt->body_empty())
123 return false;
124
125 Stmt **last_stmt_ptr = compound_stmt->body_end() - 1;
126 Stmt *last_stmt = *last_stmt_ptr;
127
128 Expr *last_expr = dyn_cast<Expr>(last_stmt);
129
130 if (!last_expr)
131 // No auxiliary variable necessary; expression returns void
132 return true;
133
134 QualType expr_qual_type = last_expr->getType();
135 clang::Type *expr_type = expr_qual_type.getTypePtr();
136
137 if (!expr_type)
138 return false;
139
140 if (expr_type->isVoidType())
141 return true;
142
143 if (log)
144 {
145 std::string s = expr_qual_type.getAsString();
146
147 log->Printf("Last statement's type: %s", s.c_str());
148 }
149
150 IdentifierInfo &result_id = Ctx.Idents.get("___clang_expr_result");
Sean Callanan45839272010-07-24 01:37:44 +0000151
Sean Callanan8c6934d2010-07-01 20:08:22 +0000152 clang::VarDecl *result_decl = VarDecl::Create(Ctx,
153 function_decl,
154 SourceLocation(),
155 &result_id,
156 expr_qual_type,
157 NULL,
158 VarDecl::Static,
159 VarDecl::Static);
160
161 if (!result_decl)
162 return false;
163
164 function_decl->addDecl(result_decl);
165
166 ///////////////////////////////
167 // call AddInitializerToDecl
168 //
169
170 Parser::DeclPtrTy result_decl_ptr;
171 result_decl_ptr.set(result_decl);
172
173 m_action->AddInitializerToDecl(result_decl_ptr, Parser::ExprArg(*m_action, last_expr));
174
175 /////////////////////////////////
176 // call ConvertDeclToDeclGroup
177 //
178
179 Parser::DeclGroupPtrTy result_decl_group_ptr;
180
181 result_decl_group_ptr = m_action->ConvertDeclToDeclGroup(result_decl_ptr);
182
183 ////////////////////////
184 // call ActOnDeclStmt
185 //
186
187 Parser::OwningStmtResult result_initialization_stmt_result(m_action->ActOnDeclStmt(result_decl_group_ptr,
188 SourceLocation(),
189 SourceLocation()));
190
Sean Callanan8c6934d2010-07-01 20:08:22 +0000191 ////////////////////////////////////////////////
192 // replace the old statement with the new one
193 //
194
Sean Callanan45839272010-07-24 01:37:44 +0000195 *last_stmt_ptr = reinterpret_cast<Stmt*>(result_initialization_stmt_result.take());
Sean Callanan8c6934d2010-07-01 20:08:22 +0000196
197 if (log)
198 {
199 std::string s;
200 raw_string_ostream os(s);
201
202 function_decl->print(os);
203
204 os.flush();
205
206 log->Printf("Transformed function AST:\n%s", s.c_str());
207 }
208
209 return true;
210}
211
212void
213ClangResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx)
214{
215 if (m_passthrough)
216 m_passthrough->HandleTranslationUnit(Ctx);
217}
218
219void
220ClangResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
221{
222 if (m_passthrough)
223 m_passthrough->HandleTagDeclDefinition(D);
224}
225
226void
227ClangResultSynthesizer::CompleteTentativeDefinition(VarDecl *D)
228{
229 if (m_passthrough)
230 m_passthrough->CompleteTentativeDefinition(D);
231}
232
233void
234ClangResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)
235{
236 if (m_passthrough)
237 m_passthrough->HandleVTable(RD, DefinitionRequired);
238}
239
240void
241ClangResultSynthesizer::PrintStats()
242{
243 if (m_passthrough)
244 m_passthrough->PrintStats();
245}
246
247void
248ClangResultSynthesizer::InitializeSema(Sema &S)
249{
250 m_sema = &S;
251 m_action = reinterpret_cast<Action*>(m_sema);
252
253 if (m_passthrough_sema)
254 m_passthrough_sema->InitializeSema(S);
255}
256
257void
258ClangResultSynthesizer::ForgetSema()
259{
260 m_sema = NULL;
261 m_action = NULL;
262
263 if (m_passthrough_sema)
264 m_passthrough_sema->ForgetSema();
265}