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