1 //===-- ASTResultSynthesizer.cpp ------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "ASTResultSynthesizer.h"
11 #include "ClangASTImporter.h"
12 #include "ClangPersistentVariables.h"
14 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
15 #include "lldb/Target/Target.h"
16 #include "lldb/Utility/LLDBAssert.h"
17 #include "lldb/Utility/LLDBLog.h"
18 #include "lldb/Utility/Log.h"
19 #include "clang/AST/ASTContext.h"
20 #include "clang/AST/Decl.h"
21 #include "clang/AST/DeclCXX.h"
22 #include "clang/AST/DeclGroup.h"
23 #include "clang/AST/DeclObjC.h"
24 #include "clang/AST/Expr.h"
25 #include "clang/AST/Stmt.h"
26 #include "clang/Parse/Parser.h"
27 #include "clang/Sema/SemaDiagnostic.h"
28 #include "llvm/Support/Casting.h"
29 #include "llvm/Support/raw_ostream.h"
33 using namespace clang
;
34 using namespace lldb_private
;
36 ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer
*passthrough
,
37 bool top_level
, Target
&target
)
38 : m_ast_context(nullptr), m_passthrough(passthrough
),
39 m_passthrough_sema(nullptr), m_target(target
), m_sema(nullptr),
40 m_top_level(top_level
) {
44 m_passthrough_sema
= dyn_cast
<SemaConsumer
>(passthrough
);
47 ASTResultSynthesizer::~ASTResultSynthesizer() = default;
49 void ASTResultSynthesizer::Initialize(ASTContext
&Context
) {
50 m_ast_context
= &Context
;
53 m_passthrough
->Initialize(Context
);
56 void ASTResultSynthesizer::TransformTopLevelDecl(Decl
*D
) {
57 Log
*log
= GetLog(LLDBLog::Expressions
);
59 if (NamedDecl
*named_decl
= dyn_cast
<NamedDecl
>(D
)) {
60 if (log
&& log
->GetVerbose()) {
61 if (named_decl
->getIdentifier())
62 LLDB_LOGF(log
, "TransformTopLevelDecl(%s)",
63 named_decl
->getIdentifier()->getNameStart());
64 else if (ObjCMethodDecl
*method_decl
= dyn_cast
<ObjCMethodDecl
>(D
))
65 LLDB_LOGF(log
, "TransformTopLevelDecl(%s)",
66 method_decl
->getSelector().getAsString().c_str());
68 LLDB_LOGF(log
, "TransformTopLevelDecl(<complex>)");
72 RecordPersistentDecl(named_decl
);
76 if (LinkageSpecDecl
*linkage_spec_decl
= dyn_cast
<LinkageSpecDecl
>(D
)) {
77 RecordDecl::decl_iterator decl_iterator
;
79 for (decl_iterator
= linkage_spec_decl
->decls_begin();
80 decl_iterator
!= linkage_spec_decl
->decls_end(); ++decl_iterator
) {
81 TransformTopLevelDecl(*decl_iterator
);
83 } else if (!m_top_level
) {
84 if (ObjCMethodDecl
*method_decl
= dyn_cast
<ObjCMethodDecl
>(D
)) {
86 !method_decl
->getSelector().getAsString().compare("$__lldb_expr:")) {
87 RecordPersistentTypes(method_decl
);
88 SynthesizeObjCMethodResult(method_decl
);
90 } else if (FunctionDecl
*function_decl
= dyn_cast
<FunctionDecl
>(D
)) {
91 // When completing user input the body of the function may be a nullptr.
92 if (m_ast_context
&& function_decl
->hasBody() &&
93 !function_decl
->getNameInfo().getAsString().compare("$__lldb_expr")) {
94 RecordPersistentTypes(function_decl
);
95 SynthesizeFunctionResult(function_decl
);
101 bool ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D
) {
102 DeclGroupRef::iterator decl_iterator
;
104 for (decl_iterator
= D
.begin(); decl_iterator
!= D
.end(); ++decl_iterator
) {
105 Decl
*decl
= *decl_iterator
;
107 TransformTopLevelDecl(decl
);
111 return m_passthrough
->HandleTopLevelDecl(D
);
115 bool ASTResultSynthesizer::SynthesizeFunctionResult(FunctionDecl
*FunDecl
) {
116 Log
*log
= GetLog(LLDBLog::Expressions
);
121 FunctionDecl
*function_decl
= FunDecl
;
126 if (log
&& log
->GetVerbose()) {
128 raw_string_ostream
os(s
);
130 function_decl
->print(os
);
132 LLDB_LOGF(log
, "Untransformed function AST:\n%s", s
.c_str());
135 Stmt
*function_body
= function_decl
->getBody();
136 CompoundStmt
*compound_stmt
= dyn_cast
<CompoundStmt
>(function_body
);
138 bool ret
= SynthesizeBodyResult(compound_stmt
, function_decl
);
140 if (log
&& log
->GetVerbose()) {
142 raw_string_ostream
os(s
);
144 function_decl
->print(os
);
146 LLDB_LOGF(log
, "Transformed function AST:\n%s", s
.c_str());
152 bool ASTResultSynthesizer::SynthesizeObjCMethodResult(
153 ObjCMethodDecl
*MethodDecl
) {
154 Log
*log
= GetLog(LLDBLog::Expressions
);
162 if (log
&& log
->GetVerbose()) {
164 raw_string_ostream
os(s
);
166 MethodDecl
->print(os
);
168 LLDB_LOGF(log
, "Untransformed method AST:\n%s", s
.c_str());
171 Stmt
*method_body
= MethodDecl
->getBody();
176 CompoundStmt
*compound_stmt
= dyn_cast
<CompoundStmt
>(method_body
);
178 bool ret
= SynthesizeBodyResult(compound_stmt
, MethodDecl
);
180 if (log
&& log
->GetVerbose()) {
182 raw_string_ostream
os(s
);
184 MethodDecl
->print(os
);
186 LLDB_LOGF(log
, "Transformed method AST:\n%s", s
.c_str());
192 /// Returns true if LLDB can take the address of the given lvalue for the sake
193 /// of capturing the expression result. Returns false if LLDB should instead
194 /// store the expression result in a result variable.
195 static bool CanTakeAddressOfLValue(const Expr
*lvalue_expr
) {
196 assert(lvalue_expr
->getValueKind() == VK_LValue
&&
197 "lvalue_expr not a lvalue");
199 QualType qt
= lvalue_expr
->getType();
200 // If the lvalue has const-qualified non-volatile integral or enum type, then
201 // the underlying value might come from a const static data member as
202 // described in C++11 [class.static.data]p3. If that's the case, then the
203 // value might not have an address if the user didn't also define the member
204 // in a namespace scope. Taking the address would cause that LLDB later fails
205 // to link the expression, so those lvalues should be stored in a result
207 if (qt
->isIntegralOrEnumerationType() && qt
.isConstQualified() &&
208 !qt
.isVolatileQualified())
213 bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt
*Body
,
215 Log
*log
= GetLog(LLDBLog::Expressions
);
217 ASTContext
&Ctx(*m_ast_context
);
222 if (Body
->body_empty())
225 Stmt
**last_stmt_ptr
= Body
->body_end() - 1;
226 Stmt
*last_stmt
= *last_stmt_ptr
;
228 while (isa
<NullStmt
>(last_stmt
)) {
229 if (last_stmt_ptr
!= Body
->body_begin()) {
231 last_stmt
= *last_stmt_ptr
;
237 Expr
*last_expr
= dyn_cast
<Expr
>(last_stmt
);
240 // No auxiliary variable necessary; expression returns void
243 // In C++11, last_expr can be a LValueToRvalue implicit cast. Strip that off
244 // if that's the case.
247 ImplicitCastExpr
*implicit_cast
= dyn_cast
<ImplicitCastExpr
>(last_expr
);
252 if (implicit_cast
->getCastKind() != CK_LValueToRValue
)
255 last_expr
= implicit_cast
->getSubExpr();
258 // is_lvalue is used to record whether the expression returns an assignable
259 // Lvalue or an Rvalue. This is relevant because they are handled
264 // - In AST result synthesis (here!) the expression E is transformed into an
265 // initialization T *$__lldb_expr_result_ptr = &E.
267 // - In structure allocation, a pointer-sized slot is allocated in the
268 // struct that is to be passed into the expression.
270 // - In IR transformations, reads and writes to $__lldb_expr_result_ptr are
271 // redirected at an entry in the struct ($__lldb_arg) passed into the
272 // expression. (Other persistent variables are treated similarly, having
273 // been materialized as references, but in those cases the value of the
274 // reference itself is never modified.)
276 // - During materialization, $0 (the result persistent variable) is ignored.
278 // - During dematerialization, $0 is marked up as a load address with value
279 // equal to the contents of the structure entry.
281 // - Note: if we cannot take an address of the resulting Lvalue (e.g. it's
282 // a static const member without an out-of-class definition), then we
283 // follow the Rvalue route.
287 // - In AST result synthesis the expression E is transformed into an
288 // initialization static T $__lldb_expr_result = E.
290 // - In structure allocation, a pointer-sized slot is allocated in the
291 // struct that is to be passed into the expression.
293 // - In IR transformations, an instruction is inserted at the beginning of
294 // the function to dereference the pointer resident in the slot. Reads and
295 // writes to $__lldb_expr_result are redirected at that dereferenced
296 // version. Guard variables for the static variable are excised.
298 // - During materialization, $0 (the result persistent variable) is
299 // populated with the location of a newly-allocated area of memory.
301 // - During dematerialization, $0 is ignored.
303 bool is_lvalue
= last_expr
->getValueKind() == VK_LValue
&&
304 last_expr
->getObjectKind() == OK_Ordinary
;
306 QualType expr_qual_type
= last_expr
->getType();
307 const clang::Type
*expr_type
= expr_qual_type
.getTypePtr();
312 if (expr_type
->isVoidType())
316 std::string s
= expr_qual_type
.getAsString();
318 LLDB_LOGF(log
, "Last statement is an %s with type: %s",
319 (is_lvalue
? "lvalue" : "rvalue"), s
.c_str());
322 clang::VarDecl
*result_decl
= nullptr;
324 if (is_lvalue
&& CanTakeAddressOfLValue(last_expr
)) {
325 IdentifierInfo
*result_ptr_id
;
327 if (expr_type
->isFunctionType())
329 &Ctx
.Idents
.get("$__lldb_expr_result"); // functions actually should
330 // be treated like function
333 result_ptr_id
= &Ctx
.Idents
.get("$__lldb_expr_result_ptr");
335 m_sema
->RequireCompleteType(last_expr
->getSourceRange().getBegin(),
337 clang::diag::err_incomplete_type
);
339 QualType ptr_qual_type
;
341 if (expr_qual_type
->getAs
<ObjCObjectType
>() != nullptr)
342 ptr_qual_type
= Ctx
.getObjCObjectPointerType(expr_qual_type
);
344 ptr_qual_type
= Ctx
.getPointerType(expr_qual_type
);
347 VarDecl::Create(Ctx
, DC
, SourceLocation(), SourceLocation(),
348 result_ptr_id
, ptr_qual_type
, nullptr, SC_Static
);
353 ExprResult address_of_expr
=
354 m_sema
->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf
, last_expr
);
355 if (address_of_expr
.get())
356 m_sema
->AddInitializerToDecl(result_decl
, address_of_expr
.get(), true);
360 IdentifierInfo
&result_id
= Ctx
.Idents
.get("$__lldb_expr_result");
363 VarDecl::Create(Ctx
, DC
, SourceLocation(), SourceLocation(), &result_id
,
364 expr_qual_type
, nullptr, SC_Static
);
369 m_sema
->AddInitializerToDecl(result_decl
, last_expr
, true);
372 DC
->addDecl(result_decl
);
374 ///////////////////////////////
375 // call AddInitializerToDecl
378 // m_sema->AddInitializerToDecl(result_decl, last_expr);
380 /////////////////////////////////
381 // call ConvertDeclToDeclGroup
384 Sema::DeclGroupPtrTy result_decl_group_ptr
;
386 result_decl_group_ptr
= m_sema
->ConvertDeclToDeclGroup(result_decl
);
388 ////////////////////////
389 // call ActOnDeclStmt
392 StmtResult
result_initialization_stmt_result(m_sema
->ActOnDeclStmt(
393 result_decl_group_ptr
, SourceLocation(), SourceLocation()));
395 ////////////////////////////////////////////////
396 // replace the old statement with the new one
399 *last_stmt_ptr
= static_cast<Stmt
*>(result_initialization_stmt_result
.get());
404 void ASTResultSynthesizer::HandleTranslationUnit(ASTContext
&Ctx
) {
406 m_passthrough
->HandleTranslationUnit(Ctx
);
409 void ASTResultSynthesizer::RecordPersistentTypes(DeclContext
*FunDeclCtx
) {
410 typedef DeclContext::specific_decl_iterator
<TypeDecl
> TypeDeclIterator
;
412 for (TypeDeclIterator i
= TypeDeclIterator(FunDeclCtx
->decls_begin()),
413 e
= TypeDeclIterator(FunDeclCtx
->decls_end());
415 MaybeRecordPersistentType(*i
);
419 void ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl
*D
) {
420 if (!D
->getIdentifier())
423 StringRef name
= D
->getName();
424 if (name
.empty() || name
.front() != '$')
427 LLDB_LOG(GetLog(LLDBLog::Expressions
), "Recording persistent type {0}", name
);
429 m_decls
.push_back(D
);
432 void ASTResultSynthesizer::RecordPersistentDecl(NamedDecl
*D
) {
433 lldbassert(m_top_level
);
435 if (!D
->getIdentifier())
438 StringRef name
= D
->getName();
442 LLDB_LOG(GetLog(LLDBLog::Expressions
), "Recording persistent decl {0}", name
);
444 m_decls
.push_back(D
);
447 void ASTResultSynthesizer::CommitPersistentDecls() {
449 m_target
.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC
);
453 auto *persistent_vars
= llvm::cast
<ClangPersistentVariables
>(state
);
455 lldb::TypeSystemClangSP scratch_ts_sp
= ScratchTypeSystemClang::GetForTarget(
456 m_target
, m_ast_context
->getLangOpts());
458 for (clang::NamedDecl
*decl
: m_decls
) {
459 StringRef name
= decl
->getName();
461 Decl
*D_scratch
= persistent_vars
->GetClangASTImporter()->DeportDecl(
462 &scratch_ts_sp
->getASTContext(), decl
);
465 Log
*log
= GetLog(LLDBLog::Expressions
);
469 llvm::raw_string_ostream
ss(s
);
472 LLDB_LOGF(log
, "Couldn't commit persistent decl: %s\n", s
.c_str());
478 if (NamedDecl
*NamedDecl_scratch
= dyn_cast
<NamedDecl
>(D_scratch
))
479 persistent_vars
->RegisterPersistentDecl(ConstString(name
),
480 NamedDecl_scratch
, scratch_ts_sp
);
484 void ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl
*D
) {
486 m_passthrough
->HandleTagDeclDefinition(D
);
489 void ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl
*D
) {
491 m_passthrough
->CompleteTentativeDefinition(D
);
494 void ASTResultSynthesizer::HandleVTable(CXXRecordDecl
*RD
) {
496 m_passthrough
->HandleVTable(RD
);
499 void ASTResultSynthesizer::PrintStats() {
501 m_passthrough
->PrintStats();
504 void ASTResultSynthesizer::InitializeSema(Sema
&S
) {
507 if (m_passthrough_sema
)
508 m_passthrough_sema
->InitializeSema(S
);
511 void ASTResultSynthesizer::ForgetSema() {
514 if (m_passthrough_sema
)
515 m_passthrough_sema
->ForgetSema();