bool VisitSwitchStmt(SwitchStmt *switchStmt) { CompoundStmt *compoundStmt = dyn_cast_or_null<CompoundStmt>(switchStmt->getBody()); if (compoundStmt) { bool breakFound = true; for (CompoundStmt::body_iterator body = compoundStmt->body_begin(), bodyEnd = compoundStmt->body_end(); body != bodyEnd; body++) { Stmt *bodyStmt = dyn_cast<Stmt>(*body); if (isBreakingPoint(bodyStmt)) { breakFound = true; continue; } if (isSwitchCase(bodyStmt)) { if (!breakFound) { addViolation(switchStmt, this); break; } FindingBreak findingBreak; breakFound = findingBreak.findBreak(dyn_cast<SwitchCase>(bodyStmt)); } } if (!breakFound) { addViolation(switchStmt, this); } } return true; }
Stmt *TransformVector::VisitDoStmt(DoStmt *Node) { // Body Stmt *Body = Node->getBody(); CompoundStmt *CS = dyn_cast<CompoundStmt>(Body); if (!CS) { // Convert a single stmt Body into a compound stmt. SourceLocation loc; CS = new (ASTCtx) CompoundStmt(ASTCtx, &Body, 1, loc, loc); } Node->setBody(TransformStmt(CS)); // Cond Expr *Cond = Node->getCond(); if (Cond->getType()->isVectorType()) { DeclVector DeclVec; Node->setCond(ConvertVecLiteralInExpr(DeclVec, Cond)); if (DeclVec.size() > 0) { CS = dyn_cast<CompoundStmt>(Node->getBody()); StmtVector StmtVec; CompoundStmt::body_iterator I, E; for (I = CS->body_begin(), E = CS->body_end(); I != E; ++I) { StmtVec.push_back(*I); } PushBackDeclStmts(StmtVec, DeclVec); CS->setStmts(ASTCtx, StmtVec.data(), StmtVec.size()); } } else { Node->setCond(TransformExpr(Cond)); } return Node; }
void UnreachableCodeRule::apply( CXCursor& node, CXCursor& parentNode, ViolationSet& violationSet) { Stmt *stmt = CursorHelper::getStmt(node); if (stmt) { CompoundStmt *compoundStmt = dyn_cast<CompoundStmt>(stmt); if (compoundStmt) { bool hasBreakPoint = false; for (CompoundStmt::body_iterator body = compoundStmt->body_begin(), bodyEnd = compoundStmt->body_end(); body != bodyEnd; body++) { if (hasBreakPoint) { Violation violation(node, this); violationSet.addViolation(violation); return; } else { Stmt *bodyStmt = (Stmt *)*body; hasBreakPoint = isBreakPoint(bodyStmt, parentNode); } } } } }
/// EmitCompoundStmt - Emit a compound statement {..} node. If GetLast is true, /// this captures the expression result of the last sub-statement and returns it /// (for use by the statement expression extension). RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, llvm::Value *AggLoc, bool isAggVol) { PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),S.getLBracLoc(), "LLVM IR generation of compound statement ('{}')"); CGDebugInfo *DI = getDebugInfo(); if (DI) { EnsureInsertPoint(); DI->setLocation(S.getLBracLoc()); // FIXME: The llvm backend is currently not ready to deal with region_end // for block scoping. In the presence of always_inline functions it gets so // confused that it doesn't emit any debug info. Just disable this for now. //DI->EmitRegionStart(CurFn, Builder); } // Keep track of the current cleanup stack depth. size_t CleanupStackDepth = CleanupEntries.size(); bool OldDidCallStackSave = DidCallStackSave; DidCallStackSave = false; for (CompoundStmt::const_body_iterator I = S.body_begin(), E = S.body_end()-GetLast; I != E; ++I) EmitStmt(*I); if (DI) { EnsureInsertPoint(); DI->setLocation(S.getRBracLoc()); // FIXME: The llvm backend is currently not ready to deal with region_end // for block scoping. In the presence of always_inline functions it gets so // confused that it doesn't emit any debug info. Just disable this for now. //DI->EmitRegionEnd(CurFn, Builder); } RValue RV; if (!GetLast) RV = RValue::get(0); else { // We have to special case labels here. They are statements, but when put // at the end of a statement expression, they yield the value of their // subexpression. Handle this by walking through all labels we encounter, // emitting them before we evaluate the subexpr. const Stmt *LastStmt = S.body_back(); while (const LabelStmt *LS = dyn_cast<LabelStmt>(LastStmt)) { EmitLabel(*LS); LastStmt = LS->getSubStmt(); } EnsureInsertPoint(); RV = EmitAnyExpr(cast<Expr>(LastStmt), AggLoc); } DidCallStackSave = OldDidCallStackSave; EmitCleanupBlocks(CleanupStackDepth); return RV; }
NamedDecl* RedundantLocalVariableRule::extractFromDeclStmt(Stmt *stmt) { CompoundStmt *compoundStmt = dyn_cast<CompoundStmt>(stmt); if (compoundStmt && compoundStmt->size() >= 2) { Stmt *lastSecondStmt = (Stmt *)*(compoundStmt->body_end() - 2); DeclStmt *declStmt = dyn_cast<DeclStmt>(lastSecondStmt); if (declStmt && declStmt->isSingleDecl()) { return dyn_cast<NamedDecl>(declStmt->getSingleDecl()); } } return NULL; }
bool RNFStatementVisitor::VisitStmtExpr(StmtExpr *SE) { CompoundStmt *CS = SE->getSubStmt(); if (ConsumerInstance->CallExprQueue.empty()) { TraverseStmt(CS); return false; } CallExpr *CallE = ConsumerInstance->CallExprQueue.back(); CurrentStmt = CallE; for (clang::CompoundStmt::body_iterator I = CS->body_begin(), E = CS->body_end(); I != E; ++I) { TraverseStmt(*I); } return false; }
int NPathComplexityMetric::nPath(SwitchStmt *stmt) { int internalNPath = 0, nPathSwitchStmt = nPath(stmt->getCond()); CompoundStmt *body = (CompoundStmt *)stmt->getBody(); for (CompoundStmt::body_iterator bodyStmt = body->body_begin(), bodyStmtEnd = body->body_end(); bodyStmt != bodyStmtEnd; bodyStmt++) { if (isa<SwitchCase>(*bodyStmt)) { SwitchCase *switchCase = dyn_cast<SwitchCase>(*bodyStmt); nPathSwitchStmt += internalNPath; internalNPath = nPath(switchCase->getSubStmt()); } else { internalNPath *= nPath(*bodyStmt); } } return nPathSwitchStmt + internalNPath; }
bool DeclExtractor::ExtractDecl(FunctionDecl* FD) { llvm::SmallVector<NamedDecl*, 4> TouchedDecls; CompoundStmt* CS = dyn_cast<CompoundStmt>(FD->getBody()); assert(CS && "Function body not a CompoundStmt?"); DeclContext* DC = FD->getTranslationUnitDecl(); Scope* TUScope = m_Sema->TUScope; assert(TUScope == m_Sema->getScopeForContext(DC) && "TU scope from DC?"); llvm::SmallVector<Stmt*, 4> Stmts; for (CompoundStmt::body_iterator I = CS->body_begin(), EI = CS->body_end(); I != EI; ++I) { DeclStmt* DS = dyn_cast<DeclStmt>(*I); if (!DS) { Stmts.push_back(*I); continue; } for (DeclStmt::decl_iterator J = DS->decl_begin(); J != DS->decl_end(); ++J) { NamedDecl* ND = dyn_cast<NamedDecl>(*J); if (isa<UsingDirectiveDecl>(*J)) continue; // FIXME: Here we should be more elegant. if (ND) { if (Stmts.size()) { // We need to emit a new custom wrapper wrapping the stmts EnforceInitOrder(Stmts); assert(!Stmts.size() && "Stmt list must be flushed."); } // We know the transaction is closed, but it is safe. getTransaction()->forceAppend(ND); DeclContext* OldDC = ND->getDeclContext(); // Make sure the decl is not found at its old possition ND->getLexicalDeclContext()->removeDecl(ND); if (Scope* S = m_Sema->getScopeForContext(OldDC)) { S->RemoveDecl(ND); if (utils::Analyze::isOnScopeChains(ND, *m_Sema)) m_Sema->IdResolver.RemoveDecl(ND); } // For variable definitions causing var/function ambiguity such as: // MyClass my();, C++ standard says it shall be resolved as a function // // In the particular context this definition is inside a function // already, but clang thinks it as a lambda, so we need to ignore the // check decl context vs lexical decl context. if (ND->getDeclContext() == ND->getLexicalDeclContext() || isa<FunctionDecl>(ND)) ND->setLexicalDeclContext(DC); else assert(0 && "Not implemented: Decl with different lexical context"); ND->setDeclContext(DC); if (VarDecl* VD = dyn_cast<VarDecl>(ND)) { VD->setStorageClass(SC_None); } clearLinkage(ND); TouchedDecls.push_back(ND); } } } bool hasNoErrors = !CheckForClashingNames(TouchedDecls, DC, TUScope); if (hasNoErrors) { for (size_t i = 0; i < TouchedDecls.size(); ++i) { // We should skip the checks for annonymous decls and we should not // register them in the lookup. if (!TouchedDecls[i]->getDeclName()) continue; m_Sema->PushOnScopeChains(TouchedDecls[i], m_Sema->getScopeForContext(DC), /*AddCurContext*/!isa<UsingDirectiveDecl>(TouchedDecls[i])); // The transparent DeclContexts (eg. scopeless enum) doesn't have // scopes. While extracting their contents we need to update the // lookup tables and telling them to pick up the new possitions // in the AST. if (DeclContext* InnerDC = dyn_cast<DeclContext>(TouchedDecls[i])) { if (InnerDC->isTransparentContext()) { // We can't PushDeclContext, because we don't have scope. Sema::ContextRAII pushedDC(*m_Sema, InnerDC); for(DeclContext::decl_iterator DI = InnerDC->decls_begin(), DE = InnerDC->decls_end(); DI != DE ; ++DI) { if (NamedDecl* ND = dyn_cast<NamedDecl>(*DI)) InnerDC->makeDeclVisibleInContext(ND); } } } } } CS->setStmts(*m_Context, Stmts.data(), Stmts.size()); // The order matters, because when we extract decls from the wrapper we // append them to the transaction. If the transaction gets unloaded it will // introduce a fake dependency, so put the move last. Transaction* T = getTransaction(); for (Transaction::iterator I = T->decls_begin(), E = T->decls_end(); I != E; ++I) if (!I->m_DGR.isNull() && I->m_DGR.isSingleDecl() && I->m_DGR.getSingleDecl() == T->getWrapperFD()) { T->erase(I); break; } T->forceAppend(FD); // Put the wrapper after its declarations. (Nice when AST dumping) DC->removeDecl(FD); DC->addDecl(FD); return hasNoErrors; }
Stmt *TransformVector::VisitSwitchStmt(SwitchStmt *Node) { DeclVector DeclVec; // Cond Expr *Cond = Node->getCond(); if (Cond->getType()->isVectorType()) { Node->setCond(ConvertVecLiteralInExpr(DeclVec, Cond)); } else { Node->setCond(TransformExpr(Cond)); } // Body Stmt *Body = Node->getBody(); CompoundStmt *CS = dyn_cast<CompoundStmt>(Body); if (!CS) { // Convert a single stmt body into a CompoundStmt. SourceLocation loc; CS = new (ASTCtx) CompoundStmt(ASTCtx, &Body, 1, loc, loc); } // Check all SwitchCase stmts themselves. SwitchCase *CurCase = Node->getSwitchCaseList(); while (CurCase) { if (CaseStmt *CaseS = dyn_cast<CaseStmt>(CurCase)) { Expr *CaseLHS = CaseS->getLHS(); if (CaseLHS->getType()->isVectorType()) { CaseS->setLHS(ConvertVecLiteralInExpr(DeclVec, CaseLHS)); } else { CaseS->setLHS(TransformExpr(CaseLHS)); } Expr *CaseRHS = CaseS->getRHS(); if (CaseRHS && CaseRHS->getType()->isVectorType()) { CaseS->setRHS(ConvertVecLiteralInExpr(DeclVec, CaseRHS)); } else { CaseS->setRHS(TransformExpr(CaseRHS)); } } CurCase = CurCase->getNextSwitchCase(); } // Check if there was a vector literal code motion. if (DeclVec.size() > 0) { PushBackDeclStmts(*CurStmtVec, DeclVec); } // If case stmts are not CompoundStmts, convert them into CompoundStmts StmtVector BodyStmts; CompoundStmt::body_iterator I, E; for (I = CS->body_begin(), E = CS->body_end(); I != E; ++I) { // Save the current stmt BodyStmts.push_back(*I); if (SwitchCase *SC = dyn_cast<SwitchCase>(*I)) { CompoundStmt::body_iterator NextI = I + 1; if (NextI == E) break; if (isa<SwitchCase>(*NextI)) { // No stmt between current case stmt and next case stmt. if (Stmt *SubStmt = SC->getSubStmt()) { if (!isa<CompoundStmt>(SubStmt)) { SourceLocation loc; CompoundStmt *SubCS = new (ASTCtx) CompoundStmt(ASTCtx, &SubStmt, 1, loc, loc); if (CaseStmt *CaseS = dyn_cast<CaseStmt>(SC)) { CaseS->setSubStmt(SubCS); } else if (DefaultStmt *DefaultS = dyn_cast<DefaultStmt>(SC)) { DefaultS->setSubStmt(SubCS); } else { assert(0 && "What statement?"); } } } } else { StmtVector StmtVec; // SubStmt if (Stmt *SubStmt = SC->getSubStmt()) { StmtVec.push_back(SubStmt); } // Following stmts do { I = NextI; StmtVec.push_back(*I); } while ((++NextI != E) && !isa<SwitchCase>(*NextI)); // Convert all stmts into a CompoundStmt. SourceLocation loc; CompoundStmt *SubCS = new (ASTCtx) CompoundStmt(ASTCtx, StmtVec.data(), StmtVec.size(), loc, loc); if (CaseStmt *CaseS = dyn_cast<CaseStmt>(SC)) { CaseS->setSubStmt(SubCS); } else if (DefaultStmt *DefaultS = dyn_cast<DefaultStmt>(SC)) { DefaultS->setSubStmt(SubCS); } else { assert(0 && "What statement?"); } } } //end if } //end for CS = new (ASTCtx) CompoundStmt(ASTCtx, BodyStmts.data(), BodyStmts.size(), SourceLocation(), SourceLocation()); ASTCtx.Deallocate(Node->getBody()); Node->setBody(TransformStmt(CS)); return Node; }
bool DeclExtractor::ExtractDecl(Decl* D) { FunctionDecl* FD = dyn_cast<FunctionDecl>(D); if (FD) { if (FD->getNameAsString().find("__cling_Un1Qu3")) return true; llvm::SmallVector<NamedDecl*, 4> TouchedDecls; CompoundStmt* CS = dyn_cast<CompoundStmt>(FD->getBody()); assert(CS && "Function body not a CompoundStmt?"); DeclContext* DC = FD->getTranslationUnitDecl(); Scope* TUScope = m_Sema->TUScope; assert(TUScope == m_Sema->getScopeForContext(DC) && "TU scope from DC?"); llvm::SmallVector<Stmt*, 4> Stmts; for (CompoundStmt::body_iterator I = CS->body_begin(), EI = CS->body_end(); I != EI; ++I) { DeclStmt* DS = dyn_cast<DeclStmt>(*I); if (!DS) { Stmts.push_back(*I); continue; } for (DeclStmt::decl_iterator J = DS->decl_begin(); J != DS->decl_end(); ++J) { NamedDecl* ND = dyn_cast<NamedDecl>(*J); if (ND) { DeclContext* OldDC = ND->getDeclContext(); // Make sure the decl is not found at its old possition OldDC->removeDecl(ND); if (Scope* S = m_Sema->getScopeForContext(OldDC)) { S->RemoveDecl(ND); m_Sema->IdResolver.RemoveDecl(ND); } if (ND->getDeclContext() == ND->getLexicalDeclContext()) ND->setLexicalDeclContext(DC); else assert("Not implemented: Decl with different lexical context"); ND->setDeclContext(DC); if (VarDecl* VD = dyn_cast<VarDecl>(ND)) { VD->setStorageClass(SC_None); VD->setStorageClassAsWritten(SC_None); // if we want to print the result of the initializer of int i = 5 // or the default initializer int i if (I+1 == EI || !isa<NullStmt>(*(I+1))) { QualType VDTy = VD->getType().getNonReferenceType(); Expr* DRE = m_Sema->BuildDeclRefExpr(VD, VDTy,VK_LValue, SourceLocation() ).take(); Stmts.push_back(DRE); } } // force recalc of the linkage (to external) ND->ClearLinkageCache(); TouchedDecls.push_back(ND); } } } bool hasNoErrors = !CheckForClashingNames(TouchedDecls, DC, TUScope); if (hasNoErrors) { for (size_t i = 0; i < TouchedDecls.size(); ++i) { m_Sema->PushOnScopeChains(TouchedDecls[i], m_Sema->getScopeForContext(DC), /*AddCurContext*/!isa<UsingDirectiveDecl>(TouchedDecls[i])); // The transparent DeclContexts (eg. scopeless enum) doesn't have // scopes. While extracting their contents we need to update the // lookup tables and telling them to pick up the new possitions // in the AST. if (DeclContext* InnerDC = dyn_cast<DeclContext>(TouchedDecls[i])) { if (InnerDC->isTransparentContext()) { // We can't PushDeclContext, because we don't have scope. Sema::ContextRAII pushedDC(*m_Sema, InnerDC); for(DeclContext::decl_iterator DI = InnerDC->decls_begin(), DE = InnerDC->decls_end(); DI != DE ; ++DI) { if (NamedDecl* ND = dyn_cast<NamedDecl>(*DI)) InnerDC->makeDeclVisibleInContext(ND); } } } // Append the new top level decl to the current transaction. getTransaction()->appendUnique(DeclGroupRef(TouchedDecls[i])); } } CS->setStmts(*m_Context, Stmts.data(), Stmts.size()); // Put the wrapper after its declarations. (Nice when AST dumping) DC->removeDecl(FD); DC->addDecl(FD); return hasNoErrors; } return true; }