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"
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) {
59 if (NamedDecl *named_decl = dyn_cast<NamedDecl>(D)) {
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>)");
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) {
84 if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D)) {
86 !method_decl->getSelector().getAsString().compare(
"$__lldb_expr:")) {
90 }
else if (FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D)) {
93 !function_decl->getNameInfo().getAsString().compare(
"$__lldb_expr")) {
102 DeclGroupRef::iterator decl_iterator;
104 for (decl_iterator = D.begin(); decl_iterator != D.end(); ++decl_iterator) {
105 Decl *decl = *decl_iterator;
121 FunctionDecl *function_decl = FunDecl;
128 raw_string_ostream os(s);
130 function_decl->print(os);
134 LLDB_LOGF(log,
"Untransformed function AST:\n%s", s.c_str());
137 Stmt *function_body = function_decl->getBody();
138 CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body);
144 raw_string_ostream os(s);
146 function_decl->print(os);
150 LLDB_LOGF(log,
"Transformed function AST:\n%s", s.c_str());
157 ObjCMethodDecl *MethodDecl) {
168 raw_string_ostream os(s);
170 MethodDecl->print(os);
174 LLDB_LOGF(log,
"Untransformed method AST:\n%s", s.c_str());
177 Stmt *method_body = MethodDecl->getBody();
182 CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(method_body);
188 raw_string_ostream os(s);
190 MethodDecl->print(os);
194 LLDB_LOGF(log,
"Transformed method AST:\n%s", s.c_str());
204 assert(lvalue_expr->getValueKind() == VK_LValue &&
205 "lvalue_expr not a lvalue");
207 QualType qt = lvalue_expr->getType();
215 if (qt->isIntegralOrEnumerationType() && qt.isConstQualified() &&
216 !qt.isVolatileQualified())
230 if (Body->body_empty())
233 Stmt **last_stmt_ptr = Body->body_end() - 1;
234 Stmt *last_stmt = *last_stmt_ptr;
236 while (isa<NullStmt>(last_stmt)) {
237 if (last_stmt_ptr != Body->body_begin()) {
239 last_stmt = *last_stmt_ptr;
245 Expr *last_expr = dyn_cast<Expr>(last_stmt);
255 ImplicitCastExpr *implicit_cast = dyn_cast<ImplicitCastExpr>(last_expr);
260 if (implicit_cast->getCastKind() != CK_LValueToRValue)
263 last_expr = implicit_cast->getSubExpr();
311 bool is_lvalue = last_expr->getValueKind() == VK_LValue &&
312 last_expr->getObjectKind() == OK_Ordinary;
314 QualType expr_qual_type = last_expr->getType();
315 const clang::Type *expr_type = expr_qual_type.getTypePtr();
320 if (expr_type->isVoidType())
324 std::string s = expr_qual_type.getAsString();
326 LLDB_LOGF(log,
"Last statement is an %s with type: %s",
327 (is_lvalue ?
"lvalue" :
"rvalue"), s.c_str());
330 clang::VarDecl *result_decl =
nullptr;
333 IdentifierInfo *result_ptr_id;
335 if (expr_type->isFunctionType())
337 &Ctx.Idents.get(
"$__lldb_expr_result");
341 result_ptr_id = &Ctx.Idents.get(
"$__lldb_expr_result_ptr");
343 m_sema->RequireCompleteType(last_expr->getSourceRange().getBegin(),
345 clang::diag::err_incomplete_type);
347 QualType ptr_qual_type;
349 if (expr_qual_type->getAs<ObjCObjectType>() !=
nullptr)
350 ptr_qual_type = Ctx.getObjCObjectPointerType(expr_qual_type);
352 ptr_qual_type = Ctx.getPointerType(expr_qual_type);
355 VarDecl::Create(Ctx, DC, SourceLocation(), SourceLocation(),
356 result_ptr_id, ptr_qual_type,
nullptr, SC_Static);
361 ExprResult address_of_expr =
362 m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr);
363 if (address_of_expr.get())
364 m_sema->AddInitializerToDecl(result_decl, address_of_expr.get(),
true);
368 IdentifierInfo &result_id = Ctx.Idents.get(
"$__lldb_expr_result");
371 VarDecl::Create(Ctx, DC, SourceLocation(), SourceLocation(), &result_id,
372 expr_qual_type,
nullptr, SC_Static);
377 m_sema->AddInitializerToDecl(result_decl, last_expr,
true);
380 DC->addDecl(result_decl);
392 Sema::DeclGroupPtrTy result_decl_group_ptr;
394 result_decl_group_ptr =
m_sema->ConvertDeclToDeclGroup(result_decl);
400 StmtResult result_initialization_stmt_result(
m_sema->ActOnDeclStmt(
401 result_decl_group_ptr, SourceLocation(), SourceLocation()));
407 *last_stmt_ptr =
static_cast<Stmt *
>(result_initialization_stmt_result.get());
418 typedef DeclContext::specific_decl_iterator<TypeDecl> TypeDeclIterator;
420 for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()),
421 e = TypeDeclIterator(FunDeclCtx->decls_end());
428 if (!D->getIdentifier())
431 StringRef name = D->getName();
432 if (name.empty() || name.front() !=
'$')
443 if (!D->getIdentifier())
446 StringRef name = D->getName();
461 auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);
466 for (clang::NamedDecl *decl :
m_decls) {
467 StringRef name = decl->getName();
469 Decl *D_scratch = persistent_vars->GetClangASTImporter()->DeportDecl(
470 &scratch_ts_sp->getASTContext(), decl);
477 llvm::raw_string_ostream ss(s);
481 LLDB_LOGF(log,
"Couldn't commit persistent decl: %s\n", s.c_str());
487 if (NamedDecl *NamedDecl_scratch = dyn_cast<NamedDecl>(D_scratch))
488 persistent_vars->RegisterPersistentDecl(
ConstString(name),
489 NamedDecl_scratch, scratch_ts_sp);
static bool CanTakeAddressOfLValue(const Expr *lvalue_expr)
Returns true if LLDB can take the address of the given lvalue for the sake of capturing the expressio...
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_LOGF(log,...)
clang::ASTContext * m_ast_context
The AST context to use for identifiers and types.
clang::ASTConsumer * m_passthrough
The ASTConsumer down the chain, for passthrough.
clang::SemaConsumer * m_passthrough_sema
The SemaConsumer down the chain, for passthrough.
void CommitPersistentDecls()
The parse has succeeded, so record its persistent decls.
void RecordPersistentTypes(clang::DeclContext *FunDeclCtx)
Given a DeclContext for a function or method, find all types declared in the context and record any p...
void RecordPersistentDecl(clang::NamedDecl *D)
Given a NamedDecl, register it as a pointer type in the target's scratch AST context.
bool SynthesizeBodyResult(clang::CompoundStmt *Body, clang::DeclContext *DC)
Process a function body and produce the result variable and initialization.
bool SynthesizeFunctionResult(clang::FunctionDecl *FunDecl)
Process a function and produce the result variable and initialization.
Target & m_target
The target, which contains the persistent variable store and the.
~ASTResultSynthesizer() override
Destructor.
ASTResultSynthesizer(clang::ASTConsumer *passthrough, bool top_level, Target &target)
Constructor.
void HandleTagDeclDefinition(clang::TagDecl *D) override
Passthrough stub.
void InitializeSema(clang::Sema &S) override
Set the Sema object to use when performing transforms, and pass it on.
void TransformTopLevelDecl(clang::Decl *D)
Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing as necessary through LinkageSpecD...
bool SynthesizeObjCMethodResult(clang::ObjCMethodDecl *MethodDecl)
Process an Objective-C method and produce the result variable and initialization.
bool HandleTopLevelDecl(clang::DeclGroupRef D) override
Examine a list of Decls to find the function $__lldb_expr and transform its code.
std::vector< clang::NamedDecl * > m_decls
Persistent declarations to register assuming the expression succeeds.
void CompleteTentativeDefinition(clang::VarDecl *D) override
Passthrough stub.
void HandleVTable(clang::CXXRecordDecl *RD) override
Passthrough stub.
void HandleTranslationUnit(clang::ASTContext &Ctx) override
Passthrough stub.
void ForgetSema() override
Reset the Sema to NULL now that transformations are done.
void PrintStats() override
Passthrough stub.
void Initialize(clang::ASTContext &Context) override
Link this consumer with a particular AST context.
void MaybeRecordPersistentType(clang::TypeDecl *D)
Given a TypeDecl, if it declares a type whose name starts with a dollar sign, register it as a pointe...
clang::Sema * m_sema
The Sema to use.
A uniqued constant string class.
static lldb::TypeSystemClangSP GetForTarget(Target &target, std::optional< IsolatedASTKind > ast_kind=DefaultAST, bool create_on_demand=true)
Returns the scratch TypeSystemClang for the given target.
PersistentExpressionState * GetPersistentExpressionStateForLanguage(lldb::LanguageType language)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
@ eLanguageTypeC
Non-standardized C, such as K&R.
std::shared_ptr< lldb_private::TypeSystemClang > TypeSystemClangSP