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);
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);
142 raw_string_ostream os(s);
144 function_decl->print(os);
146 LLDB_LOGF(log,
"Transformed function AST:\n%s", s.c_str());
153 ObjCMethodDecl *MethodDecl) {
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);
182 raw_string_ostream os(s);
184 MethodDecl->print(os);
186 LLDB_LOGF(log,
"Transformed method AST:\n%s", s.c_str());
196 assert(lvalue_expr->getValueKind() == VK_LValue &&
197 "lvalue_expr not a lvalue");
199 QualType qt = lvalue_expr->getType();
207 if (qt->isIntegralOrEnumerationType() && qt.isConstQualified() &&
208 !qt.isVolatileQualified())
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);
247 ImplicitCastExpr *implicit_cast = dyn_cast<ImplicitCastExpr>(last_expr);
252 if (implicit_cast->getCastKind() != CK_LValueToRValue)
255 last_expr = implicit_cast->getSubExpr();
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;
325 IdentifierInfo *result_ptr_id;
327 if (expr_type->isFunctionType())
329 &Ctx.Idents.get(
"$__lldb_expr_result");
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);
384 Sema::DeclGroupPtrTy result_decl_group_ptr;
386 result_decl_group_ptr =
m_sema->ConvertDeclToDeclGroup(result_decl);
392 StmtResult result_initialization_stmt_result(
m_sema->ActOnDeclStmt(
393 result_decl_group_ptr, SourceLocation(), SourceLocation()));
399 *last_stmt_ptr =
static_cast<Stmt *
>(result_initialization_stmt_result.get());
410 typedef DeclContext::specific_decl_iterator<TypeDecl> TypeDeclIterator;
412 for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()),
413 e = TypeDeclIterator(FunDeclCtx->decls_end());
420 if (!D->getIdentifier())
423 StringRef name = D->getName();
424 if (name.empty() || name.front() !=
'$')
435 if (!D->getIdentifier())
438 StringRef name = D->getName();
453 auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);
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);
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);
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