blob: 6fc78863040b0de4bc9da41d70b897c6544bbb4d [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 {
79 SynthesizeResult(*m_ast_context, function_decl);
80 }
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
102ClangResultSynthesizer::SynthesizeResult (ASTContext &Ctx,
103 FunctionDecl *FunDecl)
104{
105 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
106
107 if (!m_sema)
108 return false;
109
110 FunctionDecl *function_decl = FunDecl;
111
112 if (!function_decl)
113 return false;
114
115 Stmt *function_body = function_decl->getBody();
116 CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body);
117
118 if (!compound_stmt)
119 return false;
120
121 if (compound_stmt->body_empty())
122 return false;
123
124 Stmt **last_stmt_ptr = compound_stmt->body_end() - 1;
125 Stmt *last_stmt = *last_stmt_ptr;
126
127 Expr *last_expr = dyn_cast<Expr>(last_stmt);
128
129 if (!last_expr)
130 // No auxiliary variable necessary; expression returns void
131 return true;
132
133 QualType expr_qual_type = last_expr->getType();
134 clang::Type *expr_type = expr_qual_type.getTypePtr();
135
136 if (!expr_type)
137 return false;
138
139 if (expr_type->isVoidType())
140 return true;
141
142 if (log)
143 {
144 std::string s = expr_qual_type.getAsString();
145
146 log->Printf("Last statement's type: %s", s.c_str());
147 }
148
149 IdentifierInfo &result_id = Ctx.Idents.get("___clang_expr_result");
Sean Callanan45839272010-07-24 01:37:44 +0000150
Sean Callanan8c6934d2010-07-01 20:08:22 +0000151 clang::VarDecl *result_decl = VarDecl::Create(Ctx,
152 function_decl,
153 SourceLocation(),
154 &result_id,
155 expr_qual_type,
156 NULL,
157 VarDecl::Static,
158 VarDecl::Static);
159
160 if (!result_decl)
161 return false;
162
163 function_decl->addDecl(result_decl);
164
165 ///////////////////////////////
166 // call AddInitializerToDecl
167 //
168
169 Parser::DeclPtrTy result_decl_ptr;
170 result_decl_ptr.set(result_decl);
171
172 m_action->AddInitializerToDecl(result_decl_ptr, Parser::ExprArg(*m_action, last_expr));
173
174 /////////////////////////////////
175 // call ConvertDeclToDeclGroup
176 //
177
178 Parser::DeclGroupPtrTy result_decl_group_ptr;
179
180 result_decl_group_ptr = m_action->ConvertDeclToDeclGroup(result_decl_ptr);
181
182 ////////////////////////
183 // call ActOnDeclStmt
184 //
185
186 Parser::OwningStmtResult result_initialization_stmt_result(m_action->ActOnDeclStmt(result_decl_group_ptr,
187 SourceLocation(),
188 SourceLocation()));
189
Sean Callanan8c6934d2010-07-01 20:08:22 +0000190 ////////////////////////////////////////////////
191 // replace the old statement with the new one
192 //
193
Sean Callanan45839272010-07-24 01:37:44 +0000194 *last_stmt_ptr = reinterpret_cast<Stmt*>(result_initialization_stmt_result.take());
Sean Callanan8c6934d2010-07-01 20:08:22 +0000195
196 if (log)
197 {
198 std::string s;
199 raw_string_ostream os(s);
200
201 function_decl->print(os);
202
203 os.flush();
204
205 log->Printf("Transformed function AST:\n%s", s.c_str());
206 }
207
208 return true;
209}
210
211void
212ClangResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx)
213{
214 if (m_passthrough)
215 m_passthrough->HandleTranslationUnit(Ctx);
216}
217
218void
219ClangResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
220{
221 if (m_passthrough)
222 m_passthrough->HandleTagDeclDefinition(D);
223}
224
225void
226ClangResultSynthesizer::CompleteTentativeDefinition(VarDecl *D)
227{
228 if (m_passthrough)
229 m_passthrough->CompleteTentativeDefinition(D);
230}
231
232void
233ClangResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)
234{
235 if (m_passthrough)
236 m_passthrough->HandleVTable(RD, DefinitionRequired);
237}
238
239void
240ClangResultSynthesizer::PrintStats()
241{
242 if (m_passthrough)
243 m_passthrough->PrintStats();
244}
245
246void
247ClangResultSynthesizer::InitializeSema(Sema &S)
248{
249 m_sema = &S;
250 m_action = reinterpret_cast<Action*>(m_sema);
251
252 if (m_passthrough_sema)
253 m_passthrough_sema->InitializeSema(S);
254}
255
256void
257ClangResultSynthesizer::ForgetSema()
258{
259 m_sema = NULL;
260 m_action = NULL;
261
262 if (m_passthrough_sema)
263 m_passthrough_sema->ForgetSema();
264}