From 9abb59f9ccd7fd47f8eac71190bb7f2b2710d9a5 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Fri, 14 Mar 2008 18:14:50 +0000 Subject: [PATCH] Emit warnings for undefined control-flow. llvm-svn: 48368 --- clang/Analysis/GRExprEngine.cpp | 1 + clang/Analysis/GRSimpleVals.cpp | 39 +++++++++++++------ clang/Driver/ASTConsumers.cpp | 11 ++++-- .../Analysis/PathSensitive/GRExprEngine.h | 4 ++ 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/clang/Analysis/GRExprEngine.cpp b/clang/Analysis/GRExprEngine.cpp index b8892e3ee546..70cd1871bcca 100644 --- a/clang/Analysis/GRExprEngine.cpp +++ b/clang/Analysis/GRExprEngine.cpp @@ -1865,6 +1865,7 @@ void GRExprEngine::ViewGraph(bool trim) { AddSources(Src, undef_results_begin(), undef_results_end()); AddSources(Src, bad_calls_begin(), bad_calls_end()); AddSources(Src, undef_arg_begin(), undef_arg_end()); + AddSources(Src, undef_branches_begin(), undef_branches_end()); ViewGraph(&Src[0], &Src[0]+Src.size()); } diff --git a/clang/Analysis/GRSimpleVals.cpp b/clang/Analysis/GRSimpleVals.cpp index ee5a44c48ce5..44429336a54e 100644 --- a/clang/Analysis/GRSimpleVals.cpp +++ b/clang/Analysis/GRSimpleVals.cpp @@ -23,22 +23,33 @@ using namespace clang; namespace clang { template -static inline const PostStmt& GetLocation(ITERATOR I) { - return cast((*I)->getLocation()); +static inline ProgramPoint GetLocation(ITERATOR I) { + return (*I)->getLocation(); } template <> -inline const PostStmt& GetLocation(GRExprEngine::undef_arg_iterator I) { - return cast(I->first->getLocation()); +inline ProgramPoint GetLocation(GRExprEngine::undef_arg_iterator I) { + return I->first->getLocation(); +} + +static inline Stmt* GetStmt(const ProgramPoint& P) { + if (const PostStmt* PS = dyn_cast(&P)) { + return PS->getStmt(); + } + else if (const BlockEdge* BE = dyn_cast(&P)) { + return BE->getSrc()->getTerminator(); + } + + assert (false && "Unsupported ProgramPoint."); + return NULL; } template static void EmitDiag(Diagnostic& Diag, SourceManager& SrcMgr, unsigned ErrorDiag, ITERATOR I) { - Expr* Exp = cast(GetLocation(I).getStmt()); - cast(GetLocation(I).getStmt()); - Diag.Report(FullSourceLoc(Exp->getExprLoc(), SrcMgr), ErrorDiag); + Stmt* S = GetStmt(GetLocation(I)); + Diag.Report(FullSourceLoc(S->getLocStart(), SrcMgr), ErrorDiag); } @@ -46,10 +57,10 @@ template <> static void EmitDiag(Diagnostic& Diag, SourceManager& SrcMgr, unsigned ErrorDiag, GRExprEngine::undef_arg_iterator I) { - Expr* E1 = cast(GetLocation(I).getStmt()); + Stmt* S1 = GetStmt(GetLocation(I)); Expr* E2 = cast(I->second); - SourceLocation Loc = E1->getExprLoc(); + SourceLocation Loc = S1->getLocStart(); SourceRange R = E2->getSourceRange(); Diag.Report(FullSourceLoc(Loc, SrcMgr), ErrorDiag, 0, 0, &R, 1); } @@ -139,6 +150,11 @@ unsigned RunGRSimpleVals(CFG& cfg, Decl& CD, ASTContext& Ctx, CheckerState->undef_arg_begin(), CheckerState->undef_arg_end(), "Pass-by-value argument in function or message expression is undefined."); + + EmitWarning(Diag, SrcMgr, + CheckerState->undef_branches_begin(), + CheckerState->undef_branches_end(), + "Branch condition evaluates to an uninitialized value."); #ifndef NDEBUG if (Visualize) CheckerState->ViewGraph(TrimGraph); @@ -161,7 +177,8 @@ RVal GRSimpleVals::EvalCast(GRExprEngine& Eng, NonLVal X, QualType T) { BasicValueFactory& BasicVals = Eng.getBasicVals(); llvm::APSInt V = cast(X).getValue(); - V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType()); + V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType() + || T->isObjCQualifiedIdType()); V.extOrTrunc(Eng.getContext().getTypeSize(T)); if (T->isPointerType()) @@ -174,7 +191,7 @@ RVal GRSimpleVals::EvalCast(GRExprEngine& Eng, NonLVal X, QualType T) { RVal GRSimpleVals::EvalCast(GRExprEngine& Eng, LVal X, QualType T) { - if (T->isPointerType() || T->isReferenceType()) + if (T->isPointerType() || T->isReferenceType() || T->isObjCQualifiedIdType()) return X; assert (T->isIntegerType()); diff --git a/clang/Driver/ASTConsumers.cpp b/clang/Driver/ASTConsumers.cpp index 20fd18cd063c..e6a1ae4b70e1 100644 --- a/clang/Driver/ASTConsumers.cpp +++ b/clang/Driver/ASTConsumers.cpp @@ -505,6 +505,9 @@ void CFGVisitor::HandleTopLevelDecl(Decl *D) { if (!MD->getBody()) return; + + if (FName.size() > 0 && FName != MD->getSelector().getName()) + return; if (printFuncDeclStart()) { DeclPrinter().PrintObjCMethodDecl(MD); @@ -649,11 +652,11 @@ ASTConsumer* clang::CreateGRSimpleVals(Diagnostic &Diags, void GRSimpleValsVisitor::VisitCFG(CFG& C, Decl& CD) { SourceLocation Loc = CD.getLocation(); - + if (!Loc.isFileID() || Loc.getFileID() != Ctx->getSourceManager().getMainFileID()) return; - + if (!Visualize) { if (FunctionDecl *FD = dyn_cast(&CD)) { @@ -662,8 +665,8 @@ void GRSimpleValsVisitor::VisitCFG(CFG& C, Decl& CD) { << ' '; } else if (ObjCMethodDecl *MD = dyn_cast(&CD)) { - llvm::cerr << "ANALYZE (ObjC Method): " - << MD->getSelector().getName() << ' ' + llvm::cerr << "ANALYZE (ObjC Method): '" + << MD->getSelector().getName() << "' " << Ctx->getSourceManager().getSourceName(MD->getLocation()) << ' '; } diff --git a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h index 0c3aa847e6fd..4e50745e2225 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -204,6 +204,10 @@ public: UndefArgs.find(const_cast(N)) != UndefArgs.end(); } + typedef UndefBranchesTy::iterator undef_branch_iterator; + undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); } + undef_branch_iterator undef_branches_end() { return UndefBranches.end(); } + typedef BadDerefTy::iterator null_deref_iterator; null_deref_iterator null_derefs_begin() { return ExplicitNullDeref.begin(); } null_deref_iterator null_derefs_end() { return ExplicitNullDeref.end(); }