bool VisitStmt(Stmt *s) { // Fill out this function for your homework SourceLocation startLoc = s->getLocStart(); unsigned int lineNum = srcmgr.getExpansionLineNumber(startLoc); unsigned int colNum = srcmgr.getExpansionColumnNumber(startLoc); if (isa<IfStmt>(s)) { printBranchLineColFilename("If", lineNum, colNum, filename); } else if (isa<ForStmt>(s)) { printBranchLineColFilename("For", lineNum, colNum, filename); } else if (isa<WhileStmt>(s)) { printBranchLineColFilename("While", lineNum, colNum, filename); } else if (isa<CaseStmt>(s)) { printBranchLineColFilename("Case", lineNum, colNum, filename); } else if (isa<DoStmt>(s)) { printBranchLineColFilename("Do", lineNum, colNum, filename); } else if (isa<DefaultStmt>(s)) { printBranchLineColFilename("Default", lineNum, colNum, filename); } else if (isa<ConditionalOperator>(s)) { printBranchLineColFilename("?:", lineNum, colNum, filename); } else if (isa<SwitchStmt>(s)) { SwitchStmt *switchstmt = cast<SwitchStmt>(s); SwitchCase *branch = switchstmt->getSwitchCaseList(); bool hasDefault = false; for(; branch != NULL ; branch = branch->getNextSwitchCase()) { if (isa<DefaultStmt>(branch)) { hasDefault = true; break; } } if(!hasDefault) printBranchLineColFilename("ImpDef", lineNum, colNum, filename); } return true; }
/// VerifyJumps - Verify each element of the Jumps array to see if they are /// valid, emitting diagnostics if not. void JumpScopeChecker::VerifyJumps() { while (!Jumps.empty()) { Stmt *Jump = Jumps.pop_back_val(); // With a goto, if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) { CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(), diag::err_goto_into_protected_scope, diag::warn_goto_into_protected_scope, diag::warn_cxx98_compat_goto_into_protected_scope); continue; } // We only get indirect gotos here when they have a constant target. if (IndirectGotoStmt *IGS = dyn_cast<IndirectGotoStmt>(Jump)) { LabelDecl *Target = IGS->getConstantTarget(); CheckJump(IGS, Target->getStmt(), IGS->getGotoLoc(), diag::err_goto_into_protected_scope, diag::warn_goto_into_protected_scope, diag::warn_cxx98_compat_goto_into_protected_scope); continue; } SwitchStmt *SS = cast<SwitchStmt>(Jump); for (SwitchCase *SC = SS->getSwitchCaseList(); SC; SC = SC->getNextSwitchCase()) { assert(LabelAndGotoScopes.count(SC) && "Case not visited?"); CheckJump(SS, SC, SC->getLocStart(), diag::err_switch_into_protected_scope, 0, diag::warn_cxx98_compat_switch_into_protected_scope); } } }
void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) { llvm::Value *CondV = EmitScalarExpr(S.getCond()); // Handle nested switch statements. llvm::SwitchInst *SavedSwitchInsn = SwitchInsn; llvm::BasicBlock *SavedCRBlock = CaseRangeBlock; // Create basic block to hold stuff that comes after switch // statement. We also need to create a default block now so that // explicit case ranges tests can have a place to jump to on // failure. llvm::BasicBlock *NextBlock = createBasicBlock("sw.epilog"); llvm::BasicBlock *DefaultBlock = createBasicBlock("sw.default"); SwitchInsn = Builder.CreateSwitch(CondV, DefaultBlock); CaseRangeBlock = DefaultBlock; // Clear the insertion point to indicate we are in unreachable code. Builder.ClearInsertionPoint(); // All break statements jump to NextBlock. If BreakContinueStack is non empty // then reuse last ContinueBlock. llvm::BasicBlock *ContinueBlock = 0; if (!BreakContinueStack.empty()) ContinueBlock = BreakContinueStack.back().ContinueBlock; // Ensure any vlas created between there and here, are undone BreakContinueStack.push_back(BreakContinue(NextBlock, ContinueBlock)); // Emit switch body. EmitStmt(S.getBody()); BreakContinueStack.pop_back(); // Update the default block in case explicit case range tests have // been chained on top. SwitchInsn->setSuccessor(0, CaseRangeBlock); // If a default was never emitted then reroute any jumps to it and // discard. if (!DefaultBlock->getParent()) { DefaultBlock->replaceAllUsesWith(NextBlock); delete DefaultBlock; } // Emit continuation. EmitBlock(NextBlock, true); SwitchInsn = SavedSwitchInsn; CaseRangeBlock = SavedCRBlock; }
SwitchStmt *SwitchStmt::create(LabeledStmtInfo LabelInfo, SourceLoc SwitchLoc, Expr *SubjectExpr, SourceLoc LBraceLoc, ArrayRef<CaseStmt *> Cases, SourceLoc RBraceLoc, ASTContext &C) { void *p = C.Allocate(sizeof(SwitchStmt) + Cases.size() * sizeof(SwitchStmt*), alignof(SwitchStmt)); SwitchStmt *theSwitch = ::new (p) SwitchStmt(LabelInfo, SwitchLoc, SubjectExpr, LBraceLoc, Cases.size(), RBraceLoc); memcpy(theSwitch->getCaseBuffer(), Cases.data(), Cases.size() * sizeof(CaseStmt*)); return theSwitch; }
bool VisitStmt(Stmt *s) { // Fill out this function for your homework SourceManager &srcmgr = *m_srcmgr; SourceLocation startLoc = s->getLocStart(); unsigned int lineNum = srcmgr.getExpansionLineNumber(startLoc); unsigned int colNum = srcmgr.getExpansionColumnNumber(startLoc); /*string filename = srcmgr.getFilename(startLoc); if ((!filename.compare("")) || filename.com) { filename = prevFilename; } else { prevFilename = filename; }*/ if (isa<IfStmt>(s)) { printBranchLineColFilename("If", lineNum, colNum, filename); IfStmt *ifstmt = cast<IfStmt>(s); if(!ifstmt->getElse()) cout<<"this \"if\" has no else"<<endl; else ifstmt->getElse()->dumpColor(); } else if (isa<ForStmt>(s)) { printBranchLineColFilename("For", lineNum, colNum, filename); } else if (isa<WhileStmt>(s)) { printBranchLineColFilename("While", lineNum, colNum, filename); } else if (isa<CaseStmt>(s)) { printBranchLineColFilename("Case", lineNum, colNum, filename); } else if (isa<DoStmt>(s)) { //s->dump(); printBranchLineColFilename("Do", lineNum, colNum, filename); } else if (isa<DefaultStmt>(s)) { printBranchLineColFilename("Default", lineNum, colNum, filename); } else if (isa<ConditionalOperator>(s)) { printBranchLineColFilename("?:", lineNum, colNum, filename); } else if (isa<SwitchStmt>(s)) { SwitchStmt *switchstmt = cast<SwitchStmt>(s); SwitchCase *branch = switchstmt->getSwitchCaseList(); bool hasDefault = false; for(; branch != NULL ; branch = branch->getNextSwitchCase()) { if (isa<DefaultStmt>(branch)) { hasDefault = true; break; } } if(!hasDefault) printBranchLineColFilename("ImpDef", lineNum, colNum, filename); } return true; }
/// VerifyJumps - Verify each element of the Jumps array to see if they are /// valid, emitting diagnostics if not. void JumpScopeChecker::VerifyJumps() { while (!Jumps.empty()) { Stmt *Jump = Jumps.pop_back_val(); // With a goto, if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) { // The label may not have a statement if it's coming from inline MS ASM. if (GS->getLabel()->getStmt()) { CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(), diag::err_goto_into_protected_scope, diag::ext_goto_into_protected_scope, diag::warn_cxx98_compat_goto_into_protected_scope); } CheckGotoStmt(GS); continue; } // We only get indirect gotos here when they have a constant target. if (IndirectGotoStmt *IGS = dyn_cast<IndirectGotoStmt>(Jump)) { LabelDecl *Target = IGS->getConstantTarget(); CheckJump(IGS, Target->getStmt(), IGS->getGotoLoc(), diag::err_goto_into_protected_scope, diag::ext_goto_into_protected_scope, diag::warn_cxx98_compat_goto_into_protected_scope); continue; } SwitchStmt *SS = cast<SwitchStmt>(Jump); for (SwitchCase *SC = SS->getSwitchCaseList(); SC; SC = SC->getNextSwitchCase()) { if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(SC))) continue; SourceLocation Loc; if (CaseStmt *CS = dyn_cast<CaseStmt>(SC)) Loc = CS->getLocStart(); else if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SC)) Loc = DS->getLocStart(); else Loc = SC->getLocStart(); CheckJump(SS, SC, Loc, diag::err_switch_into_protected_scope, 0, diag::warn_cxx98_compat_switch_into_protected_scope); } } }
void InstantiationVisitor::visit(SwitchStmt& s) { std::vector<SwitchEntry> entries; for (auto& entry : s.entries()) { std::vector<SwitchLabel> labels; for (auto& label : entry.labels()) { if (label.expr()) labels.emplace_back(label.sloc(), clone(*label.expr())); else labels.emplace_back(label.sloc(), nullptr); } entries.emplace_back(std::move(labels), clone(entry.statement())); } _stmt.reset(new SwitchStmt(s.sloc(), clone(s.expr()), std::move(entries))); }