Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/AST/Interp/ByteCodeStmtGen.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- ByteCodeStmtGen.cpp - Code generator for expressions ---*- C++ -*-===//
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 "ByteCodeStmtGen.h"
10
#include "ByteCodeEmitter.h"
11
#include "ByteCodeGenError.h"
12
#include "Context.h"
13
#include "Function.h"
14
#include "PrimType.h"
15
16
using namespace clang;
17
using namespace clang::interp;
18
19
namespace clang {
20
namespace interp {
21
22
/// Scope managing label targets.
23
template <class Emitter> class LabelScope {
24
public:
25
0
  virtual ~LabelScope() {  }
26
27
protected:
28
0
  LabelScope(ByteCodeStmtGen<Emitter> *Ctx) : Ctx(Ctx) {}
29
  /// ByteCodeStmtGen instance.
30
  ByteCodeStmtGen<Emitter> *Ctx;
31
};
32
33
/// Sets the context for break/continue statements.
34
template <class Emitter> class LoopScope final : public LabelScope<Emitter> {
35
public:
36
  using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy;
37
  using OptLabelTy = typename ByteCodeStmtGen<Emitter>::OptLabelTy;
38
39
  LoopScope(ByteCodeStmtGen<Emitter> *Ctx, LabelTy BreakLabel,
40
            LabelTy ContinueLabel)
41
      : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
42
0
        OldContinueLabel(Ctx->ContinueLabel) {
43
0
    this->Ctx->BreakLabel = BreakLabel;
44
0
    this->Ctx->ContinueLabel = ContinueLabel;
45
0
  }
46
47
0
  ~LoopScope() {
48
0
    this->Ctx->BreakLabel = OldBreakLabel;
49
0
    this->Ctx->ContinueLabel = OldContinueLabel;
50
0
  }
51
52
private:
53
  OptLabelTy OldBreakLabel;
54
  OptLabelTy OldContinueLabel;
55
};
56
57
// Sets the context for a switch scope, mapping labels.
58
template <class Emitter> class SwitchScope final : public LabelScope<Emitter> {
59
public:
60
  using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy;
61
  using OptLabelTy = typename ByteCodeStmtGen<Emitter>::OptLabelTy;
62
  using CaseMap = typename ByteCodeStmtGen<Emitter>::CaseMap;
63
64
  SwitchScope(ByteCodeStmtGen<Emitter> *Ctx, CaseMap &&CaseLabels,
65
              LabelTy BreakLabel, OptLabelTy DefaultLabel)
66
      : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
67
        OldDefaultLabel(this->Ctx->DefaultLabel),
68
0
        OldCaseLabels(std::move(this->Ctx->CaseLabels)) {
69
0
    this->Ctx->BreakLabel = BreakLabel;
70
0
    this->Ctx->DefaultLabel = DefaultLabel;
71
0
    this->Ctx->CaseLabels = std::move(CaseLabels);
72
0
  }
73
74
0
  ~SwitchScope() {
75
0
    this->Ctx->BreakLabel = OldBreakLabel;
76
0
    this->Ctx->DefaultLabel = OldDefaultLabel;
77
0
    this->Ctx->CaseLabels = std::move(OldCaseLabels);
78
0
  }
79
80
private:
81
  OptLabelTy OldBreakLabel;
82
  OptLabelTy OldDefaultLabel;
83
  CaseMap OldCaseLabels;
84
};
85
86
} // namespace interp
87
} // namespace clang
88
89
template <class Emitter>
90
bool ByteCodeStmtGen<Emitter>::emitLambdaStaticInvokerBody(
91
0
    const CXXMethodDecl *MD) {
92
0
  assert(MD->isLambdaStaticInvoker());
93
0
  assert(MD->hasBody());
94
0
  assert(cast<CompoundStmt>(MD->getBody())->body_empty());
95
96
0
  const CXXRecordDecl *ClosureClass = MD->getParent();
97
0
  const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator();
98
0
  assert(ClosureClass->captures_begin() == ClosureClass->captures_end());
99
0
  const Function *Func = this->getFunction(LambdaCallOp);
100
0
  if (!Func)
101
0
    return false;
102
0
  assert(Func->hasThisPointer());
103
0
  assert(Func->getNumParams() == (MD->getNumParams() + 1 + Func->hasRVO()));
104
105
0
  if (Func->hasRVO()) {
106
0
    if (!this->emitRVOPtr(MD))
107
0
      return false;
108
0
  }
109
110
  // The lambda call operator needs an instance pointer, but we don't have
111
  // one here, and we don't need one either because the lambda cannot have
112
  // any captures, as verified above. Emit a null pointer. This is then
113
  // special-cased when interpreting to not emit any misleading diagnostics.
114
0
  if (!this->emitNullPtr(MD))
115
0
    return false;
116
117
  // Forward all arguments from the static invoker to the lambda call operator.
118
0
  for (const ParmVarDecl *PVD : MD->parameters()) {
119
0
    auto It = this->Params.find(PVD);
120
0
    assert(It != this->Params.end());
121
122
    // We do the lvalue-to-rvalue conversion manually here, so no need
123
    // to care about references.
124
0
    PrimType ParamType = this->classify(PVD->getType()).value_or(PT_Ptr);
125
0
    if (!this->emitGetParam(ParamType, It->second.Offset, MD))
126
0
      return false;
127
0
  }
128
129
0
  if (!this->emitCall(Func, LambdaCallOp))
130
0
    return false;
131
132
0
  this->emitCleanup();
133
0
  if (ReturnType)
134
0
    return this->emitRet(*ReturnType, MD);
135
136
  // Nothing to do, since we emitted the RVO pointer above.
137
0
  return this->emitRetVoid(MD);
138
0
}
139
140
template <class Emitter>
141
0
bool ByteCodeStmtGen<Emitter>::visitFunc(const FunctionDecl *F) {
142
  // Classify the return type.
143
0
  ReturnType = this->classify(F->getReturnType());
144
145
  // Emit custom code if this is a lambda static invoker.
146
0
  if (const auto *MD = dyn_cast<CXXMethodDecl>(F);
147
0
      MD && MD->isLambdaStaticInvoker())
148
0
    return this->emitLambdaStaticInvokerBody(MD);
149
150
  // Constructor. Set up field initializers.
151
0
  if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(F)) {
152
0
    const RecordDecl *RD = Ctor->getParent();
153
0
    const Record *R = this->getRecord(RD);
154
0
    if (!R)
155
0
      return false;
156
157
0
    for (const auto *Init : Ctor->inits()) {
158
      // Scope needed for the initializers.
159
0
      BlockScope<Emitter> Scope(this);
160
161
0
      const Expr *InitExpr = Init->getInit();
162
0
      if (const FieldDecl *Member = Init->getMember()) {
163
0
        const Record::Field *F = R->getField(Member);
164
165
0
        if (std::optional<PrimType> T = this->classify(InitExpr)) {
166
0
          if (!this->visit(InitExpr))
167
0
            return false;
168
169
0
          if (F->isBitField()) {
170
0
            if (!this->emitInitThisBitField(*T, F, InitExpr))
171
0
              return false;
172
0
          } else {
173
0
            if (!this->emitInitThisField(*T, F->Offset, InitExpr))
174
0
              return false;
175
0
          }
176
0
        } else {
177
          // Non-primitive case. Get a pointer to the field-to-initialize
178
          // on the stack and call visitInitialzer() for it.
179
0
          if (!this->emitGetPtrThisField(F->Offset, InitExpr))
180
0
            return false;
181
182
0
          if (!this->visitInitializer(InitExpr))
183
0
            return false;
184
185
0
          if (!this->emitPopPtr(InitExpr))
186
0
            return false;
187
0
        }
188
0
      } else if (const Type *Base = Init->getBaseClass()) {
189
        // Base class initializer.
190
        // Get This Base and call initializer on it.
191
0
        const auto *BaseDecl = Base->getAsCXXRecordDecl();
192
0
        assert(BaseDecl);
193
0
        const Record::Base *B = R->getBase(BaseDecl);
194
0
        assert(B);
195
0
        if (!this->emitGetPtrThisBase(B->Offset, InitExpr))
196
0
          return false;
197
0
        if (!this->visitInitializer(InitExpr))
198
0
          return false;
199
0
        if (!this->emitInitPtrPop(InitExpr))
200
0
          return false;
201
0
      } else {
202
0
        assert(Init->isDelegatingInitializer());
203
0
        if (!this->emitThis(InitExpr))
204
0
          return false;
205
0
        if (!this->visitInitializer(Init->getInit()))
206
0
          return false;
207
0
        if (!this->emitPopPtr(InitExpr))
208
0
          return false;
209
0
      }
210
0
    }
211
0
  }
212
213
0
  if (const auto *Body = F->getBody())
214
0
    if (!visitStmt(Body))
215
0
      return false;
216
217
  // Emit a guard return to protect against a code path missing one.
218
0
  if (F->getReturnType()->isVoidType())
219
0
    return this->emitRetVoid(SourceInfo{});
220
0
  else
221
0
    return this->emitNoRet(SourceInfo{});
222
0
}
223
224
template <class Emitter>
225
0
bool ByteCodeStmtGen<Emitter>::visitStmt(const Stmt *S) {
226
0
  switch (S->getStmtClass()) {
227
0
  case Stmt::CompoundStmtClass:
228
0
    return visitCompoundStmt(cast<CompoundStmt>(S));
229
0
  case Stmt::DeclStmtClass:
230
0
    return visitDeclStmt(cast<DeclStmt>(S));
231
0
  case Stmt::ReturnStmtClass:
232
0
    return visitReturnStmt(cast<ReturnStmt>(S));
233
0
  case Stmt::IfStmtClass:
234
0
    return visitIfStmt(cast<IfStmt>(S));
235
0
  case Stmt::WhileStmtClass:
236
0
    return visitWhileStmt(cast<WhileStmt>(S));
237
0
  case Stmt::DoStmtClass:
238
0
    return visitDoStmt(cast<DoStmt>(S));
239
0
  case Stmt::ForStmtClass:
240
0
    return visitForStmt(cast<ForStmt>(S));
241
0
  case Stmt::CXXForRangeStmtClass:
242
0
    return visitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
243
0
  case Stmt::BreakStmtClass:
244
0
    return visitBreakStmt(cast<BreakStmt>(S));
245
0
  case Stmt::ContinueStmtClass:
246
0
    return visitContinueStmt(cast<ContinueStmt>(S));
247
0
  case Stmt::SwitchStmtClass:
248
0
    return visitSwitchStmt(cast<SwitchStmt>(S));
249
0
  case Stmt::CaseStmtClass:
250
0
    return visitCaseStmt(cast<CaseStmt>(S));
251
0
  case Stmt::DefaultStmtClass:
252
0
    return visitDefaultStmt(cast<DefaultStmt>(S));
253
0
  case Stmt::GCCAsmStmtClass:
254
0
  case Stmt::MSAsmStmtClass:
255
0
    return visitAsmStmt(cast<AsmStmt>(S));
256
0
  case Stmt::AttributedStmtClass:
257
0
    return visitAttributedStmt(cast<AttributedStmt>(S));
258
0
  case Stmt::CXXTryStmtClass:
259
0
    return visitCXXTryStmt(cast<CXXTryStmt>(S));
260
0
  case Stmt::NullStmtClass:
261
0
    return true;
262
0
  default: {
263
0
    if (auto *Exp = dyn_cast<Expr>(S))
264
0
      return this->discard(Exp);
265
0
    return this->bail(S);
266
0
  }
267
0
  }
268
0
}
269
270
/// Visits the given statment without creating a variable
271
/// scope for it in case it is a compound statement.
272
template <class Emitter>
273
0
bool ByteCodeStmtGen<Emitter>::visitLoopBody(const Stmt *S) {
274
0
  if (isa<NullStmt>(S))
275
0
    return true;
276
277
0
  if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
278
0
    for (auto *InnerStmt : CS->body())
279
0
      if (!visitStmt(InnerStmt))
280
0
        return false;
281
0
    return true;
282
0
  }
283
284
0
  return this->visitStmt(S);
285
0
}
286
287
template <class Emitter>
288
bool ByteCodeStmtGen<Emitter>::visitCompoundStmt(
289
0
    const CompoundStmt *CompoundStmt) {
290
0
  BlockScope<Emitter> Scope(this);
291
0
  for (auto *InnerStmt : CompoundStmt->body())
292
0
    if (!visitStmt(InnerStmt))
293
0
      return false;
294
0
  return true;
295
0
}
296
297
template <class Emitter>
298
0
bool ByteCodeStmtGen<Emitter>::visitDeclStmt(const DeclStmt *DS) {
299
0
  for (auto *D : DS->decls()) {
300
0
    if (isa<StaticAssertDecl, TagDecl, TypedefNameDecl>(D))
301
0
      continue;
302
303
0
    const auto *VD = dyn_cast<VarDecl>(D);
304
0
    if (!VD)
305
0
      return false;
306
0
    if (!this->visitVarDecl(VD))
307
0
      return false;
308
0
  }
309
310
0
  return true;
311
0
}
312
313
template <class Emitter>
314
0
bool ByteCodeStmtGen<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
315
0
  if (const Expr *RE = RS->getRetValue()) {
316
0
    ExprScope<Emitter> RetScope(this);
317
0
    if (ReturnType) {
318
      // Primitive types are simply returned.
319
0
      if (!this->visit(RE))
320
0
        return false;
321
0
      this->emitCleanup();
322
0
      return this->emitRet(*ReturnType, RS);
323
0
    } else if (RE->getType()->isVoidType()) {
324
0
      if (!this->visit(RE))
325
0
        return false;
326
0
    } else {
327
      // RVO - construct the value in the return location.
328
0
      if (!this->emitRVOPtr(RE))
329
0
        return false;
330
0
      if (!this->visitInitializer(RE))
331
0
        return false;
332
0
      if (!this->emitPopPtr(RE))
333
0
        return false;
334
335
0
      this->emitCleanup();
336
0
      return this->emitRetVoid(RS);
337
0
    }
338
0
  }
339
340
  // Void return.
341
0
  this->emitCleanup();
342
0
  return this->emitRetVoid(RS);
343
0
}
344
345
template <class Emitter>
346
0
bool ByteCodeStmtGen<Emitter>::visitIfStmt(const IfStmt *IS) {
347
0
  BlockScope<Emitter> IfScope(this);
348
349
0
  if (IS->isNonNegatedConsteval())
350
0
    return visitStmt(IS->getThen());
351
0
  if (IS->isNegatedConsteval())
352
0
    return IS->getElse() ? visitStmt(IS->getElse()) : true;
353
354
0
  if (auto *CondInit = IS->getInit())
355
0
    if (!visitStmt(CondInit))
356
0
      return false;
357
358
0
  if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt())
359
0
    if (!visitDeclStmt(CondDecl))
360
0
      return false;
361
362
0
  if (!this->visitBool(IS->getCond()))
363
0
    return false;
364
365
0
  if (const Stmt *Else = IS->getElse()) {
366
0
    LabelTy LabelElse = this->getLabel();
367
0
    LabelTy LabelEnd = this->getLabel();
368
0
    if (!this->jumpFalse(LabelElse))
369
0
      return false;
370
0
    if (!visitStmt(IS->getThen()))
371
0
      return false;
372
0
    if (!this->jump(LabelEnd))
373
0
      return false;
374
0
    this->emitLabel(LabelElse);
375
0
    if (!visitStmt(Else))
376
0
      return false;
377
0
    this->emitLabel(LabelEnd);
378
0
  } else {
379
0
    LabelTy LabelEnd = this->getLabel();
380
0
    if (!this->jumpFalse(LabelEnd))
381
0
      return false;
382
0
    if (!visitStmt(IS->getThen()))
383
0
      return false;
384
0
    this->emitLabel(LabelEnd);
385
0
  }
386
387
0
  return true;
388
0
}
389
390
template <class Emitter>
391
0
bool ByteCodeStmtGen<Emitter>::visitWhileStmt(const WhileStmt *S) {
392
0
  const Expr *Cond = S->getCond();
393
0
  const Stmt *Body = S->getBody();
394
395
0
  LabelTy CondLabel = this->getLabel(); // Label before the condition.
396
0
  LabelTy EndLabel = this->getLabel();  // Label after the loop.
397
0
  LoopScope<Emitter> LS(this, EndLabel, CondLabel);
398
399
0
  this->emitLabel(CondLabel);
400
0
  if (!this->visitBool(Cond))
401
0
    return false;
402
0
  if (!this->jumpFalse(EndLabel))
403
0
    return false;
404
405
0
  LocalScope<Emitter> Scope(this);
406
0
  {
407
0
    DestructorScope<Emitter> DS(Scope);
408
0
    if (!this->visitLoopBody(Body))
409
0
      return false;
410
0
  }
411
412
0
  if (!this->jump(CondLabel))
413
0
    return false;
414
0
  this->emitLabel(EndLabel);
415
416
0
  return true;
417
0
}
418
419
template <class Emitter>
420
0
bool ByteCodeStmtGen<Emitter>::visitDoStmt(const DoStmt *S) {
421
0
  const Expr *Cond = S->getCond();
422
0
  const Stmt *Body = S->getBody();
423
424
0
  LabelTy StartLabel = this->getLabel();
425
0
  LabelTy EndLabel = this->getLabel();
426
0
  LabelTy CondLabel = this->getLabel();
427
0
  LoopScope<Emitter> LS(this, EndLabel, CondLabel);
428
0
  LocalScope<Emitter> Scope(this);
429
430
0
  this->emitLabel(StartLabel);
431
0
  {
432
0
    DestructorScope<Emitter> DS(Scope);
433
434
0
    if (!this->visitLoopBody(Body))
435
0
      return false;
436
0
    this->emitLabel(CondLabel);
437
0
    if (!this->visitBool(Cond))
438
0
      return false;
439
0
  }
440
0
  if (!this->jumpTrue(StartLabel))
441
0
    return false;
442
443
0
  this->emitLabel(EndLabel);
444
0
  return true;
445
0
}
446
447
template <class Emitter>
448
0
bool ByteCodeStmtGen<Emitter>::visitForStmt(const ForStmt *S) {
449
  // for (Init; Cond; Inc) { Body }
450
0
  const Stmt *Init = S->getInit();
451
0
  const Expr *Cond = S->getCond();
452
0
  const Expr *Inc = S->getInc();
453
0
  const Stmt *Body = S->getBody();
454
455
0
  LabelTy EndLabel = this->getLabel();
456
0
  LabelTy CondLabel = this->getLabel();
457
0
  LabelTy IncLabel = this->getLabel();
458
0
  LoopScope<Emitter> LS(this, EndLabel, IncLabel);
459
0
  LocalScope<Emitter> Scope(this);
460
461
0
  if (Init && !this->visitStmt(Init))
462
0
    return false;
463
0
  this->emitLabel(CondLabel);
464
0
  if (Cond) {
465
0
    if (!this->visitBool(Cond))
466
0
      return false;
467
0
    if (!this->jumpFalse(EndLabel))
468
0
      return false;
469
0
  }
470
471
0
  {
472
0
    DestructorScope<Emitter> DS(Scope);
473
474
0
    if (Body && !this->visitLoopBody(Body))
475
0
      return false;
476
0
    this->emitLabel(IncLabel);
477
0
    if (Inc && !this->discard(Inc))
478
0
      return false;
479
0
  }
480
481
0
  if (!this->jump(CondLabel))
482
0
    return false;
483
0
  this->emitLabel(EndLabel);
484
0
  return true;
485
0
}
486
487
template <class Emitter>
488
0
bool ByteCodeStmtGen<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
489
0
  const Stmt *Init = S->getInit();
490
0
  const Expr *Cond = S->getCond();
491
0
  const Expr *Inc = S->getInc();
492
0
  const Stmt *Body = S->getBody();
493
0
  const Stmt *BeginStmt = S->getBeginStmt();
494
0
  const Stmt *RangeStmt = S->getRangeStmt();
495
0
  const Stmt *EndStmt = S->getEndStmt();
496
0
  const VarDecl *LoopVar = S->getLoopVariable();
497
498
0
  LabelTy EndLabel = this->getLabel();
499
0
  LabelTy CondLabel = this->getLabel();
500
0
  LabelTy IncLabel = this->getLabel();
501
0
  LoopScope<Emitter> LS(this, EndLabel, IncLabel);
502
503
  // Emit declarations needed in the loop.
504
0
  if (Init && !this->visitStmt(Init))
505
0
    return false;
506
0
  if (!this->visitStmt(RangeStmt))
507
0
    return false;
508
0
  if (!this->visitStmt(BeginStmt))
509
0
    return false;
510
0
  if (!this->visitStmt(EndStmt))
511
0
    return false;
512
513
  // Now the condition as well as the loop variable assignment.
514
0
  this->emitLabel(CondLabel);
515
0
  if (!this->visitBool(Cond))
516
0
    return false;
517
0
  if (!this->jumpFalse(EndLabel))
518
0
    return false;
519
520
0
  if (!this->visitVarDecl(LoopVar))
521
0
    return false;
522
523
  // Body.
524
0
  LocalScope<Emitter> Scope(this);
525
0
  {
526
0
    DestructorScope<Emitter> DS(Scope);
527
528
0
    if (!this->visitLoopBody(Body))
529
0
      return false;
530
0
    this->emitLabel(IncLabel);
531
0
    if (!this->discard(Inc))
532
0
      return false;
533
0
  }
534
0
  if (!this->jump(CondLabel))
535
0
    return false;
536
537
0
  this->emitLabel(EndLabel);
538
0
  return true;
539
0
}
540
541
template <class Emitter>
542
0
bool ByteCodeStmtGen<Emitter>::visitBreakStmt(const BreakStmt *S) {
543
0
  if (!BreakLabel)
544
0
    return false;
545
546
0
  this->VarScope->emitDestructors();
547
0
  return this->jump(*BreakLabel);
548
0
}
549
550
template <class Emitter>
551
0
bool ByteCodeStmtGen<Emitter>::visitContinueStmt(const ContinueStmt *S) {
552
0
  if (!ContinueLabel)
553
0
    return false;
554
555
0
  this->VarScope->emitDestructors();
556
0
  return this->jump(*ContinueLabel);
557
0
}
558
559
template <class Emitter>
560
0
bool ByteCodeStmtGen<Emitter>::visitSwitchStmt(const SwitchStmt *S) {
561
0
  const Expr *Cond = S->getCond();
562
0
  PrimType CondT = this->classifyPrim(Cond->getType());
563
564
0
  LabelTy EndLabel = this->getLabel();
565
0
  OptLabelTy DefaultLabel = std::nullopt;
566
0
  unsigned CondVar = this->allocateLocalPrimitive(Cond, CondT, true, false);
567
568
0
  if (const auto *CondInit = S->getInit())
569
0
    if (!visitStmt(CondInit))
570
0
      return false;
571
572
  // Initialize condition variable.
573
0
  if (!this->visit(Cond))
574
0
    return false;
575
0
  if (!this->emitSetLocal(CondT, CondVar, S))
576
0
    return false;
577
578
0
  CaseMap CaseLabels;
579
  // Create labels and comparison ops for all case statements.
580
0
  for (const SwitchCase *SC = S->getSwitchCaseList(); SC;
581
0
       SC = SC->getNextSwitchCase()) {
582
0
    if (const auto *CS = dyn_cast<CaseStmt>(SC)) {
583
      // FIXME: Implement ranges.
584
0
      if (CS->caseStmtIsGNURange())
585
0
        return false;
586
0
      CaseLabels[SC] = this->getLabel();
587
588
0
      const Expr *Value = CS->getLHS();
589
0
      PrimType ValueT = this->classifyPrim(Value->getType());
590
591
      // Compare the case statement's value to the switch condition.
592
0
      if (!this->emitGetLocal(CondT, CondVar, CS))
593
0
        return false;
594
0
      if (!this->visit(Value))
595
0
        return false;
596
597
      // Compare and jump to the case label.
598
0
      if (!this->emitEQ(ValueT, S))
599
0
        return false;
600
0
      if (!this->jumpTrue(CaseLabels[CS]))
601
0
        return false;
602
0
    } else {
603
0
      assert(!DefaultLabel);
604
0
      DefaultLabel = this->getLabel();
605
0
    }
606
0
  }
607
608
  // If none of the conditions above were true, fall through to the default
609
  // statement or jump after the switch statement.
610
0
  if (DefaultLabel) {
611
0
    if (!this->jump(*DefaultLabel))
612
0
      return false;
613
0
  } else {
614
0
    if (!this->jump(EndLabel))
615
0
      return false;
616
0
  }
617
618
0
  SwitchScope<Emitter> SS(this, std::move(CaseLabels), EndLabel, DefaultLabel);
619
0
  if (!this->visitStmt(S->getBody()))
620
0
    return false;
621
0
  this->emitLabel(EndLabel);
622
0
  return true;
623
0
}
624
625
template <class Emitter>
626
0
bool ByteCodeStmtGen<Emitter>::visitCaseStmt(const CaseStmt *S) {
627
0
  this->emitLabel(CaseLabels[S]);
628
0
  return this->visitStmt(S->getSubStmt());
629
0
}
630
631
template <class Emitter>
632
0
bool ByteCodeStmtGen<Emitter>::visitDefaultStmt(const DefaultStmt *S) {
633
0
  this->emitLabel(*DefaultLabel);
634
0
  return this->visitStmt(S->getSubStmt());
635
0
}
636
637
template <class Emitter>
638
0
bool ByteCodeStmtGen<Emitter>::visitAsmStmt(const AsmStmt *S) {
639
0
  return this->emitInvalid(S);
640
0
}
641
642
template <class Emitter>
643
0
bool ByteCodeStmtGen<Emitter>::visitAttributedStmt(const AttributedStmt *S) {
644
  // Ignore all attributes.
645
0
  return this->visitStmt(S->getSubStmt());
646
0
}
647
648
template <class Emitter>
649
0
bool ByteCodeStmtGen<Emitter>::visitCXXTryStmt(const CXXTryStmt *S) {
650
  // Ignore all handlers.
651
0
  return this->visitStmt(S->getTryBlock());
652
0
}
653
654
namespace clang {
655
namespace interp {
656
657
template class ByteCodeStmtGen<ByteCodeEmitter>;
658
659
} // namespace interp
660
} // namespace clang