r290505 - Fix for PR15623 (corrected r290413 reverted at 290415). The patch eliminates unwanted ProgramState checker data propagation from an operand of the logical operation to operation result.
Author: ayartsev Date: Sat Dec 24 18:57:51 2016 New Revision: 290505 URL: http://llvm.org/viewvc/llvm-project?rev=290505=rev Log: Fix for PR15623 (corrected r290413 reverted at 290415). The patch eliminates unwanted ProgramState checker data propagation from an operand of the logical operation to operation result. The patch also simplifies an assume of a constraint of the form: "(exp comparison_op expr) != 0" to true into an assume of "exp comparison_op expr" to true. (And similarly, an assume of the form "(exp comparison_op expr) == 0" to true as an assume of exp comparison_op expr to false.) which improves precision overall. https://reviews.llvm.org/D22862 Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp cfe/trunk/test/Analysis/malloc.c cfe/trunk/test/Analysis/misc-ps.c Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=290505=290504=290505=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Sat Dec 24 18:57:51 2016 @@ -666,23 +666,13 @@ void ExprEngine::VisitLogicalExpr(const if (RHSVal.isUndef()) { X = RHSVal; } else { - DefinedOrUnknownSVal DefinedRHS = RHSVal.castAs(); - ProgramStateRef StTrue, StFalse; - std::tie(StTrue, StFalse) = N->getState()->assume(DefinedRHS); - if (StTrue) { -if (StFalse) { - // We can't constrain the value to 0 or 1. - // The best we can do is a cast. - X = getSValBuilder().evalCast(RHSVal, B->getType(), RHS->getType()); -} else { - // The value is known to be true. - X = getSValBuilder().makeIntVal(1, B->getType()); -} - } else { -// The value is known to be false. -assert(StFalse && "Infeasible path!"); -X = getSValBuilder().makeIntVal(0, B->getType()); - } + // We evaluate "RHSVal != 0" expression which result in 0 if the value is + // known to be false, 1 if the value is known to be true and a new symbol + // when the assumption is unknown. + nonloc::ConcreteInt Zero(getBasicVals().getValue(0, B->getType())); + X = evalBinOp(N->getState(), BO_NE, +svalBuilder.evalCast(RHSVal, B->getType(), RHS->getType()), +Zero, B->getType()); } } Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X)); Modified: cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp?rev=290505=290504=290505=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp Sat Dec 24 18:57:51 2016 @@ -254,6 +254,19 @@ ProgramStateRef SimpleConstraintManager: assert(BinaryOperator::isComparisonOp(Op) && "Non-comparison ops should be rewritten as comparisons to zero."); + SymbolRef Sym = LHS; + + // Simplification: translate an assume of a constraint of the form + // "(exp comparison_op expr) != 0" to true into an assume of + // "exp comparison_op expr" to true. (And similarly, an assume of the form + // "(exp comparison_op expr) == 0" to true into an assume of + // "exp comparison_op expr" to false.) + if (Int == 0 && (Op == BO_EQ || Op == BO_NE)) { +if (const BinarySymExpr *SE = dyn_cast(Sym)) + if (BinaryOperator::isComparisonOp(SE->getOpcode())) +return assume(State, nonloc::SymbolVal(Sym), (Op == BO_NE ? true : false)); + } + // Get the type used for calculating wraparound. BasicValueFactory = getBasicVals(); APSIntType WraparoundType = BVF.getAPSIntType(LHS->getType()); @@ -265,7 +278,6 @@ ProgramStateRef SimpleConstraintManager: // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to // the subclasses of SimpleConstraintManager to handle the adjustment. - SymbolRef Sym = LHS; llvm::APSInt Adjustment = WraparoundType.getZeroValue(); computeAdjustment(Sym, Adjustment); Modified: cfe/trunk/test/Analysis/malloc.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=290505=290504=290505=diff == --- cfe/trunk/test/Analysis/malloc.c (original) +++ cfe/trunk/test/Analysis/malloc.c Sat Dec 24 18:57:51 2016 @@ -1763,6 +1763,17 @@ void testConstEscapeThroughAnotherField( constEscape(&(s.x)); // could free s->p! } // no-warning +// PR15623 +int
r290415 - Revert changes made by r290413 until regression is fixed.
Author: ayartsev Date: Thu Dec 22 22:09:18 2016 New Revision: 290415 URL: http://llvm.org/viewvc/llvm-project?rev=290415=rev Log: Revert changes made by r290413 until regression is fixed. Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp cfe/trunk/test/Analysis/malloc.c cfe/trunk/test/Analysis/misc-ps.c Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=290415=290414=290415=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Thu Dec 22 22:09:18 2016 @@ -665,13 +665,23 @@ void ExprEngine::VisitLogicalExpr(const if (RHSVal.isUndef()) { X = RHSVal; } else { - // We evaluate "RHSVal != 0" expression which result in 0 if the value is - // known to be false, 1 if the value is known to be true and a new symbol - // when the assumption is unknown. - nonloc::ConcreteInt Zero(getBasicVals().getValue(0, B->getType())); - X = evalBinOp(N->getState(), BO_NE, -svalBuilder.evalCast(RHSVal, B->getType(), RHS->getType()), -Zero, B->getType()); + DefinedOrUnknownSVal DefinedRHS = RHSVal.castAs(); + ProgramStateRef StTrue, StFalse; + std::tie(StTrue, StFalse) = N->getState()->assume(DefinedRHS); + if (StTrue) { +if (StFalse) { + // We can't constrain the value to 0 or 1. + // The best we can do is a cast. + X = getSValBuilder().evalCast(RHSVal, B->getType(), RHS->getType()); +} else { + // The value is known to be true. + X = getSValBuilder().makeIntVal(1, B->getType()); +} + } else { +// The value is known to be false. +assert(StFalse && "Infeasible path!"); +X = getSValBuilder().makeIntVal(0, B->getType()); + } } } Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X)); Modified: cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp?rev=290415=290414=290415=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp Thu Dec 22 22:09:18 2016 @@ -254,21 +254,6 @@ ProgramStateRef SimpleConstraintManager: assert(BinaryOperator::isComparisonOp(Op) && "Non-comparison ops should be rewritten as comparisons to zero."); - SymbolRef Sym = LHS; - - // Simplification: translate an assume of a constraint of the form - // "(exp comparison_op expr) != 0" to true into an assume of - // "exp comparison_op expr" to true. (And similarly, an assume of the form - // "(exp comparison_op expr) == 0" to true into an assume of - // "exp comparison_op expr" to false.) - if (Int == 0 && (Op == BO_EQ || Op == BO_NE)) { -if (const BinarySymExpr *SE = dyn_cast(Sym)) { - BinaryOperator::Opcode Op = SE->getOpcode(); - if (BinaryOperator::isComparisonOp(Op)) -return assume(State, nonloc::SymbolVal(Sym), (Op == BO_NE ? true : false)); -} - } - // Get the type used for calculating wraparound. BasicValueFactory = getBasicVals(); APSIntType WraparoundType = BVF.getAPSIntType(LHS->getType()); @@ -280,6 +265,7 @@ ProgramStateRef SimpleConstraintManager: // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to // the subclasses of SimpleConstraintManager to handle the adjustment. + SymbolRef Sym = LHS; llvm::APSInt Adjustment = WraparoundType.getZeroValue(); computeAdjustment(Sym, Adjustment); Modified: cfe/trunk/test/Analysis/malloc.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=290415=290414=290415=diff == --- cfe/trunk/test/Analysis/malloc.c (original) +++ cfe/trunk/test/Analysis/malloc.c Thu Dec 22 22:09:18 2016 @@ -1763,17 +1763,6 @@ void testConstEscapeThroughAnotherField( constEscape(&(s.x)); // could free s->p! } // no-warning -// PR15623 -int testNoCheckerDataPropogationFromLogicalOpOperandToOpResult(void) { - char *param = malloc(10); - char *value = malloc(10); - int ok = (param && value); - free(param); - free(value); - // Previously we ended up with 'Use of memory after it is freed' on return. - return ok; // no warning -} - // // False negatives. Modified: cfe/trunk/test/Analysis/misc-ps.c URL:
r290413 - Fix for PR15623. The patch eliminates unwanted ProgramState checker data propagation from an operand of the logical operation to operation result.
Author: ayartsev Date: Thu Dec 22 21:31:00 2016 New Revision: 290413 URL: http://llvm.org/viewvc/llvm-project?rev=290413=rev Log: Fix for PR15623. The patch eliminates unwanted ProgramState checker data propagation from an operand of the logical operation to operation result. The patch also simplifies an assume of a constraint of the form: "(exp comparison_op expr) != 0" to true into an assume of "exp comparison_op expr" to true. (And similarly, an assume of the form "(exp comparison_op expr) == 0" to true as an assume of exp comparison_op expr to false.) which improves precision overall. https://reviews.llvm.org/D22862 Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp cfe/trunk/test/Analysis/malloc.c cfe/trunk/test/Analysis/misc-ps.c Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=290413=290412=290413=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Thu Dec 22 21:31:00 2016 @@ -665,23 +665,13 @@ void ExprEngine::VisitLogicalExpr(const if (RHSVal.isUndef()) { X = RHSVal; } else { - DefinedOrUnknownSVal DefinedRHS = RHSVal.castAs(); - ProgramStateRef StTrue, StFalse; - std::tie(StTrue, StFalse) = N->getState()->assume(DefinedRHS); - if (StTrue) { -if (StFalse) { - // We can't constrain the value to 0 or 1. - // The best we can do is a cast. - X = getSValBuilder().evalCast(RHSVal, B->getType(), RHS->getType()); -} else { - // The value is known to be true. - X = getSValBuilder().makeIntVal(1, B->getType()); -} - } else { -// The value is known to be false. -assert(StFalse && "Infeasible path!"); -X = getSValBuilder().makeIntVal(0, B->getType()); - } + // We evaluate "RHSVal != 0" expression which result in 0 if the value is + // known to be false, 1 if the value is known to be true and a new symbol + // when the assumption is unknown. + nonloc::ConcreteInt Zero(getBasicVals().getValue(0, B->getType())); + X = evalBinOp(N->getState(), BO_NE, +svalBuilder.evalCast(RHSVal, B->getType(), RHS->getType()), +Zero, B->getType()); } } Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X)); Modified: cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp?rev=290413=290412=290413=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp Thu Dec 22 21:31:00 2016 @@ -254,6 +254,21 @@ ProgramStateRef SimpleConstraintManager: assert(BinaryOperator::isComparisonOp(Op) && "Non-comparison ops should be rewritten as comparisons to zero."); + SymbolRef Sym = LHS; + + // Simplification: translate an assume of a constraint of the form + // "(exp comparison_op expr) != 0" to true into an assume of + // "exp comparison_op expr" to true. (And similarly, an assume of the form + // "(exp comparison_op expr) == 0" to true into an assume of + // "exp comparison_op expr" to false.) + if (Int == 0 && (Op == BO_EQ || Op == BO_NE)) { +if (const BinarySymExpr *SE = dyn_cast(Sym)) { + BinaryOperator::Opcode Op = SE->getOpcode(); + if (BinaryOperator::isComparisonOp(Op)) +return assume(State, nonloc::SymbolVal(Sym), (Op == BO_NE ? true : false)); +} + } + // Get the type used for calculating wraparound. BasicValueFactory = getBasicVals(); APSIntType WraparoundType = BVF.getAPSIntType(LHS->getType()); @@ -265,7 +280,6 @@ ProgramStateRef SimpleConstraintManager: // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to // the subclasses of SimpleConstraintManager to handle the adjustment. - SymbolRef Sym = LHS; llvm::APSInt Adjustment = WraparoundType.getZeroValue(); computeAdjustment(Sym, Adjustment); Modified: cfe/trunk/test/Analysis/malloc.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=290413=290412=290413=diff == --- cfe/trunk/test/Analysis/malloc.c (original) +++ cfe/trunk/test/Analysis/malloc.c Thu Dec 22 21:31:00 2016 @@ -1763,6 +1763,17 @@ void testConstEscapeThroughAnotherField( constEscape(&(s.x)); // could free s->p! } // no-warning +// PR15623 +int
[PATCH] D22862: [analyzer] Fix for PR15623: eliminate unwanted ProgramState checker data propagation.
ayartsev updated this revision to Diff 78810. ayartsev added a comment. The updated patch implements Devin's solution. Please review. https://reviews.llvm.org/D22862 Files: lib/StaticAnalyzer/Core/ExprEngineC.cpp lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp test/Analysis/unwanted-programstate-data-propagation.c Index: test/Analysis/unwanted-programstate-data-propagation.c === --- test/Analysis/unwanted-programstate-data-propagation.c +++ test/Analysis/unwanted-programstate-data-propagation.c @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection,unix.Malloc -verify %s + +// test for PR15623 +#include "Inputs/system-header-simulator.h" + +void clang_analyzer_eval(int); + +typedef __typeof(sizeof(int)) size_t; +void *malloc(size_t); +void free(void *); + +int test1(void) { + char *param = malloc(10); + char *value = malloc(10); + int ok = (param && value); + free(param); + free(value); + // Previously we ended up with 'Use of memory after it is freed' on return. + return ok; // no warning +} + +void test2(int n) { + if ((n == 0) != 0) { +clang_analyzer_eval(n == 0); // expected-warning{{TRUE}} + } +} Index: lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp === --- lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp +++ lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp @@ -250,6 +250,21 @@ assert(BinaryOperator::isComparisonOp(op) && "Non-comparison ops should be rewritten as comparisons to zero."); + SymbolRef Sym = LHS; + + // Simplification: translate an assume of a constraint of the form + // "(exp comparison_op expr) != 0" to true into an assume of + // "exp comparison_op expr" to true. (And similarly, an assume of the form + // "(exp comparison_op expr) == 0" to true into an assume of + // "exp comparison_op expr" to false.) + if (Int == 0 && (op == BO_EQ || op == BO_NE)) { +if (const BinarySymExpr *SE = dyn_cast(Sym)) { + BinaryOperator::Opcode Op = SE->getOpcode(); + if (BinaryOperator::isComparisonOp(Op)) +return assume(state, nonloc::SymbolVal(Sym), (op == BO_NE ? true : false)); +} + } + // Get the type used for calculating wraparound. BasicValueFactory = getBasicVals(); APSIntType WraparoundType = BVF.getAPSIntType(LHS->getType()); @@ -261,7 +276,6 @@ // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to // the subclasses of SimpleConstraintManager to handle the adjustment. - SymbolRef Sym = LHS; llvm::APSInt Adjustment = WraparoundType.getZeroValue(); computeAdjustment(Sym, Adjustment); Index: lib/StaticAnalyzer/Core/ExprEngineC.cpp === --- lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -618,23 +618,13 @@ if (RHSVal.isUndef()) { X = RHSVal; } else { - DefinedOrUnknownSVal DefinedRHS = RHSVal.castAs(); - ProgramStateRef StTrue, StFalse; - std::tie(StTrue, StFalse) = N->getState()->assume(DefinedRHS); - if (StTrue) { -if (StFalse) { - // We can't constrain the value to 0 or 1. - // The best we can do is a cast. - X = getSValBuilder().evalCast(RHSVal, B->getType(), RHS->getType()); -} else { - // The value is known to be true. - X = getSValBuilder().makeIntVal(1, B->getType()); -} - } else { -// The value is known to be false. -assert(StFalse && "Infeasible path!"); -X = getSValBuilder().makeIntVal(0, B->getType()); - } + // We evaluate "RHSVal != 0" expression which result in 0 if the value is + // known to be false, 1 if the value is known to be true and a new symbol + // when the assumption is unknown. + nonloc::ConcreteInt Zero(getBasicVals().getValue(0, B->getType())); + X = evalBinOp(N->getState(), BO_NE, +svalBuilder.evalCast(RHSVal, B->getType(), RHS->getType()), +Zero, B->getType()); } } Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X)); Index: test/Analysis/unwanted-programstate-data-propagation.c === --- test/Analysis/unwanted-programstate-data-propagation.c +++ test/Analysis/unwanted-programstate-data-propagation.c @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection,unix.Malloc -verify %s + +// test for PR15623 +#include "Inputs/system-header-simulator.h" + +void clang_analyzer_eval(int); + +typedef __typeof(sizeof(int)) size_t; +void *malloc(size_t); +void free(void *); + +int test1(void) { + char *param = malloc(10); + char *value = malloc(10); + int ok =
[PATCH] D22494: [analyzer] Explain why analyzer report is not generated (fix for PR12421).
ayartsev closed this revision. ayartsev added a comment. Closed by r283499. https://reviews.llvm.org/D22494 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r283499 - [analyzer] Add explanation why analyzer report is not generated (fix for PR12421).
Author: ayartsev Date: Thu Oct 6 16:42:21 2016 New Revision: 283499 URL: http://llvm.org/viewvc/llvm-project?rev=283499=rev Log: [analyzer] Add explanation why analyzer report is not generated (fix for PR12421). Currently if the path diagnostic consumer (e.g HTMLDiagnostics and PlistDiagnostics) do not support cross file diagnostics then the path diagnostic report is silently omitted in the case of cross file diagnostics. The patch adds a little verbosity to Clang in this case. The patch also adds help entry for the "--analyzer-output" driver option. Added: cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.c cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.h Modified: cfe/trunk/include/clang/Driver/Options.td cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp Modified: cfe/trunk/include/clang/Driver/Options.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=283499=283498=283499=diff == --- cfe/trunk/include/clang/Driver/Options.td (original) +++ cfe/trunk/include/clang/Driver/Options.td Thu Oct 6 16:42:21 2016 @@ -2005,7 +2005,8 @@ def _CLASSPATH : Separate<["--"], "CLASS def _all_warnings : Flag<["--"], "all-warnings">, Alias; def _analyze_auto : Flag<["--"], "analyze-auto">, Flags<[DriverOption]>; def _analyzer_no_default_checks : Flag<["--"], "analyzer-no-default-checks">, Flags<[DriverOption]>; -def _analyzer_output : JoinedOrSeparate<["--"], "analyzer-output">, Flags<[DriverOption]>; +def _analyzer_output : JoinedOrSeparate<["--"], "analyzer-output">, Flags<[DriverOption]>, + HelpText<"Static analyzer report output format (html|plist|plist-multi-file|plist-html|text).">; def _analyze : Flag<["--"], "analyze">, Flags<[DriverOption, CoreOption]>, HelpText<"Run the static analyzer">; def _assemble : Flag<["--"], "assemble">, Alias; Modified: cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp?rev=283499=283498=283499=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp Thu Oct 6 16:42:21 2016 @@ -211,6 +211,12 @@ void PathDiagnosticConsumer::HandlePathD const SourceManager = D->path.front()->getLocation().getManager(); SmallVector WorkList; WorkList.push_back(>path); +SmallString<128> buf; +llvm::raw_svector_ostream warning(buf); +warning << "warning: Path diagnostic report is not generated. Current " +<< "output format does not support diagnostics that cross file " +<< "boundaries. Refer to --analyzer-output for valid output " +<< "formats\n"; while (!WorkList.empty()) { const PathPieces = *WorkList.pop_back_val(); @@ -222,19 +228,25 @@ void PathDiagnosticConsumer::HandlePathD if (FID.isInvalid()) { FID = SMgr.getFileID(L); -} else if (SMgr.getFileID(L) != FID) - return; // FIXME: Emit a warning? +} else if (SMgr.getFileID(L) != FID) { + llvm::errs() << warning.str(); + return; +} // Check the source ranges. ArrayRef Ranges = piece->getRanges(); for (ArrayRef::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { SourceLocation L = SMgr.getExpansionLoc(I->getBegin()); - if (!L.isFileID() || SMgr.getFileID(L) != FID) -return; // FIXME: Emit a warning? + if (!L.isFileID() || SMgr.getFileID(L) != FID) { +llvm::errs() << warning.str(); +return; + } L = SMgr.getExpansionLoc(I->getEnd()); - if (!L.isFileID() || SMgr.getFileID(L) != FID) -return; // FIXME: Emit a warning? + if (!L.isFileID() || SMgr.getFileID(L) != FID) { +llvm::errs() << warning.str(); +return; + } } if (const PathDiagnosticCallPiece *call = Added: cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.c?rev=283499=auto == --- cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.c (added) +++ cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.c Thu Oct 6 16:42:21 2016 @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=html -o PR12421.html %s 2>&1 | FileCheck %s + +// Test for PR12421 +#include "diag-cross-file-boundaries.h" + +int main(){ + f(); + return 0; +} + +// CHECK: warning: Path diagnostic report
Re: [PATCH] D22494: [analyzer] Explain why analyzer report is not generated (fix for PR12421).
ayartsev updated this revision to Diff 71056. ayartsev added a comment. Updated the patch. Important change in Options.td was missing in the last patch + indentation fixed. Still Ok to commit? https://reviews.llvm.org/D22494 Files: include/clang/Driver/Options.td lib/StaticAnalyzer/Core/PathDiagnostic.cpp test/Analysis/diagnostics/diag-cross-file-boundaries.c test/Analysis/diagnostics/diag-cross-file-boundaries.h Index: test/Analysis/diagnostics/diag-cross-file-boundaries.h === --- test/Analysis/diagnostics/diag-cross-file-boundaries.h +++ test/Analysis/diagnostics/diag-cross-file-boundaries.h @@ -0,0 +1,4 @@ +static void f() { + int *p = 0; + *p = 1; // expected-warning{{Dereference of null pointer}} +} Index: test/Analysis/diagnostics/diag-cross-file-boundaries.c === --- test/Analysis/diagnostics/diag-cross-file-boundaries.c +++ test/Analysis/diagnostics/diag-cross-file-boundaries.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=html -o PR12421.html %s 2>&1 | FileCheck %s + +// Test for PR12421 +#include "diag-cross-file-boundaries.h" + +int main(){ + f(); + return 0; +} + +// CHECK: warning: Path diagnostic report is not generated. Index: lib/StaticAnalyzer/Core/PathDiagnostic.cpp === --- lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -211,6 +211,12 @@ const SourceManager = D->path.front()->getLocation().getManager(); SmallVector WorkList; WorkList.push_back(>path); +SmallString<128> buf; +llvm::raw_svector_ostream warning(buf); +warning << "warning: Path diagnostic report is not generated. Current " +<< "output format does not support diagnostics that cross file " +<< "boundaries. Refer to --analyzer-output for valid output " +<< "formats\n"; while (!WorkList.empty()) { const PathPieces = *WorkList.pop_back_val(); @@ -222,19 +228,25 @@ if (FID.isInvalid()) { FID = SMgr.getFileID(L); -} else if (SMgr.getFileID(L) != FID) - return; // FIXME: Emit a warning? +} else if (SMgr.getFileID(L) != FID) { + llvm::errs() << warning.str(); + return; +} // Check the source ranges. ArrayRef Ranges = piece->getRanges(); for (ArrayRef::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { SourceLocation L = SMgr.getExpansionLoc(I->getBegin()); - if (!L.isFileID() || SMgr.getFileID(L) != FID) -return; // FIXME: Emit a warning? + if (!L.isFileID() || SMgr.getFileID(L) != FID) { +llvm::errs() << warning.str(); +return; + } L = SMgr.getExpansionLoc(I->getEnd()); - if (!L.isFileID() || SMgr.getFileID(L) != FID) -return; // FIXME: Emit a warning? + if (!L.isFileID() || SMgr.getFileID(L) != FID) { +llvm::errs() << warning.str(); +return; + } } if (const PathDiagnosticCallPiece *call = Index: include/clang/Driver/Options.td === --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1969,7 +1969,8 @@ def _all_warnings : Flag<["--"], "all-warnings">, Alias; def _analyze_auto : Flag<["--"], "analyze-auto">, Flags<[DriverOption]>; def _analyzer_no_default_checks : Flag<["--"], "analyzer-no-default-checks">, Flags<[DriverOption]>; -def _analyzer_output : JoinedOrSeparate<["--"], "analyzer-output">, Flags<[DriverOption]>; +def _analyzer_output : JoinedOrSeparate<["--"], "analyzer-output">, Flags<[DriverOption]>, + HelpText<"Static analyzer report output format (html|plist|plist-multi-file|plist-html|text).">; def _analyze : Flag<["--"], "analyze">, Flags<[DriverOption, CoreOption]>, HelpText<"Run the static analyzer">; def _assemble : Flag<["--"], "assemble">, Alias; Index: test/Analysis/diagnostics/diag-cross-file-boundaries.h === --- test/Analysis/diagnostics/diag-cross-file-boundaries.h +++ test/Analysis/diagnostics/diag-cross-file-boundaries.h @@ -0,0 +1,4 @@ +static void f() { + int *p = 0; + *p = 1; // expected-warning{{Dereference of null pointer}} +} Index: test/Analysis/diagnostics/diag-cross-file-boundaries.c === --- test/Analysis/diagnostics/diag-cross-file-boundaries.c +++ test/Analysis/diagnostics/diag-cross-file-boundaries.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s +// RUN: %clang_cc1 -analyze
Re: [PATCH] D22494: [analyzer] Explain why analyzer report is not generated (fix for PR12421).
ayartsev updated this revision to Diff 70772. ayartsev added a comment. Updated the patch, added help entry for the "--analyzer-output" driver option. Please review. https://reviews.llvm.org/D22494 Files: lib/StaticAnalyzer/Core/PathDiagnostic.cpp test/Analysis/diagnostics/diag-cross-file-boundaries.c test/Analysis/diagnostics/diag-cross-file-boundaries.h Index: test/Analysis/diagnostics/diag-cross-file-boundaries.h === --- test/Analysis/diagnostics/diag-cross-file-boundaries.h +++ test/Analysis/diagnostics/diag-cross-file-boundaries.h @@ -0,0 +1,4 @@ +static void f() { + int *p = 0; + *p = 1; // expected-warning{{Dereference of null pointer}} +} Index: test/Analysis/diagnostics/diag-cross-file-boundaries.c === --- test/Analysis/diagnostics/diag-cross-file-boundaries.c +++ test/Analysis/diagnostics/diag-cross-file-boundaries.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=html -o PR12421.html %s 2>&1 | FileCheck %s + +// Test for PR12421 +#include "diag-cross-file-boundaries.h" + +int main(){ + f(); + return 0; +} + +// CHECK: warning: Path diagnostic report is not generated. Index: lib/StaticAnalyzer/Core/PathDiagnostic.cpp === --- lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -211,6 +211,12 @@ const SourceManager = D->path.front()->getLocation().getManager(); SmallVector WorkList; WorkList.push_back(>path); +SmallString<128> buf; +llvm::raw_svector_ostream warning(buf); +warning << "warning: Path diagnostic report is not generated. Current " +<< "output format does not support diagnostics that cross file " +<< "boundaries. Refer to --analyzer-output for valid output " + << "formats\n"; while (!WorkList.empty()) { const PathPieces = *WorkList.pop_back_val(); @@ -222,19 +228,25 @@ if (FID.isInvalid()) { FID = SMgr.getFileID(L); -} else if (SMgr.getFileID(L) != FID) - return; // FIXME: Emit a warning? +} else if (SMgr.getFileID(L) != FID) { + llvm::errs() << warning.str(); + return; +} // Check the source ranges. ArrayRef Ranges = piece->getRanges(); for (ArrayRef::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { SourceLocation L = SMgr.getExpansionLoc(I->getBegin()); - if (!L.isFileID() || SMgr.getFileID(L) != FID) -return; // FIXME: Emit a warning? + if (!L.isFileID() || SMgr.getFileID(L) != FID) { +llvm::errs() << warning.str(); +return; + } L = SMgr.getExpansionLoc(I->getEnd()); - if (!L.isFileID() || SMgr.getFileID(L) != FID) -return; // FIXME: Emit a warning? + if (!L.isFileID() || SMgr.getFileID(L) != FID) { +llvm::errs() << warning.str(); +return; + } } if (const PathDiagnosticCallPiece *call = Index: test/Analysis/diagnostics/diag-cross-file-boundaries.h === --- test/Analysis/diagnostics/diag-cross-file-boundaries.h +++ test/Analysis/diagnostics/diag-cross-file-boundaries.h @@ -0,0 +1,4 @@ +static void f() { + int *p = 0; + *p = 1; // expected-warning{{Dereference of null pointer}} +} Index: test/Analysis/diagnostics/diag-cross-file-boundaries.c === --- test/Analysis/diagnostics/diag-cross-file-boundaries.c +++ test/Analysis/diagnostics/diag-cross-file-boundaries.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=html -o PR12421.html %s 2>&1 | FileCheck %s + +// Test for PR12421 +#include "diag-cross-file-boundaries.h" + +int main(){ + f(); + return 0; +} + +// CHECK: warning: Path diagnostic report is not generated. Index: lib/StaticAnalyzer/Core/PathDiagnostic.cpp === --- lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -211,6 +211,12 @@ const SourceManager = D->path.front()->getLocation().getManager(); SmallVector WorkList; WorkList.push_back(>path); +SmallString<128> buf; +llvm::raw_svector_ostream warning(buf); +warning << "warning: Path diagnostic report is not generated. Current " +<< "output format does not support diagnostics that cross file " +<< "boundaries. Refer to --analyzer-output for valid output " + << "formats\n";
Re: [PATCH] D22494: [analyzer] Explain why analyzer report is not generated (fix for PR12421).
ayartsev added inline comments. Comment at: lib/StaticAnalyzer/Core/PathDiagnostic.cpp:216 @@ +215,3 @@ +llvm::raw_svector_ostream warning(buf); +warning << "warning: Path diagnostic report is not generated. Current " +<< "output format does not support diagnostics that cross file " ayartsev wrote: > zaks.anna wrote: > > ayartsev wrote: > > > zaks.anna wrote: > > > > Can/should we be specific about what the user-specified output format > > > > is? > > > It's unable to extract information about user-specified output format > > > from the "PathDiagnosticConsumer" interface. And this class seem to be > > > too generic to contain "AnalyzerOptions" member or to have e.g. "pure > > > virtual getOutputFormatName()". > > > So the only way I see to get info about output format is to use > > > "PathDiagnosticConsumer::getName()". > > > Maybe it makes sense just to add a hint to use "--analyzer-output" driver > > > option to change output format. However this option is not documented at > > > all and is not displayed in clang help. What do you think? > > I think mentioning the option is the best option. What is that option > > called in scan-build? > scan-build (both perl and python versions) has two options: "-plist" and > "-plist-html" that are translated to "-analyzer-output=plist" and > "-analyzer-output=plist-html" frontend options respectively. I suggest to document the "--analyzer-output" option and to mention this option in the warning. https://reviews.llvm.org/D22494 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D22494: [analyzer] Explain why analyzer report is not generated (fix for PR12421).
ayartsev added inline comments. Comment at: lib/StaticAnalyzer/Core/PathDiagnostic.cpp:216 @@ +215,3 @@ +llvm::raw_svector_ostream warning(buf); +warning << "warning: Path diagnostic report is not generated. Current " +<< "output format does not support diagnostics that cross file " zaks.anna wrote: > ayartsev wrote: > > zaks.anna wrote: > > > Can/should we be specific about what the user-specified output format is? > > It's unable to extract information about user-specified output format from > > the "PathDiagnosticConsumer" interface. And this class seem to be too > > generic to contain "AnalyzerOptions" member or to have e.g. "pure virtual > > getOutputFormatName()". > > So the only way I see to get info about output format is to use > > "PathDiagnosticConsumer::getName()". > > Maybe it makes sense just to add a hint to use "--analyzer-output" driver > > option to change output format. However this option is not documented at > > all and is not displayed in clang help. What do you think? > I think mentioning the option is the best option. What is that option called > in scan-build? scan-build (both perl and python versions) has two options: "-plist" and "-plist-html" that are translated to "-analyzer-output=plist" and "-analyzer-output=plist-html" frontend options respectively. https://reviews.llvm.org/D22494 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D22494: [analyzer] Explain why analyzer report is not generated (fix for PR12421).
ayartsev added a comment. Gentle ping. https://reviews.llvm.org/D22494 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D22494: [analyzer] Explain why analyzer report is not generated (fix for PR12421).
ayartsev added a comment. Ping. https://reviews.llvm.org/D22494 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D22862: [analyzer] Fix for PR15623: eliminate unwanted ProgramState checker data propagation.
ayartsev added a comment. @zaks.anna, sorry for the noise about the "misc-ps-region-store.m" test, my mistake. In https://reviews.llvm.org/D22862#508674, @NoQ wrote: > Hmm. The test in `unwanted-programstate-data-propagation.c` passes on my > machine even without the patch, and the return value on the respective path > is correctly represented as `(conj_$6{void *}) != 0U`, which comes from the > `evalCast()` call in `VisitLogicalExpr()` and is the default behavior of > `evalCast()` for Loc to pointer casts. There seems to be something amiss. Hm, updated to trunk, now the test passes without the patch. Changing "_Bool" to "int" in the test reproduces the issue. In https://reviews.llvm.org/D22862#501315, @dcoughlin wrote: > Does this seem reasonable? Thanks for the idea, working on the solution. @dcoughlin, @NoQ, could you, please, tell, how you get dumps of symbolic expressions and constraints like "(conj_$6{void *}) != 0U"? Tried different debug.* checkers and clang_analyzer_explain() but failed. https://reviews.llvm.org/D22862 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D22494: [analyzer] Explain why analyzer report is not generated (fix for PR12421).
ayartsev added inline comments. Comment at: lib/StaticAnalyzer/Core/PathDiagnostic.cpp:216 @@ +215,3 @@ +llvm::raw_svector_ostream warning(buf); +warning << "warning: Path diagnostic report is not generated. Current " +<< "output format does not support diagnostics that cross file " zaks.anna wrote: > Can/should we be specific about what the user-specified output format is? It's unable to extract information about user-specified output format from the "PathDiagnosticConsumer" interface. And this class seem to be too generic to contain "AnalyzerOptions" member or to have e.g. "pure virtual getOutputFormatName()". So the only way I see to get info about output format is to use "PathDiagnosticConsumer::getName()". Maybe it makes sense just to add a hint to use "--analyzer-output" driver option to change output format. However this option is not documented at all and is not displayed in clang help. What do you think? https://reviews.llvm.org/D22494 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D22494: [analyzer] Explain why analyzer report is not generated (fix for PR12421).
ayartsev added inline comments. Comment at: test/Analysis/PR12421.c:11 @@ +10,2 @@ + +// CHECK: warning: Path diagnostic report is not generated. HTMLDiagnostics does not support diagnostics that cross file boundaries. zaks.anna wrote: > ayartsev wrote: > > zaks.anna wrote: > > > We should use the name of the diagnostic consumer here - that will only > > > be legible for the developers working on the attic analyzer core. > > Done. As for me the name of the diagnostic consumer also makes the warning > > more clear and helpful for an ordinary user. From the consumer name he can > > see what report format is talked about and maybe change the scan-build > > (which setups the '-analyzer-output' frontend option internally) options. > > Do you still want to remove the consumer name from the warning? > "HTMLDiagnostics" is not a name a user would be familiar with. You should use > only familiar terms in diagnostics. Ok. Comment at: test/Analysis/PR12421.h:1 @@ +1,2 @@ +static void f() { + int *p = 0; zaks.anna wrote: > zaks.anna wrote: > > Please. do not use the PR as a file name. Use the purpose of the test > > instead, > this does not seem to be done. Did you see an updated diff? Or I'm probably missing something. Maybe you mean something like this: check-diag-cross-file-boundaries-no-report.* ? https://reviews.llvm.org/D22494 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D22862: [analyzer] Fix for PR15623: eliminate unwanted ProgramState checker data propagation.
ayartsev added inline comments. Comment at: test/Analysis/misc-ps-region-store.m:332 @@ -330,3 +331,3 @@ if (p < q) { // If we reach here, 'p' cannot be null. If 'p' is null, then 'n' must // be '0', meaning that this branch is not feasible. zaks.anna wrote: > Try substituting 'p' with null and you will se that n must be zero in that > case because, otherwise, we would take the early return branch. Since p is > not null, we should not warn here. > > This is a regression. If we reached the line "unsigned short *p = (unsigned short*) data;" then ''data" is definitely null and "n" is definitely >0, otherwise we would take the early return branch. Then we have "p" is definitely null and "q" is either equal (if n == 1) or greater then "p". In case of n > 1 we definitely have a null dereference. Please tell what I'm missing. https://reviews.llvm.org/D22862 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D22862: [analyzer] Fix for PR15623: eliminate unwanted ProgramState checker data propagation.
ayartsev created this revision. ayartsev added reviewers: zaks.anna, krememek. ayartsev added a subscriber: cfe-commits. The attached patch eliminates unneeded checker data propagation from one of the operands of a logical operation to the operation result. The result of a logical operation is calculated from the logical values of its operands and is independent from operands nature. One of the test changed its result (misc-ps-region-store.m, rdar_7275774). I did not manage to understand the test, something is definitely wrong with it - at least the comment inside the test do not correspond to reality and an old test result seem to be wrong. The patch fixes https://llvm.org/bugs/show_bug.cgi?id=15623. Please review! https://reviews.llvm.org/D22862 Files: lib/StaticAnalyzer/Core/ExprEngineC.cpp test/Analysis/misc-ps-region-store.m test/Analysis/unwanted-programstate-data-propagation.c Index: test/Analysis/unwanted-programstate-data-propagation.c === --- test/Analysis/unwanted-programstate-data-propagation.c +++ test/Analysis/unwanted-programstate-data-propagation.c @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -verify %s +// expected-no-diagnostics + +// test for PR15623 +#include "Inputs/system-header-simulator.h" + +typedef __typeof(sizeof(int)) size_t; +void *malloc(size_t); +void free(void *); + +_Bool test1(void) { + char *param = malloc(10); + char *value = malloc(10); + _Bool ok = (param && value); + free(param); + free(value); + // Previously we ended up with 'Use of memory after it is freed' on return. + // This happened due to incorrect processing of logical AND at line + // '_Bool ok = (param && value);'. The ProgramState data attached to the + // pointers memory region by the unix.Malloc checker was propogated to the + // 'ok' variable by mistake. + return ok; // no warning +} Index: test/Analysis/misc-ps-region-store.m === --- test/Analysis/misc-ps-region-store.m +++ test/Analysis/misc-ps-region-store.m @@ -323,14 +323,15 @@ void rdar_7275774(void *data, unsigned n) { if (!(data || n == 0)) return; - + + // 'data' == null, n > 0 unsigned short *p = (unsigned short*) data; unsigned short *q = p + (n / 2); if (p < q) { // If we reach here, 'p' cannot be null. If 'p' is null, then 'n' must // be '0', meaning that this branch is not feasible. -*p = *q; // no-warning +*p = *q; // expected-warning{{Dereference of null pointer (loaded from variable 'p')}} } } Index: lib/StaticAnalyzer/Core/ExprEngineC.cpp === --- lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -602,8 +602,7 @@ if (StTrue) { if (StFalse) { // We can't constrain the value to 0 or 1. - // The best we can do is a cast. - X = getSValBuilder().evalCast(RHSVal, B->getType(), RHS->getType()); + X = UnknownVal(); } else { // The value is known to be true. X = getSValBuilder().makeIntVal(1, B->getType()); Index: test/Analysis/unwanted-programstate-data-propagation.c === --- test/Analysis/unwanted-programstate-data-propagation.c +++ test/Analysis/unwanted-programstate-data-propagation.c @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -verify %s +// expected-no-diagnostics + +// test for PR15623 +#include "Inputs/system-header-simulator.h" + +typedef __typeof(sizeof(int)) size_t; +void *malloc(size_t); +void free(void *); + +_Bool test1(void) { + char *param = malloc(10); + char *value = malloc(10); + _Bool ok = (param && value); + free(param); + free(value); + // Previously we ended up with 'Use of memory after it is freed' on return. + // This happened due to incorrect processing of logical AND at line + // '_Bool ok = (param && value);'. The ProgramState data attached to the + // pointers memory region by the unix.Malloc checker was propogated to the + // 'ok' variable by mistake. + return ok; // no warning +} Index: test/Analysis/misc-ps-region-store.m === --- test/Analysis/misc-ps-region-store.m +++ test/Analysis/misc-ps-region-store.m @@ -323,14 +323,15 @@ void rdar_7275774(void *data, unsigned n) { if (!(data || n == 0)) return; - + + // 'data' == null, n > 0 unsigned short *p = (unsigned short*) data; unsigned short *q = p + (n / 2); if (p < q) { // If we reach here, 'p' cannot be null. If 'p' is null, then 'n' must // be '0', meaning that this branch is not feasible. -*p = *q; // no-warning +*p = *q; // expected-warning{{Dereference of null pointer (loaded from variable 'p')}} }
Re: [PATCH] D22494: [analyzer] Explain why analyzer report is not generated (fix for PR12421).
ayartsev updated this revision to Diff 65519. ayartsev marked 2 inline comments as done. https://reviews.llvm.org/D22494 Files: lib/StaticAnalyzer/Core/PathDiagnostic.cpp test/Analysis/diagnostics/diag-cross-file-boundaries.c test/Analysis/diagnostics/diag-cross-file-boundaries.h Index: test/Analysis/diagnostics/diag-cross-file-boundaries.h === --- test/Analysis/diagnostics/diag-cross-file-boundaries.h +++ test/Analysis/diagnostics/diag-cross-file-boundaries.h @@ -0,0 +1,4 @@ +static void f() { + int *p = 0; + *p = 1; // expected-warning{{Dereference of null pointer}} +} Index: test/Analysis/diagnostics/diag-cross-file-boundaries.c === --- test/Analysis/diagnostics/diag-cross-file-boundaries.c +++ test/Analysis/diagnostics/diag-cross-file-boundaries.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=html -o PR12421.html %s 2>&1 | FileCheck %s + +// Test for PR12421 +#include "diag-cross-file-boundaries.h" + +int main(){ + f(); + return 0; +} + +// CHECK: warning: Path diagnostic report is not generated. Current output format does not support diagnostics that cross file boundaries. Index: lib/StaticAnalyzer/Core/PathDiagnostic.cpp === --- lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -211,6 +211,11 @@ const SourceManager = D->path.front()->getLocation().getManager(); SmallVector WorkList; WorkList.push_back(>path); +SmallString<128> buf; +llvm::raw_svector_ostream warning(buf); +warning << "warning: Path diagnostic report is not generated. Current " +<< "output format does not support diagnostics that cross file " +<< "boundaries.\n"; while (!WorkList.empty()) { const PathPieces = *WorkList.pop_back_val(); @@ -222,19 +227,25 @@ if (FID.isInvalid()) { FID = SMgr.getFileID(L); -} else if (SMgr.getFileID(L) != FID) - return; // FIXME: Emit a warning? +} else if (SMgr.getFileID(L) != FID) { + llvm::errs() << warning.str(); + return; +} // Check the source ranges. ArrayRef Ranges = piece->getRanges(); for (ArrayRef::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { SourceLocation L = SMgr.getExpansionLoc(I->getBegin()); - if (!L.isFileID() || SMgr.getFileID(L) != FID) -return; // FIXME: Emit a warning? + if (!L.isFileID() || SMgr.getFileID(L) != FID) { +llvm::errs() << warning.str(); +return; + } L = SMgr.getExpansionLoc(I->getEnd()); - if (!L.isFileID() || SMgr.getFileID(L) != FID) -return; // FIXME: Emit a warning? + if (!L.isFileID() || SMgr.getFileID(L) != FID) { +llvm::errs() << warning.str(); +return; + } } if (const PathDiagnosticCallPiece *call = Index: test/Analysis/diagnostics/diag-cross-file-boundaries.h === --- test/Analysis/diagnostics/diag-cross-file-boundaries.h +++ test/Analysis/diagnostics/diag-cross-file-boundaries.h @@ -0,0 +1,4 @@ +static void f() { + int *p = 0; + *p = 1; // expected-warning{{Dereference of null pointer}} +} Index: test/Analysis/diagnostics/diag-cross-file-boundaries.c === --- test/Analysis/diagnostics/diag-cross-file-boundaries.c +++ test/Analysis/diagnostics/diag-cross-file-boundaries.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=html -o PR12421.html %s 2>&1 | FileCheck %s + +// Test for PR12421 +#include "diag-cross-file-boundaries.h" + +int main(){ + f(); + return 0; +} + +// CHECK: warning: Path diagnostic report is not generated. Current output format does not support diagnostics that cross file boundaries. Index: lib/StaticAnalyzer/Core/PathDiagnostic.cpp === --- lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -211,6 +211,11 @@ const SourceManager = D->path.front()->getLocation().getManager(); SmallVector WorkList; WorkList.push_back(>path); +SmallString<128> buf; +llvm::raw_svector_ostream warning(buf); +warning << "warning: Path diagnostic report is not generated. Current " +<< "output format does not support diagnostics that cross file " +<< "boundaries.\n"; while (!WorkList.empty()) { const PathPieces =
Re: [PATCH] D22494: [analyzer] Explain why analyzer report is not generated (fix for PR12421).
ayartsev added inline comments. Comment at: test/Analysis/PR12421.c:11 @@ +10,2 @@ + +// CHECK: warning: Path diagnostic report is not generated. HTMLDiagnostics does not support diagnostics that cross file boundaries. zaks.anna wrote: > We should use the name of the diagnostic consumer here - that will only be > legible for the developers working on the attic analyzer core. Done. As for me the name of the diagnostic consumer also makes the warning more clear and helpful for an ordinary user. From the consumer name he can see what report format is talked about and maybe change the scan-build (which setups the '-analyzer-output' frontend option internally) options. Do you still want to remove the consumer name from the warning? https://reviews.llvm.org/D22494 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D22494: [analyzer] Explain why analyzer report is not generated (fix for PR12421).
ayartsev created this revision. ayartsev added reviewers: zaks.anna, dcoughlin. ayartsev added a subscriber: cfe-commits. Hi all, Currently if the path diagnostic consumer (e.g HTMLDiagnostics and PlistDiagnostics) do not support cross file diagnostics then the path diagnostic report is just silently omitted in the case of cross file diagnostics. If the analyzer finds an issue the missing report looks like a Clang bug as an issue is successfully reported to stdout but no report is generated. The patch adds a little verbosity to Clang in the case considered above. [[ https://llvm.org/bugs/show_bug.cgi?id=12421 | PR12421 ]] is devoted to the issue. Please review! Tried to write tests that would cover warnings inside the 'for' loop, but failed. Any ideas? https://reviews.llvm.org/D22494 Files: lib/StaticAnalyzer/Core/PathDiagnostic.cpp test/Analysis/PR12421.c test/Analysis/PR12421.h Index: test/Analysis/PR12421.h === --- test/Analysis/PR12421.h +++ test/Analysis/PR12421.h @@ -0,0 +1,4 @@ +static void f() { + int *p = 0; + *p = 1; // expected-warning{{Dereference of null pointer}} +} Index: test/Analysis/PR12421.c === --- test/Analysis/PR12421.c +++ test/Analysis/PR12421.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=html -o PR12421.html %s 2>&1 | FileCheck %s + +#include "PR12421.h" + +int main(){ + f(); + return 0; +} + +// CHECK: warning: Path diagnostic report is not generated. HTMLDiagnostics does not support diagnostics that cross file boundaries. Index: lib/StaticAnalyzer/Core/PathDiagnostic.cpp === --- lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -211,6 +211,10 @@ const SourceManager = D->path.front()->getLocation().getManager(); SmallVector WorkList; WorkList.push_back(>path); +SmallString<128> buf; +llvm::raw_svector_ostream warning(buf); +warning << "warning: Path diagnostic report is not generated. " << getName() +<< " does not support diagnostics that cross file boundaries.\n"; while (!WorkList.empty()) { const PathPieces = *WorkList.pop_back_val(); @@ -222,19 +226,25 @@ if (FID.isInvalid()) { FID = SMgr.getFileID(L); -} else if (SMgr.getFileID(L) != FID) - return; // FIXME: Emit a warning? +} else if (SMgr.getFileID(L) != FID) { + llvm::errs() << warning.str(); + return; +} // Check the source ranges. ArrayRef Ranges = piece->getRanges(); for (ArrayRef::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { SourceLocation L = SMgr.getExpansionLoc(I->getBegin()); - if (!L.isFileID() || SMgr.getFileID(L) != FID) -return; // FIXME: Emit a warning? + if (!L.isFileID() || SMgr.getFileID(L) != FID) { +llvm::errs() << warning.str(); +return; + } L = SMgr.getExpansionLoc(I->getEnd()); - if (!L.isFileID() || SMgr.getFileID(L) != FID) -return; // FIXME: Emit a warning? + if (!L.isFileID() || SMgr.getFileID(L) != FID) { +llvm::errs() << warning.str(); +return; + } } if (const PathDiagnosticCallPiece *call = Index: test/Analysis/PR12421.h === --- test/Analysis/PR12421.h +++ test/Analysis/PR12421.h @@ -0,0 +1,4 @@ +static void f() { + int *p = 0; + *p = 1; // expected-warning{{Dereference of null pointer}} +} Index: test/Analysis/PR12421.c === --- test/Analysis/PR12421.c +++ test/Analysis/PR12421.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=html -o PR12421.html %s 2>&1 | FileCheck %s + +#include "PR12421.h" + +int main(){ + f(); + return 0; +} + +// CHECK: warning: Path diagnostic report is not generated. HTMLDiagnostics does not support diagnostics that cross file boundaries. Index: lib/StaticAnalyzer/Core/PathDiagnostic.cpp === --- lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -211,6 +211,10 @@ const SourceManager = D->path.front()->getLocation().getManager(); SmallVector WorkList; WorkList.push_back(>path); +SmallString<128> buf; +llvm::raw_svector_ostream warning(buf); +warning << "warning: Path diagnostic report is not generated. " << getName() +<< " does not support
r270154 - [analyzer] Fix for PR23790 : constrain return value of strcmp() rather than returning a concrete value.
Author: ayartsev Date: Thu May 19 18:03:49 2016 New Revision: 270154 URL: http://llvm.org/viewvc/llvm-project?rev=270154=rev Log: [analyzer] Fix for PR23790 : constrain return value of strcmp() rather than returning a concrete value. The function strcmp() can return any value, not just {-1,0,1} : "The strcmp(const char *s1, const char *s2) function returns an integer greater than, equal to, or less than zero, accordingly as the string pointed to by s1 is greater than, equal to, or less than the string pointed to by s2." [C11 7.24.4.2p3] https://llvm.org/bugs/show_bug.cgi?id=23790 http://reviews.llvm.org/D16317 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp cfe/trunk/test/Analysis/string.c Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp?rev=270154=270153=270154=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp Thu May 19 18:03:49 2016 @@ -1837,6 +1837,8 @@ void CStringChecker::evalStrcmpCommon(Ch const StringLiteral *s1StrLiteral = getCStringLiteral(C, state, s1, s1Val); const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val); bool canComputeResult = false; + SVal resultVal = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx, +C.blockCount()); if (s1StrLiteral && s2StrLiteral) { StringRef s1StrRef = s1StrLiteral->getString(); @@ -1870,28 +1872,29 @@ void CStringChecker::evalStrcmpCommon(Ch s2StrRef = s2StrRef.substr(0, s2Term); // Use StringRef's comparison methods to compute the actual result. - int result; + int compareRes = ignoreCase ? s1StrRef.compare_lower(s2StrRef) + : s1StrRef.compare(s2StrRef); - if (ignoreCase) { -// Compare string 1 to string 2 the same way strcasecmp() does. -result = s1StrRef.compare_lower(s2StrRef); - } else { -// Compare string 1 to string 2 the same way strcmp() does. -result = s1StrRef.compare(s2StrRef); + // The strcmp function returns an integer greater than, equal to, or less + // than zero, [c11, p7.24.4.2]. + if (compareRes == 0) { +resultVal = svalBuilder.makeIntVal(compareRes, CE->getType()); + } + else { +DefinedSVal zeroVal = svalBuilder.makeIntVal(0, CE->getType()); +// Constrain strcmp's result range based on the result of StringRef's +// comparison methods. +BinaryOperatorKind op = (compareRes == 1) ? BO_GT : BO_LT; +SVal compareWithZero = + svalBuilder.evalBinOp(state, op, resultVal, zeroVal, +svalBuilder.getConditionType()); +DefinedSVal compareWithZeroVal = compareWithZero.castAs(); +state = state->assume(compareWithZeroVal, true); } - - // Build the SVal of the comparison and bind the return value. - SVal resultVal = svalBuilder.makeIntVal(result, CE->getType()); - state = state->BindExpr(CE, LCtx, resultVal); } } - if (!canComputeResult) { -// Conjure a symbolic value. It's the best we can do. -SVal resultVal = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx, - C.blockCount()); -state = state->BindExpr(CE, LCtx, resultVal); - } + state = state->BindExpr(CE, LCtx, resultVal); // Record this as a possible path. C.addTransition(state); Modified: cfe/trunk/test/Analysis/string.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/string.c?rev=270154=270153=270154=diff == --- cfe/trunk/test/Analysis/string.c (original) +++ cfe/trunk/test/Analysis/string.c Thu May 19 18:03:49 2016 @@ -680,6 +680,18 @@ void strncat_empty() { #define strcmp BUILTIN(strcmp) int strcmp(const char * s1, const char * s2); +void strcmp_check_modelling() { + char *x = "aa"; + char *y = "a"; + clang_analyzer_eval(strcmp(x, y) > 0); // expected-warning{{TRUE}} + clang_analyzer_eval(strcmp(x, y) <= 0); // expected-warning{{FALSE}} + clang_analyzer_eval(strcmp(x, y) > 1); // expected-warning{{UNKNOWN}} + + clang_analyzer_eval(strcmp(y, x) < 0); // expected-warning{{TRUE}} + clang_analyzer_eval(strcmp(y, x) >= 0); // expected-warning{{FALSE}} + clang_analyzer_eval(strcmp(y, x) < -1); // expected-warning{{UNKNOWN}} +} + void strcmp_constant0() { clang_analyzer_eval(strcmp("123", "123") == 0); // expected-warning{{TRUE}} } @@ -703,13 +715,13 @@ void strcmp_0() { void strcmp_1() { char *x = "234"; char *y = "123"; - clang_analyzer_eval(strcmp(x, y) == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(strcmp(x, y) > 0); //
Re: [PATCH] D17091: [analyzer][scan-build-py] Non-existing directory for scan-build output.
ayartsev added a comment. In http://reviews.llvm.org/D17091#358022, @rizsotto.mailinglist wrote: > the semicolon at the end of line 39 is an issue for PEP8. please remove it. Done. Committed as r261480, thanks for the review. http://reviews.llvm.org/D17091 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r261480 - [analyzer][scan-build] Non-existing directory for scan-build output.
Author: ayartsev Date: Sun Feb 21 11:04:26 2016 New Revision: 261480 URL: http://llvm.org/viewvc/llvm-project?rev=261480=rev Log: [analyzer][scan-build] Non-existing directory for scan-build output. Makes scan-build successfully accept non-existing output directories provided via "-o" option. The directory is created in this case. This behavior is conforming to the old perl scan-build implementation. (http://reviews.llvm.org/D17091) Modified: cfe/trunk/tools/scan-build-py/libscanbuild/report.py Modified: cfe/trunk/tools/scan-build-py/libscanbuild/report.py URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build-py/libscanbuild/report.py?rev=261480=261479=261480=diff == --- cfe/trunk/tools/scan-build-py/libscanbuild/report.py (original) +++ cfe/trunk/tools/scan-build-py/libscanbuild/report.py Sun Feb 21 11:04:26 2016 @@ -35,7 +35,12 @@ def report_directory(hint, keep): keep -- a boolean value to keep or delete the empty report directory. """ stamp = time.strftime('scan-build-%Y-%m-%d-%H%M%S-', time.localtime()) -name = tempfile.mkdtemp(prefix=stamp, dir=hint) + +parentdir = os.path.abspath(hint) +if not os.path.exists(parentdir): +os.makedirs(parentdir) + +name = tempfile.mkdtemp(prefix=stamp, dir=parentdir) logging.info('Report directory created: %s', name) ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D17091: [analyzer][scan-build-py] Non-existing directory for scan-build output.
ayartsev added a comment. Ping. http://reviews.llvm.org/D17091 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D16317: [Analyzer] Fix for PR23790: bind real value returned from strcmp when modelling strcmp.
ayartsev added a comment. Ping. http://reviews.llvm.org/D16317 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r260420 - [analyzer] Windows: launch scan-build from an arbitrary location.
Author: ayartsev Date: Wed Feb 10 13:46:41 2016 New Revision: 260420 URL: http://llvm.org/viewvc/llvm-project?rev=260420=rev Log: [analyzer] Windows: launch scan-build from an arbitrary location. The following batch files allow to launch scan-build from an arbitrary location if path to clang\tools\scan-build-py\bin is added to %PATH%. Added: cfe/trunk/tools/scan-build-py/bin/analyze-build.bat cfe/trunk/tools/scan-build-py/bin/analyze-c++.bat cfe/trunk/tools/scan-build-py/bin/analyze-cc.bat cfe/trunk/tools/scan-build-py/bin/intercept-build.bat cfe/trunk/tools/scan-build-py/bin/intercept-c++.bat cfe/trunk/tools/scan-build-py/bin/intercept-cc.bat cfe/trunk/tools/scan-build-py/bin/scan-build.bat Added: cfe/trunk/tools/scan-build-py/bin/analyze-build.bat URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build-py/bin/analyze-build.bat?rev=260420=auto == --- cfe/trunk/tools/scan-build-py/bin/analyze-build.bat (added) +++ cfe/trunk/tools/scan-build-py/bin/analyze-build.bat Wed Feb 10 13:46:41 2016 @@ -0,0 +1 @@ +python %~dp0analyze-build %* Added: cfe/trunk/tools/scan-build-py/bin/analyze-c++.bat URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build-py/bin/analyze-c%2B%2B.bat?rev=260420=auto == --- cfe/trunk/tools/scan-build-py/bin/analyze-c++.bat (added) +++ cfe/trunk/tools/scan-build-py/bin/analyze-c++.bat Wed Feb 10 13:46:41 2016 @@ -0,0 +1 @@ +python %~dp0analyze-c++ %* Added: cfe/trunk/tools/scan-build-py/bin/analyze-cc.bat URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build-py/bin/analyze-cc.bat?rev=260420=auto == --- cfe/trunk/tools/scan-build-py/bin/analyze-cc.bat (added) +++ cfe/trunk/tools/scan-build-py/bin/analyze-cc.bat Wed Feb 10 13:46:41 2016 @@ -0,0 +1 @@ +python %~dp0analyze-cc %* Added: cfe/trunk/tools/scan-build-py/bin/intercept-build.bat URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build-py/bin/intercept-build.bat?rev=260420=auto == --- cfe/trunk/tools/scan-build-py/bin/intercept-build.bat (added) +++ cfe/trunk/tools/scan-build-py/bin/intercept-build.bat Wed Feb 10 13:46:41 2016 @@ -0,0 +1 @@ +python %~dp0intercept-build %* Added: cfe/trunk/tools/scan-build-py/bin/intercept-c++.bat URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build-py/bin/intercept-c%2B%2B.bat?rev=260420=auto == --- cfe/trunk/tools/scan-build-py/bin/intercept-c++.bat (added) +++ cfe/trunk/tools/scan-build-py/bin/intercept-c++.bat Wed Feb 10 13:46:41 2016 @@ -0,0 +1 @@ +python %~dp0intercept-c++ %* Added: cfe/trunk/tools/scan-build-py/bin/intercept-cc.bat URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build-py/bin/intercept-cc.bat?rev=260420=auto == --- cfe/trunk/tools/scan-build-py/bin/intercept-cc.bat (added) +++ cfe/trunk/tools/scan-build-py/bin/intercept-cc.bat Wed Feb 10 13:46:41 2016 @@ -0,0 +1 @@ +python %~dp0intercept-cc %* Added: cfe/trunk/tools/scan-build-py/bin/scan-build.bat URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build-py/bin/scan-build.bat?rev=260420=auto == --- cfe/trunk/tools/scan-build-py/bin/scan-build.bat (added) +++ cfe/trunk/tools/scan-build-py/bin/scan-build.bat Wed Feb 10 13:46:41 2016 @@ -0,0 +1 @@ +python %~dp0scan-build %* ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D17091: [analyzer][scan-build-py] Non-existing directory for scan-build output.
ayartsev created this revision. ayartsev added a reviewer: rizsotto.mailinglist. ayartsev added a subscriber: cfe-commits. Attached patch makes scan-build successfully accept non-existing output directories provided via "-o" option. The directory is created in this case. This behavior is conforming to the old perl scan-build implementation. Please review. http://reviews.llvm.org/D17091 Files: tools/scan-build-py/libscanbuild/report.py Index: tools/scan-build-py/libscanbuild/report.py === --- tools/scan-build-py/libscanbuild/report.py +++ tools/scan-build-py/libscanbuild/report.py @@ -35,7 +35,12 @@ keep -- a boolean value to keep or delete the empty report directory. """ stamp = time.strftime('scan-build-%Y-%m-%d-%H%M%S-', time.localtime()) -name = tempfile.mkdtemp(prefix=stamp, dir=hint) + +parentdir = os.path.abspath(hint); +if not os.path.exists(parentdir): +os.makedirs(parentdir) + +name = tempfile.mkdtemp(prefix=stamp, dir=parentdir) logging.info('Report directory created: %s', name) Index: tools/scan-build-py/libscanbuild/report.py === --- tools/scan-build-py/libscanbuild/report.py +++ tools/scan-build-py/libscanbuild/report.py @@ -35,7 +35,12 @@ keep -- a boolean value to keep or delete the empty report directory. """ stamp = time.strftime('scan-build-%Y-%m-%d-%H%M%S-', time.localtime()) -name = tempfile.mkdtemp(prefix=stamp, dir=hint) + +parentdir = os.path.abspath(hint); +if not os.path.exists(parentdir): +os.makedirs(parentdir) + +name = tempfile.mkdtemp(prefix=stamp, dir=parentdir) logging.info('Report directory created: %s', name) ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r251552 - [analyzer] Preserve the order checkers were enabled/disabled.
Author: ayartsev Date: Wed Oct 28 15:43:39 2015 New Revision: 251552 URL: http://llvm.org/viewvc/llvm-project?rev=251552=rev Log: [analyzer] Preserve the order checkers were enabled/disabled. In addition to r251524: preserve the order the checkers were enabled/disabled to be deterministic. Additionally return the number of arguments read by 'ProcessArgs' - for debug purpose. Modified: cfe/trunk/tools/scan-build/scan-build Modified: cfe/trunk/tools/scan-build/scan-build URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build/scan-build?rev=251552=251551=251552=diff == --- cfe/trunk/tools/scan-build/scan-build (original) +++ cfe/trunk/tools/scan-build/scan-build Wed Oct 28 15:43:39 2015 @@ -1447,9 +1447,12 @@ my $ForceDisplayHelp = 0; sub ProcessArgs { my $Args = shift; + my $NumArgs = 0; while (@$Args) { +$NumArgs++; + # Scan for options we recognize. my $arg = $Args->[0]; @@ -1631,7 +1634,8 @@ sub ProcessArgs { if ($arg eq "-enable-checker") { shift @$Args; my $Checker = shift @$Args; - $Options{EnableCheckers}{$Checker} = 1; + # Store $NumArgs to preserve the order the checkers were enabled. + $Options{EnableCheckers}{$Checker} = $NumArgs; delete $Options{DisableCheckers}{$Checker}; next; } @@ -1639,7 +1643,8 @@ sub ProcessArgs { if ($arg eq "-disable-checker") { shift @$Args; my $Checker = shift @$Args; - $Options{DisableCheckers}{$Checker} = 1; + # Store $NumArgs to preserve the order the checkers were disabled. + $Options{DisableCheckers}{$Checker} = $NumArgs; delete $Options{EnableCheckers}{$Checker}; next; } @@ -1676,8 +1681,10 @@ sub ProcessArgs { DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/); +$NumArgs--; last; } + return $NumArgs; } if (!@ARGV) { @@ -1751,8 +1758,16 @@ Diag("Using '$Clang' for static analysis SetHtmlEnv(\@ARGV, $Options{OutputDir}); my @AnalysesToRun; -foreach (keys %{$Options{EnableCheckers}}) { push @AnalysesToRun, "-analyzer-checker", $_; } -foreach (keys %{$Options{DisableCheckers}}) { push @AnalysesToRun, "-analyzer-disable-checker", $_; } +foreach (sort { $Options{EnableCheckers}{$a} <=> $Options{EnableCheckers}{$b} } + keys %{$Options{EnableCheckers}}) { + # Push checkers in order they were enabled. + push @AnalysesToRun, "-analyzer-checker", $_; +} +foreach (sort { $Options{DisableCheckers}{$a} <=> $Options{DisableCheckers}{$b} } + keys %{$Options{DisableCheckers}}) { + # Push checkers in order they were disabled. + push @AnalysesToRun, "-analyzer-disable-checker", $_; +} if ($Options{AnalyzeHeaders}) { push @AnalysesToRun, "-analyzer-opt-analyze-headers"; } if ($Options{AnalyzerStats}) { push @AnalysesToRun, '-analyzer-checker=debug.Stats'; } if ($Options{MaxLoop} > 0) { push @AnalysesToRun, "-analyzer-max-loop $Options{MaxLoop}"; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: r251524 - [analyzer] Make inclusion/exclusion of checkers less ambiguous.
On 28.10.2015 21:26, Devin Coughlin wrote: On Oct 28, 2015, at 9:28 AM, Anton Yartsev via cfe-commits <cfe-commits@lists.llvm.org> wrote: Author: ayartsev Date: Wed Oct 28 11:28:57 2015 New Revision: 251524 URL: http://llvm.org/viewvc/llvm-project?rev=251524=rev Log: [analyzer] Make inclusion/exclusion of checkers less ambiguous. ... my @AnalysesToRun; -foreach (@{$Options{EnableCheckers}}) { push @AnalysesToRun, "-analyzer-checker", $_; } -foreach (@{$Options{DisableCheckers}}) { push @AnalysesToRun, "-analyzer-disable-checker", $_; } +foreach (keys %{$Options{EnableCheckers}}) { push @AnalysesToRun, "-analyzer-checker", $_; } +foreach (keys %{$Options{DisableCheckers}}) { push @AnalysesToRun, "-analyzer-disable-checker", $_; } Does keys guarantee a stable iteration order across different invocations of scan-build? I think it is important that the environment scan-build sets up be deterministic. Hi, Devin, thanks for the remark. Preserved the order the checkers were enabled/disabled at r251552 to be fully consistent. Devin -- Anton ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r247828 - [analyzer] Improved behavior if Clang was not found, part II
Author: ayartsev Date: Wed Sep 16 13:12:15 2015 New Revision: 247828 URL: http://llvm.org/viewvc/llvm-project?rev=247828=rev Log: [analyzer] Improved behavior if Clang was not found, part II - scan-build help: display 'Could not query Clang for the list of available checkers.' + the reason why it happened so if clang was not found. - display requested/forced help in case of --use-analyzer=Xcode. Modified: cfe/trunk/tools/scan-build/scan-build Modified: cfe/trunk/tools/scan-build/scan-build URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build/scan-build?rev=247828=247827=247828=diff == --- cfe/trunk/tools/scan-build/scan-build (original) +++ cfe/trunk/tools/scan-build/scan-build Wed Sep 16 13:12:15 2015 @@ -1100,6 +1100,7 @@ sub RunBuildCommand { sub DisplayHelp { + my $ArgClangNotFoundErrMsg = shift; print <
r247466 - [analyzer] Improve behavior if Clang not found.
Author: ayartsev Date: Fri Sep 11 15:41:09 2015 New Revision: 247466 URL: http://llvm.org/viewvc/llvm-project?rev=247466=rev Log: [analyzer] Improve behavior if Clang not found. - Eliminate 'No such file or directory at scan-build line ...' error if '$RealBin/bin/clang' or '$RealBin/clang' directory does not exist. - Eliminate 'Use of uninitialized value $Clang in concatenation (.) or string at scan-build line ...' error if help is displayed while $Clang was not found. Modified: cfe/trunk/tools/scan-build/scan-build Modified: cfe/trunk/tools/scan-build/scan-build URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build/scan-build?rev=247466=247465=247466=diff == --- cfe/trunk/tools/scan-build/scan-build (original) +++ cfe/trunk/tools/scan-build/scan-build Fri Sep 11 15:41:09 2015 @@ -1258,39 +1258,40 @@ LOADING CHECKERS: -load-plugin [plugin library] ENDTEXT - # Query clang for list of checkers that are enabled. - - # create a list to load the plugins via the 'Xclang' command line - # argument - my @PluginLoadCommandline_xclang; - foreach my $param ( @{$Options{PluginsToLoad}} ) { -push ( @PluginLoadCommandline_xclang, "-Xclang" ); -push ( @PluginLoadCommandline_xclang, "-load" ); -push ( @PluginLoadCommandline_xclang, "-Xclang" ); -push ( @PluginLoadCommandline_xclang, $param ); - } + if (defined $Clang && -x $Clang) { +# Query clang for list of checkers that are enabled. - my %EnabledCheckers; - foreach my $lang ("c", "objective-c", "objective-c++", "c++") { -my $ExecLine = join(' ', qq/"$Clang"/, @PluginLoadCommandline_xclang, "--analyze", "-x", $lang, "-", "-###", "2>&1", "|"); -open(PS, $ExecLine); -while () { - foreach my $val (split /\s+/) { -$val =~ s/\"//g; -if ($val =~ /-analyzer-checker\=([^\s]+)/) { - $EnabledCheckers{$1} = 1; +# create a list to load the plugins via the 'Xclang' command line +# argument +my @PluginLoadCommandline_xclang; +foreach my $param ( @{$Options{PluginsToLoad}} ) { + push ( @PluginLoadCommandline_xclang, "-Xclang" ); + push ( @PluginLoadCommandline_xclang, "-load" ); + push ( @PluginLoadCommandline_xclang, "-Xclang" ); + push ( @PluginLoadCommandline_xclang, $param ); +} + +my %EnabledCheckers; +foreach my $lang ("c", "objective-c", "objective-c++", "c++") { + my $ExecLine = join(' ', qq/"$Clang"/, @PluginLoadCommandline_xclang, "--analyze", "-x", $lang, "-", "-###", "2>&1", "|"); + open(PS, $ExecLine); + while () { +foreach my $val (split /\s+/) { + $val =~ s/\"//g; + if ($val =~ /-analyzer-checker\=([^\s]+)/) { +$EnabledCheckers{$1} = 1; + } } } } - } - # Query clang for complete list of checkers. - my @PluginLoadCommandline; - foreach my $param ( @{$Options{PluginsToLoad}} ) { -push ( @PluginLoadCommandline, "-load" ); -push ( @PluginLoadCommandline, $param ); - } - if (defined $Clang && -x $Clang) { +# Query clang for complete list of checkers. +my @PluginLoadCommandline; +foreach my $param ( @{$Options{PluginsToLoad}} ) { + push ( @PluginLoadCommandline, "-load" ); + push ( @PluginLoadCommandline, $param ); +} + my $ExecLine = join(' ', qq/"$Clang"/, "-cc1", @PluginLoadCommandline, "-analyzer-checker-help", "2>&1", "|"); open(PS, $ExecLine); my $foundCheckers = 0; @@ -1634,6 +1635,7 @@ if (!@ARGV) { } ProcessArgs(\@ARGV); +# All arguments are now shifted from @ARGV. The rest is a build command, if any. if (!@ARGV and !$RequestDisplayHelp) { ErrorDiag("No build command specified.\n\n"); @@ -1642,9 +1644,9 @@ if (!@ARGV and !$RequestDisplayHelp) { # Find 'clang' if (!defined $Options{AnalyzerDiscoveryMethod}) { - $Clang = Cwd::realpath("$RealBin/bin/clang"); + $Clang = Cwd::realpath("$RealBin/bin/clang") if (-d "$RealBin/bin/clang"); if (!defined $Clang || ! -x $Clang) { -$Clang = Cwd::realpath("$RealBin/clang"); +$Clang = Cwd::realpath("$RealBin/clang") if (-d "$RealBin/clang"); } if (!defined $Clang || ! -x $Clang) { if (!$RequestDisplayHelp && !$ForceDisplayHelp) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r245621 - [analyzer] Fix for PR24112 (scan-build doesn't work with --use-analyzer=path to clang++.exe).
Author: ayartsev Date: Thu Aug 20 16:52:39 2015 New Revision: 245621 URL: http://llvm.org/viewvc/llvm-project?rev=245621view=rev Log: [analyzer] Fix for PR24112 (scan-build doesn't work with --use-analyzer=path to clang++.exe). Don't derive the path_to_clang++ from the path_to_clang if the path_to_clang is really the path_to_clang++. Modified: cfe/trunk/tools/scan-build/scan-build Modified: cfe/trunk/tools/scan-build/scan-build URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build/scan-build?rev=245621r1=245620r2=245621view=diff == --- cfe/trunk/tools/scan-build/scan-build (original) +++ cfe/trunk/tools/scan-build/scan-build Thu Aug 20 16:52:39 2015 @@ -1646,14 +1646,20 @@ if ($ForceDisplayHelp || $RequestDisplay } $ClangCXX = $Clang; -# Determine operating system under which this copy of Perl was built. -my $IsWinBuild = ($^O =~/msys|cygwin|MSWin32/); -if($IsWinBuild) { - $ClangCXX =~ s/.exe$/++.exe/; -} -else { - $ClangCXX =~ s/\-\d+\.\d+$//; - $ClangCXX .= ++; +if ($Clang !~ /\+\+(\.exe)?$/) { + # If $Clang holds the name of the clang++ executable then we leave + # $ClangCXX and $Clang equal, otherwise construct the name of the clang++ + # executable from the clang executable name. + + # Determine operating system under which this copy of Perl was built. + my $IsWinBuild = ($^O =~/msys|cygwin|MSWin32/); + if($IsWinBuild) { +$ClangCXX =~ s/.exe$/++.exe/; + } + else { +$ClangCXX =~ s/\-\d+\.\d+$//; +$ClangCXX .= ++; + } } # Make sure to use to handle paths with spaces. ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r244673 - [analyzer] Incorrect env variable replaced.
Author: ayartsev Date: Tue Aug 11 16:24:19 2015 New Revision: 244673 URL: http://llvm.org/viewvc/llvm-project?rev=244673view=rev Log: [analyzer] Incorrect env variable replaced. Modified: cfe/trunk/tools/scan-build/scan-build Modified: cfe/trunk/tools/scan-build/scan-build URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build/scan-build?rev=244673r1=244672r2=244673view=diff == --- cfe/trunk/tools/scan-build/scan-build (original) +++ cfe/trunk/tools/scan-build/scan-build Tue Aug 11 16:24:19 2015 @@ -920,7 +920,7 @@ sub SetEnv { $ENV{$opt} = $Options-{$opt}; } foreach my $opt ('CCC_ANALYZER_STORE_MODEL', -'CCC_ANALYZER_PLUGINS', +'CCC_ANALYZER_CONSTRAINTS_MODEL', 'CCC_ANALYZER_INTERNAL_STATS', 'CCC_ANALYZER_OUTPUT_FORMAT') { my $x = $Options-{$opt}; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits