1//===-- ASTResultSynthesizer.cpp ------------------------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#include "ASTResultSynthesizer.h"
10
11#include "ClangASTImporter.h"
12#include "ClangPersistentVariables.h"
13
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"
30#include <cstdlib>
31
32using namespace llvm;
33using namespace clang;
34using namespace lldb_private;
35
36ASTResultSynthesizer::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) {
41  if (!m_passthrough)
42    return;
43
44  m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
45}
46
47ASTResultSynthesizer::~ASTResultSynthesizer() = default;
48
49void ASTResultSynthesizer::Initialize(ASTContext &Context) {
50  m_ast_context = &Context;
51
52  if (m_passthrough)
53    m_passthrough->Initialize(Context);
54}
55
56void ASTResultSynthesizer::TransformTopLevelDecl(Decl *D) {
57  Log *log = GetLog(LLDBLog::Expressions);
58
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());
67      else
68        LLDB_LOGF(log, "TransformTopLevelDecl(<complex>)");
69    }
70
71    if (m_top_level) {
72      RecordPersistentDecl(named_decl);
73    }
74  }
75
76  if (LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D)) {
77    RecordDecl::decl_iterator decl_iterator;
78
79    for (decl_iterator = linkage_spec_decl->decls_begin();
80         decl_iterator != linkage_spec_decl->decls_end(); ++decl_iterator) {
81      TransformTopLevelDecl(*decl_iterator);
82    }
83  } else if (!m_top_level) {
84    if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D)) {
85      if (m_ast_context &&
86          !method_decl->getSelector().getAsString().compare("$__lldb_expr:")) {
87        RecordPersistentTypes(method_decl);
88        SynthesizeObjCMethodResult(method_decl);
89      }
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);
96      }
97    }
98  }
99}
100
101bool ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D) {
102  DeclGroupRef::iterator decl_iterator;
103
104  for (decl_iterator = D.begin(); decl_iterator != D.end(); ++decl_iterator) {
105    Decl *decl = *decl_iterator;
106
107    TransformTopLevelDecl(decl);
108  }
109
110  if (m_passthrough)
111    return m_passthrough->HandleTopLevelDecl(D);
112  return true;
113}
114
115bool ASTResultSynthesizer::SynthesizeFunctionResult(FunctionDecl *FunDecl) {
116  Log *log = GetLog(LLDBLog::Expressions);
117
118  if (!m_sema)
119    return false;
120
121  FunctionDecl *function_decl = FunDecl;
122
123  if (!function_decl)
124    return false;
125
126  if (log && log->GetVerbose()) {
127    std::string s;
128    raw_string_ostream os(s);
129
130    function_decl->print(os);
131
132    os.flush();
133
134    LLDB_LOGF(log, "Untransformed function AST:\n%s", s.c_str());
135  }
136
137  Stmt *function_body = function_decl->getBody();
138  CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body);
139
140  bool ret = SynthesizeBodyResult(compound_stmt, function_decl);
141
142  if (log && log->GetVerbose()) {
143    std::string s;
144    raw_string_ostream os(s);
145
146    function_decl->print(os);
147
148    os.flush();
149
150    LLDB_LOGF(log, "Transformed function AST:\n%s", s.c_str());
151  }
152
153  return ret;
154}
155
156bool ASTResultSynthesizer::SynthesizeObjCMethodResult(
157    ObjCMethodDecl *MethodDecl) {
158  Log *log = GetLog(LLDBLog::Expressions);
159
160  if (!m_sema)
161    return false;
162
163  if (!MethodDecl)
164    return false;
165
166  if (log && log->GetVerbose()) {
167    std::string s;
168    raw_string_ostream os(s);
169
170    MethodDecl->print(os);
171
172    os.flush();
173
174    LLDB_LOGF(log, "Untransformed method AST:\n%s", s.c_str());
175  }
176
177  Stmt *method_body = MethodDecl->getBody();
178
179  if (!method_body)
180    return false;
181
182  CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(method_body);
183
184  bool ret = SynthesizeBodyResult(compound_stmt, MethodDecl);
185
186  if (log && log->GetVerbose()) {
187    std::string s;
188    raw_string_ostream os(s);
189
190    MethodDecl->print(os);
191
192    os.flush();
193
194    LLDB_LOGF(log, "Transformed method AST:\n%s", s.c_str());
195  }
196
197  return ret;
198}
199
200/// Returns true if LLDB can take the address of the given lvalue for the sake
201/// of capturing the expression result. Returns false if LLDB should instead
202/// store the expression result in a result variable.
203static bool CanTakeAddressOfLValue(const Expr *lvalue_expr) {
204  assert(lvalue_expr->getValueKind() == VK_LValue &&
205         "lvalue_expr not a lvalue");
206
207  QualType qt = lvalue_expr->getType();
208  // If the lvalue has const-qualified non-volatile integral or enum type, then
209  // the underlying value might come from a const static data member as
210  // described in C++11 [class.static.data]p3. If that's the case, then the
211  // value might not have an address if the user didn't also define the member
212  // in a namespace scope. Taking the address would cause that LLDB later fails
213  // to link the expression, so those lvalues should be stored in a result
214  // variable.
215  if (qt->isIntegralOrEnumerationType() && qt.isConstQualified() &&
216      !qt.isVolatileQualified())
217    return false;
218  return true;
219}
220
221bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body,
222                                                DeclContext *DC) {
223  Log *log = GetLog(LLDBLog::Expressions);
224
225  ASTContext &Ctx(*m_ast_context);
226
227  if (!Body)
228    return false;
229
230  if (Body->body_empty())
231    return false;
232
233  Stmt **last_stmt_ptr = Body->body_end() - 1;
234  Stmt *last_stmt = *last_stmt_ptr;
235
236  while (isa<NullStmt>(last_stmt)) {
237    if (last_stmt_ptr != Body->body_begin()) {
238      last_stmt_ptr--;
239      last_stmt = *last_stmt_ptr;
240    } else {
241      return false;
242    }
243  }
244
245  Expr *last_expr = dyn_cast<Expr>(last_stmt);
246
247  if (!last_expr)
248    // No auxiliary variable necessary; expression returns void
249    return true;
250
251  // In C++11, last_expr can be a LValueToRvalue implicit cast.  Strip that off
252  // if that's the case.
253
254  do {
255    ImplicitCastExpr *implicit_cast = dyn_cast<ImplicitCastExpr>(last_expr);
256
257    if (!implicit_cast)
258      break;
259
260    if (implicit_cast->getCastKind() != CK_LValueToRValue)
261      break;
262
263    last_expr = implicit_cast->getSubExpr();
264  } while (false);
265
266  // is_lvalue is used to record whether the expression returns an assignable
267  // Lvalue or an Rvalue.  This is relevant because they are handled
268  // differently.
269  //
270  // For Lvalues
271  //
272  //   - In AST result synthesis (here!) the expression E is transformed into an
273  //     initialization T *$__lldb_expr_result_ptr = &E.
274  //
275  //   - In structure allocation, a pointer-sized slot is allocated in the
276  //     struct that is to be passed into the expression.
277  //
278  //   - In IR transformations, reads and writes to $__lldb_expr_result_ptr are
279  //     redirected at an entry in the struct ($__lldb_arg) passed into the
280  //     expression. (Other persistent variables are treated similarly, having
281  //     been materialized as references, but in those cases the value of the
282  //     reference itself is never modified.)
283  //
284  //   - During materialization, $0 (the result persistent variable) is ignored.
285  //
286  //   - During dematerialization, $0 is marked up as a load address with value
287  //     equal to the contents of the structure entry.
288  //
289  //   - Note: if we cannot take an address of the resulting Lvalue (e.g. it's
290  //     a static const member without an out-of-class definition), then we
291  //     follow the Rvalue route.
292  //
293  // For Rvalues
294  //
295  //   - In AST result synthesis the expression E is transformed into an
296  //     initialization static T $__lldb_expr_result = E.
297  //
298  //   - In structure allocation, a pointer-sized slot is allocated in the
299  //     struct that is to be passed into the expression.
300  //
301  //   - In IR transformations, an instruction is inserted at the beginning of
302  //     the function to dereference the pointer resident in the slot. Reads and
303  //     writes to $__lldb_expr_result are redirected at that dereferenced
304  //     version. Guard variables for the static variable are excised.
305  //
306  //   - During materialization, $0 (the result persistent variable) is
307  //     populated with the location of a newly-allocated area of memory.
308  //
309  //   - During dematerialization, $0 is ignored.
310
311  bool is_lvalue = last_expr->getValueKind() == VK_LValue &&
312                   last_expr->getObjectKind() == OK_Ordinary;
313
314  QualType expr_qual_type = last_expr->getType();
315  const clang::Type *expr_type = expr_qual_type.getTypePtr();
316
317  if (!expr_type)
318    return false;
319
320  if (expr_type->isVoidType())
321    return true;
322
323  if (log) {
324    std::string s = expr_qual_type.getAsString();
325
326    LLDB_LOGF(log, "Last statement is an %s with type: %s",
327              (is_lvalue ? "lvalue" : "rvalue"), s.c_str());
328  }
329
330  clang::VarDecl *result_decl = nullptr;
331
332  if (is_lvalue && CanTakeAddressOfLValue(last_expr)) {
333    IdentifierInfo *result_ptr_id;
334
335    if (expr_type->isFunctionType())
336      result_ptr_id =
337          &Ctx.Idents.get("$__lldb_expr_result"); // functions actually should
338                                                  // be treated like function
339                                                  // pointers
340    else
341      result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result_ptr");
342
343    m_sema->RequireCompleteType(last_expr->getSourceRange().getBegin(),
344                                expr_qual_type,
345                                clang::diag::err_incomplete_type);
346
347    QualType ptr_qual_type;
348
349    if (expr_qual_type->getAs<ObjCObjectType>() != nullptr)
350      ptr_qual_type = Ctx.getObjCObjectPointerType(expr_qual_type);
351    else
352      ptr_qual_type = Ctx.getPointerType(expr_qual_type);
353
354    result_decl =
355        VarDecl::Create(Ctx, DC, SourceLocation(), SourceLocation(),
356                        result_ptr_id, ptr_qual_type, nullptr, SC_Static);
357
358    if (!result_decl)
359      return false;
360
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);
365    else
366      return false;
367  } else {
368    IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result");
369
370    result_decl =
371        VarDecl::Create(Ctx, DC, SourceLocation(), SourceLocation(), &result_id,
372                        expr_qual_type, nullptr, SC_Static);
373
374    if (!result_decl)
375      return false;
376
377    m_sema->AddInitializerToDecl(result_decl, last_expr, true);
378  }
379
380  DC->addDecl(result_decl);
381
382  ///////////////////////////////
383  // call AddInitializerToDecl
384  //
385
386  // m_sema->AddInitializerToDecl(result_decl, last_expr);
387
388  /////////////////////////////////
389  // call ConvertDeclToDeclGroup
390  //
391
392  Sema::DeclGroupPtrTy result_decl_group_ptr;
393
394  result_decl_group_ptr = m_sema->ConvertDeclToDeclGroup(result_decl);
395
396  ////////////////////////
397  // call ActOnDeclStmt
398  //
399
400  StmtResult result_initialization_stmt_result(m_sema->ActOnDeclStmt(
401      result_decl_group_ptr, SourceLocation(), SourceLocation()));
402
403  ////////////////////////////////////////////////
404  // replace the old statement with the new one
405  //
406
407  *last_stmt_ptr = static_cast<Stmt *>(result_initialization_stmt_result.get());
408
409  return true;
410}
411
412void ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx) {
413  if (m_passthrough)
414    m_passthrough->HandleTranslationUnit(Ctx);
415}
416
417void ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx) {
418  typedef DeclContext::specific_decl_iterator<TypeDecl> TypeDeclIterator;
419
420  for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()),
421                        e = TypeDeclIterator(FunDeclCtx->decls_end());
422       i != e; ++i) {
423    MaybeRecordPersistentType(*i);
424  }
425}
426
427void ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D) {
428  if (!D->getIdentifier())
429    return;
430
431  StringRef name = D->getName();
432  if (name.empty() || name.front() != '$')
433    return;
434
435  LLDB_LOG(GetLog(LLDBLog::Expressions), "Recording persistent type {0}", name);
436
437  m_decls.push_back(D);
438}
439
440void ASTResultSynthesizer::RecordPersistentDecl(NamedDecl *D) {
441  lldbassert(m_top_level);
442
443  if (!D->getIdentifier())
444    return;
445
446  StringRef name = D->getName();
447  if (name.empty())
448    return;
449
450  LLDB_LOG(GetLog(LLDBLog::Expressions), "Recording persistent decl {0}", name);
451
452  m_decls.push_back(D);
453}
454
455void ASTResultSynthesizer::CommitPersistentDecls() {
456  auto *state =
457      m_target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC);
458  if (!state)
459    return;
460
461  auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);
462
463  lldb::TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(
464      m_target, m_ast_context->getLangOpts());
465
466  for (clang::NamedDecl *decl : m_decls) {
467    StringRef name = decl->getName();
468
469    Decl *D_scratch = persistent_vars->GetClangASTImporter()->DeportDecl(
470        &scratch_ts_sp->getASTContext(), decl);
471
472    if (!D_scratch) {
473      Log *log = GetLog(LLDBLog::Expressions);
474
475      if (log) {
476        std::string s;
477        llvm::raw_string_ostream ss(s);
478        decl->dump(ss);
479        ss.flush();
480
481        LLDB_LOGF(log, "Couldn't commit persistent  decl: %s\n", s.c_str());
482      }
483
484      continue;
485    }
486
487    if (NamedDecl *NamedDecl_scratch = dyn_cast<NamedDecl>(D_scratch))
488      persistent_vars->RegisterPersistentDecl(ConstString(name),
489                                              NamedDecl_scratch, scratch_ts_sp);
490  }
491}
492
493void ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D) {
494  if (m_passthrough)
495    m_passthrough->HandleTagDeclDefinition(D);
496}
497
498void ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D) {
499  if (m_passthrough)
500    m_passthrough->CompleteTentativeDefinition(D);
501}
502
503void ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD) {
504  if (m_passthrough)
505    m_passthrough->HandleVTable(RD);
506}
507
508void ASTResultSynthesizer::PrintStats() {
509  if (m_passthrough)
510    m_passthrough->PrintStats();
511}
512
513void ASTResultSynthesizer::InitializeSema(Sema &S) {
514  m_sema = &S;
515
516  if (m_passthrough_sema)
517    m_passthrough_sema->InitializeSema(S);
518}
519
520void ASTResultSynthesizer::ForgetSema() {
521  m_sema = nullptr;
522
523  if (m_passthrough_sema)
524    m_passthrough_sema->ForgetSema();
525}
526