Coverage Report

Created: 2022-01-25 06:29

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