[PATCH] D27918: [analyzer] OStreamChecker

2019-07-23 Thread Endre Fülöp via Phabricator via cfe-commits
gamesh411 abandoned this revision.
gamesh411 added a comment.
Herald added subscribers: Charusso, donat.nagy, Szelethus, mikhail.ramalho, 
a.sidorin, szepet, baloghadamsoftware.

There are multiple new additions to stream formatters, and this patch is way 
too old. I may consider creating a new checker like this with an extended 
feature set later.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D27918/new/

https://reviews.llvm.org/D27918



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27918: [analyzer] OStreamChecker

2017-08-20 Thread Anna Zaks via Phabricator via cfe-commits
zaks.anna added inline comments.



Comment at: lib/StaticAnalyzer/Checkers/OStreamFormatChecker.cpp:513
+
+bool OStreamFormatChecker::evalCall(const CallExpr *CE,
+CheckerContext &C) const {

gamesh411 wrote:
> NoQ wrote:
> > One of the practical differences between `checkPostCall` and `evalCall` is 
> > that in the latter you have full control over the function execution, 
> > including invalidations that the call causes. Your code not only sets the 
> > return value, but also removes invalidations that normally happen. Like, 
> > normally when an unknown function is called, it is either inlined and 
> > therefore modeled directly, or destroys all information about any global 
> > variables or heap memory that it might have touched. By implementing 
> > `evalCall`, you are saying that the only effect of calling `operator<<()` 
> > on a `basic_ostream` is returning the first argument lvalue, and nothing 
> > else happens; inlining is suppressed, invalidation is suppressed.
> > 
> > I'm not sure if it's a good thing. On one hand, this is not entirely true, 
> > because the operator changes the internal state of the stream and maybe of 
> > some global stuff inside the standard library. On the other hand, it is 
> > unlikely to matter in practice, as far as i can see.
> > 
> > Would it undermine any of your efforts here if you add a manual 
> > invalidation of the stream object and of the `GlobalSystemSpaceRegion` 
> > memory space (you could construct a temporary `CallEvent` and call one of 
> > its methods if it turns out to be easier)?
> > 
> > I'm not exactly in favor of turning this into `checkPostCall()` because 
> > binding expressions in that callback may cause hard-to-notice conflicts 
> > across multiple checkers. Some checkers may even take the old value before 
> > it's replaced. For `evalCall()` we at least have an assert.
> > 
> > If you intend to keep the return value as the only effect, there's option 
> > of making a synthesized body in our body farm, which is even better at 
> > avoiding inter-checker conflicts. Body farms were created for that specific 
> > purpose, even though they also have their drawbacks (sometimes `evalCall` 
> > is more flexible than anything we could synthesize, eg. D20811).
> > 
> > If you have considered all the alternative options mentioned above and 
> > rejected them, could you add a comment explaining why? :)
> I am not familiar with the BodyFarm  approach, however I tried something 
> along the lines of:
> auto CEvt = 
> ResultEqualsFirstParam->getStateManager().getCallEventManager().getSimpleCall(CE,
>  S, C.getLocationContext());
> ProgramStateRef StreamStateInvalidated = 
> CEvt->invalidateRegions(C.blockCount());
> 
> It however broke test2 (where the state is set to hex formatting, then,  back 
> to dec). Any tips why resetting regions could cause problems?
> 
I agree that we should not use evalCall(), especially, in an opt-in checker, as 
it can introduce subtle/hard to debug issues. As was mentioned, if a checker 
implements evalCall(), the usual evaluation by the analyzer core does not 
occur, which could lead to various unpredictable results. 


https://reviews.llvm.org/D27918



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27918: [analyzer] OStreamChecker

2017-08-20 Thread Endre Fülöp via Phabricator via cfe-commits
gamesh411 added a comment.

Ping. @NoQ would you please have a look? Thanks!


https://reviews.llvm.org/D27918



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27918: [analyzer] OStreamChecker

2017-07-24 Thread Endre Fülöp via Phabricator via cfe-commits
gamesh411 updated this revision to Diff 107923.

https://reviews.llvm.org/D27918

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/OStreamFormatChecker.cpp
  test/Analysis/Inputs/system-header-simulator-cxx-iostream.h
  test/Analysis/ostream-format.cpp

Index: test/Analysis/ostream-format.cpp
===
--- /dev/null
+++ test/Analysis/ostream-format.cpp
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.OStreamFormat -verify -std=c++11 %s
+
+#include "Inputs/system-header-simulator-cxx-iostream.h"
+
+
+class StreamState {
+public:
+  StreamState(std::ostream &out)
+  : m_out(out), m_fmt(out.flags()), m_prec(out.precision()) {}
+
+  ~StreamState() {
+m_out.precision(m_prec);
+m_out.flags(m_fmt);
+  }
+
+private:
+  std::ostream &m_out;
+  std::ios_base::fmtflags m_fmt;
+  std::streamsize m_prec;
+};
+
+void test1(int i) {
+  std::cout << std::hex << i;
+} // expected-warning{{Possibly forgotten ostream format modification in scope}}
+
+void test2(int i) { std::cout << std::hex << i << std::dec; } // OK.
+
+void test3(int i) {
+  std::cout << std::hex << i;
+  std::cout << std::dec;
+} // ok
+
+void test4(float f) {
+  std::cout << std::setprecision(2)
+<< f; // The stream state is chaged, but not restored.
+} // expected-warning{{Possibly forgotten ostream format modification in scope}}
+
+int test5() {
+  std::cout.setf(std::ios::hex,
+ std::ios::basefield); // Set hex as the basefield.
+  std::cout.setf(std::ios::showbase);  // Activating showbase.
+  std::cout << 100 << '\n';
+  std::cout.unsetf(std::ios::showbase); // Deactivating showbase.
+  std::cout << 100 << '\n';
+  return 0; // The stream state is chaged, but not restored.
+} // expected-warning{{Possibly forgotten ostream format modification in scope}}
+
+void test6(const char *results) {
+  StreamState ss(std::cout);
+  std::cout << std::setiosflags(std::ios::fixed)
+<< std::setprecision(6); // The stream state is set here.
+  std::cout << results << std::endl;
+} // OK, stream state is recovered here.
+
+void test7(int i) {
+  std::cout << std::hex << i;
+  std::cout.setf(std::ios::dec);
+} // OK.
+
+void test8(float i) {
+  std::cout << std::setprecision(12) << i;
+  std::cout.precision(6);
+} // OK.
+
+void test9(float i) {
+  std::cout.precision(6);
+  std::cout << std::setprecision(12) << i;
+} // expected-warning{{Possibly forgotten ostream format modification in scope}}
+
+void test10(float i) {
+  std::cout.precision(12);
+  std::cout << std::setprecision(6) << i;
+} // OK.
+
Index: test/Analysis/Inputs/system-header-simulator-cxx-iostream.h
===
--- /dev/null
+++ test/Analysis/Inputs/system-header-simulator-cxx-iostream.h
@@ -0,0 +1,195 @@
+// Like the compiler, the static analyzer treats some functions differently if
+// they come from a system header -- for example, it is assumed that system
+// functions do not arbitrarily free() their parameters, and that some bugs
+// found in system headers cannot be fixed by the user and should be
+// suppressed.
+#pragma clang system_header
+
+namespace std {
+typedef unsigned streamsize;
+
+namespace ios {
+int boolalpha;
+int dec;
+int fixed;
+int hex;
+int internal;
+int left;
+int oct;
+int right;
+int scientific;
+int showbase;
+int showpoint;
+int showpos;
+int skipws;
+int unitbuf;
+int uppercase;
+int adjustfield;
+int basefield;
+int floatfield;
+}
+
+class ios_base {
+public:
+  typedef int fmtflags;
+  fmtflags m_fmt;
+  fmtflags flags() const;
+  fmtflags flags(fmtflags);
+  fmtflags setf(fmtflags);
+  fmtflags setf(fmtflags, fmtflags);
+  void unsetf(fmtflags);
+  streamsize precision() const;
+  streamsize precision(streamsize);
+  streamsize width() const;
+  streamsize width(streamsize);
+};
+
+template  class basic_ios : public ios_base {};
+
+// Simple manipulators.
+
+ios_base &boolalpha(ios_base &);
+ios_base &noboolalpha(ios_base &);
+ios_base &showbase(ios_base &);
+ios_base &noshowbase(ios_base &);
+ios_base &showpoint(ios_base &);
+ios_base &noshowpoint(ios_base &);
+ios_base &showpos(ios_base &);
+ios_base &noshowpos(ios_base &);
+ios_base &skipws(ios_base &);
+ios_base &noskipws(ios_base &);
+ios_base &uppercase(ios_base &);
+ios_base &nouppercase(ios_base &);
+ios_base &unitbuf(ios_base &);
+ios_base &nounitbuf(ios_base &);
+ios_base &internal(ios_base &);
+ios_base &left(ios_base &);
+ios_base &right(ios_base &);
+ios_base &dec(ios_base &);
+ios_base &hex(ios_base &);
+ios_base &oct(ios_base &);
+ios_base &fixed(ios_base &);
+ios_base &scientific(ios_base &);
+ios_base &hexfloat(ios_base &);
+ios_base &defaultfloat(ios_base &);
+
+
+template  class basic_ostream : public basic_ios {
+public:
+  basic_ostream &operator<<(int);
+  basic_ostream &operator<<(float);
+  basic_ostream &operat

[PATCH] D27918: [analyzer] OStreamChecker

2017-07-24 Thread Endre Fülöp via Phabricator via cfe-commits
gamesh411 updated this revision to Diff 107921.

https://reviews.llvm.org/D27918

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/OStreamFormatChecker.cpp
  test/Analysis/Inputs/system-header-simulator-cxx-iostream.h
  test/Analysis/ostream-format.cpp

Index: test/Analysis/ostream-format.cpp
===
--- /dev/null
+++ test/Analysis/ostream-format.cpp
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.OStreamFormat -verify -std=c++11 %s
+
+#include "Inputs/system-header-simulator-cxx-iostream.h"
+
+
+class StreamState {
+public:
+  StreamState(std::ostream &out)
+  : m_out(out), m_fmt(out.flags()), m_prec(out.precision()) {}
+
+  ~StreamState() {
+m_out.precision(m_prec);
+m_out.flags(m_fmt);
+  }
+
+private:
+  std::ostream &m_out;
+  std::ios_base::fmtflags m_fmt;
+  std::streamsize m_prec;
+};
+
+void test1(int i) {
+  std::cout << std::hex << i;
+} // expected-warning{{Possibly forgotten ostream format modification in scope}}
+
+void test2(int i) { std::cout << std::hex << i << std::dec; } // OK.
+
+void test3(int i) {
+  std::cout << std::hex << i;
+  std::cout << std::dec;
+} // ok
+
+void test4(float f) {
+  std::cout << std::setprecision(2)
+<< f; // The stream state is chaged, but not restored.
+} // expected-warning{{Possibly forgotten ostream format modification in scope}}
+
+int test5() {
+  std::cout.setf(std::ios::hex,
+ std::ios::basefield); // Set hex as the basefield.
+  std::cout.setf(std::ios::showbase);  // Activating showbase.
+  std::cout << 100 << '\n';
+  std::cout.unsetf(std::ios::showbase); // Deactivating showbase.
+  std::cout << 100 << '\n';
+  return 0; // The stream state is chaged, but not restored.
+} // expected-warning{{Possibly forgotten ostream format modification in scope}}
+
+void test6(const char *results) {
+  StreamState ss(std::cout);
+  std::cout << std::setiosflags(std::ios::fixed)
+<< std::setprecision(6); // The stream state is set here.
+  std::cout << results << std::endl;
+} // OK, stream state is recovered here.
+
+void test7(int i) {
+  std::cout << std::hex << i;
+  std::cout.setf(std::ios::dec);
+} // OK.
+
+void test8(float i) {
+  std::cout << std::setprecision(12) << i;
+  std::cout.precision(6);
+} // OK.
+
+void test9(float i) {
+  std::cout.precision(6);
+  std::cout << std::setprecision(12) << i;
+} // expected-warning{{Possibly forgotten ostream format modification in scope}}
+
+void test10(float i) {
+  std::cout.precision(12);
+  std::cout << std::setprecision(6) << i;
+} // OK.
+
Index: test/Analysis/Inputs/system-header-simulator-cxx-iostream.h
===
--- /dev/null
+++ test/Analysis/Inputs/system-header-simulator-cxx-iostream.h
@@ -0,0 +1,195 @@
+// Like the compiler, the static analyzer treats some functions differently if
+// they come from a system header -- for example, it is assumed that system
+// functions do not arbitrarily free() their parameters, and that some bugs
+// found in system headers cannot be fixed by the user and should be
+// suppressed.
+#pragma clang system_header
+
+namespace std {
+typedef unsigned streamsize;
+
+namespace ios {
+int boolalpha;
+int dec;
+int fixed;
+int hex;
+int internal;
+int left;
+int oct;
+int right;
+int scientific;
+int showbase;
+int showpoint;
+int showpos;
+int skipws;
+int unitbuf;
+int uppercase;
+int adjustfield;
+int basefield;
+int floatfield;
+}
+
+class ios_base {
+public:
+  typedef int fmtflags;
+  fmtflags m_fmt;
+  fmtflags flags() const;
+  fmtflags flags(fmtflags);
+  fmtflags setf(fmtflags);
+  fmtflags setf(fmtflags, fmtflags);
+  void unsetf(fmtflags);
+  streamsize precision() const;
+  streamsize precision(streamsize);
+  streamsize width() const;
+  streamsize width(streamsize);
+};
+
+template  class basic_ios : public ios_base {};
+
+// Simple manipulators.
+
+ios_base &boolalpha(ios_base &);
+ios_base &noboolalpha(ios_base &);
+ios_base &showbase(ios_base &);
+ios_base &noshowbase(ios_base &);
+ios_base &showpoint(ios_base &);
+ios_base &noshowpoint(ios_base &);
+ios_base &showpos(ios_base &);
+ios_base &noshowpos(ios_base &);
+ios_base &skipws(ios_base &);
+ios_base &noskipws(ios_base &);
+ios_base &uppercase(ios_base &);
+ios_base &nouppercase(ios_base &);
+ios_base &unitbuf(ios_base &);
+ios_base &nounitbuf(ios_base &);
+ios_base &internal(ios_base &);
+ios_base &left(ios_base &);
+ios_base &right(ios_base &);
+ios_base &dec(ios_base &);
+ios_base &hex(ios_base &);
+ios_base &oct(ios_base &);
+ios_base &fixed(ios_base &);
+ios_base &scientific(ios_base &);
+ios_base &hexfloat(ios_base &);
+ios_base &defaultfloat(ios_base &);
+
+
+template  class basic_ostream : public basic_ios {
+public:
+  basic_ostream &operator<<(int);
+  basic_ostream &operator<<(float);
+  basic_ostream &operat

[PATCH] D27918: [analyzer] OStreamChecker

2017-07-24 Thread Endre Fülöp via Phabricator via cfe-commits
gamesh411 added a comment.

Hello,

After experimentation the following AST difference between the mock and the 
standard library implementation still stands (which necessitates the special 
handling of the complex manipulators). Example:

  // The different behaviour of the AST is illustrated on the test4 function of 
the test suite:
  //
  // void test4(float f) {
  //   std::cout << std::setprecision(2)
  // << f; // The stream state is chaged, but not restored.
  // } // expected-warning{{Possibly forgotten ostream format modification in 
scope}}
  //
  // The AST of the function with the standard library include
  // (note the wrapping CXXConstructorExpr):
  // |-FunctionDecl 0x5642e3f80b70  line:33:6 test4 'void 
(float)'
  // | |-ParmVarDecl 0x5642e3f80ab0  col:18 used f 'float'
  // | `-CompoundStmt 0x5642e3f818b0 
  // |   `-ExprWithCleanups 0x5642e3f81898  
'std::basic_ostream 
>::__ostream_type':'class std::basic_ostream' lvalue
  // | `-CXXOperatorCallExpr 0x5642e3f81850  
'std::basic_ostream 
>::__ostream_type':'class std::basic_ostream' lvalue
  // |   |-ImplicitCastExpr 0x5642e3f81838  
'std::basic_ostream >::__ostream_type 
&(*)(float)' 
  // |   | `-DeclRefExpr 0x5642e3f817b8  'std::basic_ostream >::__ostream_type &(float)' lvalue CXXMethod 
0x5642e3edf120 'operator<<' 'std::basic_ostream >::__ostream_type &(float)'
  // |   |-CXXOperatorCallExpr 0x5642e3f81270  
'basic_ostream >':'class 
std::basic_ostream' lvalue
  // |   | |-ImplicitCastExpr 0x5642e3f81258  'basic_ostream > &(*)(basic_ostream > &, struct std::_Setprecision)' 
  // |   | | `-DeclRefExpr 0x5642e3f811d0  'basic_ostream > &(basic_ostream > &, struct std::_Setprecision)' lvalue Function 
0x5642e3f6a6e0 'operator<<' 'basic_ostream 
> &(basic_ostream > &, struct 
std::_Setprecision)'
  // |   | |-DeclRefExpr 0x5642e3f80c30  
'std::ostream':'class std::basic_ostream' lvalue Var 0x5642e3f56578 
'cout' 'std::ostream':'class std::basic_ostream'
  // |   | `-CXXConstructExpr 0x5642e3f81198  'struct 
std::_Setprecision' 'void (const struct std::_Setprecision &) throw()' elidable
  // |   |   `-MaterializeTemporaryExpr 0x5642e3f81088  
'const struct std::_Setprecision' lvalue
  // |   | `-ImplicitCastExpr 0x5642e3f81070  'const 
struct std::_Setprecision' 
  // |   |   `-CallExpr 0x5642e3f80d20  'struct 
std::_Setprecision'
  // |   | |-ImplicitCastExpr 0x5642e3f80d08  
'struct std::_Setprecision (*)(int)' 
  // |   | | `-DeclRefExpr 0x5642e3f80c88  'struct 
std::_Setprecision (int)' lvalue Function 0x5642e3f63f70 'setprecision' 'struct 
std::_Setprecision (int)'
  // |   | `-IntegerLiteral 0x5642e3f80cc0  'int' 2
  // |   `-ImplicitCastExpr 0x5642e3f817a0  'float' 

  // | `-DeclRefExpr 0x5642e3f812b8  'float' lvalue ParmVar 
0x5642e3f80ab0 'f' 'float'
  //













   |   | `-IntegerLiteral 
0x5642e3f80cc0  'int' 2
  // The AST of the function with the mock library include
  // |-FunctionDecl 0x55c053dfaa70  line:32:6 test4 'void 
(float)'
  // | |-ParmVarDecl 0x55c053dfa9b0  col:18 used f 'float'
  // | `-CompoundStmt 0x55c053dfb7c0 
  // |   `-ExprWithCleanups 0x55c053dfb7a8  'class 
std::basic_ostream' lvalue
  // | `-CXXOperatorCallExpr 0x55c053dfb760  'class 
std::basic_ostream' lvalue
  // |   |-ImplicitCastExpr 0x55c053dfb748  'class 
std::basic_ostream &(*)(float)' 
  // |   | `-DeclRefExpr 0x55c053dfb6f8  'class 
std::basic_ostream &(float)' lvalue CXXMethod 0x55c053df8120 'operator<<' 
'class std::basic_ostream &(float)'
  // |   |-CXXOperatorCallExpr 0x55c053dfb670  
'basic_ostream':'class std::basic_ostream' lvalue
  // |   | |-ImplicitCastExpr 0x55c053dfb658  'basic_ostream 
&(*)(basic_ostream &, const class std::setprecision_manip &)' 

  // |   |

[PATCH] D27918: [analyzer] OStreamChecker

2017-06-06 Thread Endre Fülöp via Phabricator via cfe-commits
gamesh411 updated this revision to Diff 101549.
gamesh411 marked an inline comment as done.
gamesh411 added a comment.

Update diff.


https://reviews.llvm.org/D27918

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/OStreamFormatChecker.cpp
  test/Analysis/Inputs/system-header-simulator-cxx-iostream.h
  test/Analysis/ostream-format.cpp

Index: test/Analysis/ostream-format.cpp
===
--- /dev/null
+++ test/Analysis/ostream-format.cpp
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.OStreamFormat -verify -std=c++11 %s
+
+#include "Inputs/system-header-simulator-cxx-iostream.h"
+
+
+class StreamState {
+public:
+  StreamState(std::ostream &out)
+  : m_out(out), m_fmt(out.flags()), m_prec(out.precision()) {}
+
+  ~StreamState() {
+m_out.precision(m_prec);
+m_out.flags(m_fmt);
+  }
+
+private:
+  std::ostream &m_out;
+  std::ios_base::fmtflags m_fmt;
+  std::streamsize m_prec;
+};
+
+void test1(int i) {
+  std::cout << std::hex << i;
+} // expected-warning{{Possibly forgotten ostream format modification in scope}}
+
+void test2(int i) { std::cout << std::hex << i << std::dec; } // OK.
+
+void test3(int i) {
+  std::cout << std::hex << i;
+  std::cout << std::dec;
+} // ok
+
+void test4(float f) {
+  std::cout << std::setprecision(2)
+<< f; // The stream state is chaged, but not restored.
+} // expected-warning{{Possibly forgotten ostream format modification in scope}}
+
+int test5() {
+  std::cout.setf(std::ios::hex,
+ std::ios::basefield); // Set hex as the basefield.
+  std::cout.setf(std::ios::showbase);  // Activating showbase.
+  std::cout << 100 << '\n';
+  std::cout.unsetf(std::ios::showbase); // Deactivating showbase.
+  std::cout << 100 << '\n';
+  return 0; // The stream state is chaged, but not restored.
+} // expected-warning{{Possibly forgotten ostream format modification in scope}}
+
+void test6(std::string &results) {
+  StreamState ss(std::cout);
+  std::cout << std::setiosflags(std::ios::fixed)
+<< std::setprecision(6); // The stream state is set here.
+  std::cout << results << std::endl;
+} // OK, stream state is recovered here.
+
+void test7(int i) {
+  std::cout << std::hex << i;
+  std::cout.setf(std::ios::dec);
+} // OK.
+
+void test8(float i) {
+  std::cout << std::setprecision(12) << i;
+  std::cout.precision(6);
+} // OK.
+
+void test9(float i) {
+  std::cout.precision(6);
+  std::cout << std::setprecision(12) << i;
+} // expected-warning{{Possibly forgotten ostream format modification in scope}}
+
+void test10(float i) {
+  std::cout.precision(12);
+  std::cout << std::setprecision(6) << i;
+} // OK.
+
Index: test/Analysis/Inputs/system-header-simulator-cxx-iostream.h
===
--- /dev/null
+++ test/Analysis/Inputs/system-header-simulator-cxx-iostream.h
@@ -0,0 +1,195 @@
+// Like the compiler, the static analyzer treats some functions differently if
+// they come from a system header -- for example, it is assumed that system
+// functions do not arbitrarily free() their parameters, and that some bugs
+// found in system headers cannot be fixed by the user and should be
+// suppressed.
+#pragma clang system_header
+
+namespace std {
+typedef unsigned streamsize;
+
+namespace ios {
+int boolalpha;
+int dec;
+int fixed;
+int hex;
+int internal;
+int left;
+int oct;
+int right;
+int scientific;
+int showbase;
+int showpoint;
+int showpos;
+int skipws;
+int unitbuf;
+int uppercase;
+int adjustfield;
+int basefield;
+int floatfield;
+}
+
+class ios_base {
+public:
+  typedef int fmtflags;
+  fmtflags m_fmt;
+  fmtflags flags() const;
+  fmtflags flags(fmtflags);
+  fmtflags setf(fmtflags);
+  fmtflags setf(fmtflags, fmtflags);
+  void unsetf(fmtflags);
+  streamsize precision() const;
+  streamsize precision(streamsize);
+  streamsize width() const;
+  streamsize width(streamsize);
+};
+
+template  class basic_ios : public ios_base {};
+
+// Simple manipulators.
+
+ios_base &boolalpha(ios_base &);
+ios_base &noboolalpha(ios_base &);
+ios_base &showbase(ios_base &);
+ios_base &noshowbase(ios_base &);
+ios_base &showpoint(ios_base &);
+ios_base &noshowpoint(ios_base &);
+ios_base &showpos(ios_base &);
+ios_base &noshowpos(ios_base &);
+ios_base &skipws(ios_base &);
+ios_base &noskipws(ios_base &);
+ios_base &uppercase(ios_base &);
+ios_base &nouppercase(ios_base &);
+ios_base &unitbuf(ios_base &);
+ios_base &nounitbuf(ios_base &);
+ios_base &internal(ios_base &);
+ios_base &left(ios_base &);
+ios_base &right(ios_base &);
+ios_base &dec(ios_base &);
+ios_base &hex(ios_base &);
+ios_base &oct(ios_base &);
+ios_base &fixed(ios_base &);
+ios_base &scientific(ios_base &);
+ios_base &hexfloat(ios_base &);
+ios_base &defaultfloat(ios_base &);
+
+
+template  class basic_ostream : public basic_ios {
+public:
+  basic_

[PATCH] D27918: [analyzer] OStreamChecker

2017-06-06 Thread Endre Fülöp via Phabricator via cfe-commits
gamesh411 marked 6 inline comments as done.
gamesh411 added a comment.

Update diff.




Comment at: lib/StaticAnalyzer/Checkers/OStreamFormatChecker.cpp:263-282
+  mutable IdentifierInfo *II_BasicOstream, *II_Flags, *II_Setf, *II_Unsetf,
+  *II_Setiosflags, *II_Resetiosflags, *II_Precision, *II_SetPrecision,
+  *II_BaseField, *II_Hex, *II_Dec, *II_Oct, *II_AdjustField, *II_Left,
+  *II_Right, *II_Internal, *II_BoolAlpha, *II_NoBoolAlpha, *II_ShowPos,
+  *II_NoShowPos, *II_ShowBase, *II_NoShowBase, *II_UpperCase,
+  *II_NoUpperCase, *II_ShowPoint, *II_NoShowPoint, *II_FloatField,
+  *II_Fixed, *II_Scientific;

NoQ wrote:
> If you ever want to extend the `CallDescription` class to cover your use 
> case, please let us know :)
> 
> While most of these aren't functions, the approach used in this class could 
> be used here as well - making initialization code shorter.
I will look at the CallDescription class, and how the checker can benefit. Is 
it still a problem, that we can not initialize IdentifierInfos during checker 
construction? If so, how will would a CallDescription implementation solve that?



Comment at: lib/StaticAnalyzer/Checkers/OStreamFormatChecker.cpp:387
+
+static Optional tryEvaluateAsInt(const Expr *E, ProgramStateRef S,
+  CheckerContext C) {

NoQ wrote:
> I think you should use `SimpleSValBuilder::getKnownValue()`. The 
> `EvaluateAsInt` part doesn't add much because the analyzer's engine should 
> already be more powerful than that. On the other hand, the 
> `ConstraintManager::getSymVal()` thing, which is already done in 
> `SimpleSValBuilder::getKnownValue()`, may be useful.
I have tried an implementation of getKnownValue(), and it more terse, and did 
not handle the cases it should have had to anyway.



Comment at: lib/StaticAnalyzer/Checkers/OStreamFormatChecker.cpp:513
+
+bool OStreamFormatChecker::evalCall(const CallExpr *CE,
+CheckerContext &C) const {

NoQ wrote:
> One of the practical differences between `checkPostCall` and `evalCall` is 
> that in the latter you have full control over the function execution, 
> including invalidations that the call causes. Your code not only sets the 
> return value, but also removes invalidations that normally happen. Like, 
> normally when an unknown function is called, it is either inlined and 
> therefore modeled directly, or destroys all information about any global 
> variables or heap memory that it might have touched. By implementing 
> `evalCall`, you are saying that the only effect of calling `operator<<()` on 
> a `basic_ostream` is returning the first argument lvalue, and nothing else 
> happens; inlining is suppressed, invalidation is suppressed.
> 
> I'm not sure if it's a good thing. On one hand, this is not entirely true, 
> because the operator changes the internal state of the stream and maybe of 
> some global stuff inside the standard library. On the other hand, it is 
> unlikely to matter in practice, as far as i can see.
> 
> Would it undermine any of your efforts here if you add a manual invalidation 
> of the stream object and of the `GlobalSystemSpaceRegion` memory space (you 
> could construct a temporary `CallEvent` and call one of its methods if it 
> turns out to be easier)?
> 
> I'm not exactly in favor of turning this into `checkPostCall()` because 
> binding expressions in that callback may cause hard-to-notice conflicts 
> across multiple checkers. Some checkers may even take the old value before 
> it's replaced. For `evalCall()` we at least have an assert.
> 
> If you intend to keep the return value as the only effect, there's option of 
> making a synthesized body in our body farm, which is even better at avoiding 
> inter-checker conflicts. Body farms were created for that specific purpose, 
> even though they also have their drawbacks (sometimes `evalCall` is more 
> flexible than anything we could synthesize, eg. D20811).
> 
> If you have considered all the alternative options mentioned above and 
> rejected them, could you add a comment explaining why? :)
I am not familiar with the BodyFarm  approach, however I tried something along 
the lines of:
auto CEvt = 
ResultEqualsFirstParam->getStateManager().getCallEventManager().getSimpleCall(CE,
 S, C.getLocationContext());
ProgramStateRef StreamStateInvalidated = 
CEvt->invalidateRegions(C.blockCount());

It however broke test2 (where the state is set to hex formatting, then,  back 
to dec). Any tips why resetting regions could cause problems?



https://reviews.llvm.org/D27918



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27918: [analyzer] OStreamChecker

2017-04-04 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added a comment.

Hello,

Sorry again for the delays, thank you for your patience. Your checker is in 
good shape, very well-structured and easy to follow, you definitely know your 
stuff, and my comments here are relatively minor.

Are you planning on making more varied warning messages, eg. specifying which 
format modifiers are forgotten, and where in the code they were previously set? 
The latter could be done by using the "bug reporter visitor" mechanism.

I'm sure we can at the very least eventually land this checker into the `optin` 
package, which is the new package for warnings that aren't on by default, but 
are advised to be turned on by the users if the codebase intends to use certain 
language or API features or contracts (unlike the `alpha` package which is for 
checkers undergoing development to be ultimately moved out of alpha). For 
moving out of alpha, i think the work on the warning messages needs to be done, 
and the checker needs to be tested on a large codebase to make sure that the 
false positive rate is low (i guess you already did it), and that's pretty much 
it :) On a side note, i've been recently thinking of making `optin` checkers 
more visible to the `scan-build` users, eg. mentioning in the log that certain 
checks may be worth enabling.




Comment at: lib/StaticAnalyzer/Checkers/OStreamFormatChecker.cpp:263-282
+  mutable IdentifierInfo *II_BasicOstream, *II_Flags, *II_Setf, *II_Unsetf,
+  *II_Setiosflags, *II_Resetiosflags, *II_Precision, *II_SetPrecision,
+  *II_BaseField, *II_Hex, *II_Dec, *II_Oct, *II_AdjustField, *II_Left,
+  *II_Right, *II_Internal, *II_BoolAlpha, *II_NoBoolAlpha, *II_ShowPos,
+  *II_NoShowPos, *II_ShowBase, *II_NoShowBase, *II_UpperCase,
+  *II_NoUpperCase, *II_ShowPoint, *II_NoShowPoint, *II_FloatField,
+  *II_Fixed, *II_Scientific;

If you ever want to extend the `CallDescription` class to cover your use case, 
please let us know :)

While most of these aren't functions, the approach used in this class could be 
used here as well - making initialization code shorter.



Comment at: lib/StaticAnalyzer/Checkers/OStreamFormatChecker.cpp:387
+
+static Optional tryEvaluateAsInt(const Expr *E, ProgramStateRef S,
+  CheckerContext C) {

I think you should use `SimpleSValBuilder::getKnownValue()`. The 
`EvaluateAsInt` part doesn't add much because the analyzer's engine should 
already be more powerful than that. On the other hand, the 
`ConstraintManager::getSymVal()` thing, which is already done in 
`SimpleSValBuilder::getKnownValue()`, may be useful.



Comment at: lib/StaticAnalyzer/Checkers/OStreamFormatChecker.cpp:403
+
+  return Optional();
+}

By the way, there's the `None` thing that represents any empty optional.



Comment at: lib/StaticAnalyzer/Checkers/OStreamFormatChecker.cpp:513
+
+bool OStreamFormatChecker::evalCall(const CallExpr *CE,
+CheckerContext &C) const {

One of the practical differences between `checkPostCall` and `evalCall` is that 
in the latter you have full control over the function execution, including 
invalidations that the call causes. Your code not only sets the return value, 
but also removes invalidations that normally happen. Like, normally when an 
unknown function is called, it is either inlined and therefore modeled 
directly, or destroys all information about any global variables or heap memory 
that it might have touched. By implementing `evalCall`, you are saying that the 
only effect of calling `operator<<()` on a `basic_ostream` is returning the 
first argument lvalue, and nothing else happens; inlining is suppressed, 
invalidation is suppressed.

I'm not sure if it's a good thing. On one hand, this is not entirely true, 
because the operator changes the internal state of the stream and maybe of some 
global stuff inside the standard library. On the other hand, it is unlikely to 
matter in practice, as far as i can see.

Would it undermine any of your efforts here if you add a manual invalidation of 
the stream object and of the `GlobalSystemSpaceRegion` memory space (you could 
construct a temporary `CallEvent` and call one of its methods if it turns out 
to be easier)?

I'm not exactly in favor of turning this into `checkPostCall()` because binding 
expressions in that callback may cause hard-to-notice conflicts across multiple 
checkers. Some checkers may even take the old value before it's replaced. For 
`evalCall()` we at least have an assert.

If you intend to keep the return value as the only effect, there's option of 
making a synthesized body in our body farm, which is even better at avoiding 
inter-checker conflicts. Body farms were created for that specific purpose, 
even though they also have their drawbacks (sometimes `evalCall` is more 
flexible than anything we could synth

[PATCH] D27918: [analyzer] OStreamChecker

2017-02-28 Thread Endre Fülöp via Phabricator via cfe-commits
gamesh411 added a comment.

Hello,
This checker was developed indeed with internal usage in mind. It should not 
necessary be added as a default checker. However I have run it on the 
boost-1.63.0 codebase, and there some some mildly interesting findings in 
examples and tests. There is also a true positive result in the core codebase.

As for the patter described above, it certainly is a possible use-case to set 
streams inside functions, but very few ( if any ) false positives was found 
thanks to that, and the main case for them was that I could not run the 
cross-TU analyzer (boosts bjam build system proved to be reluctant to work 
together with ClangSA).


https://reviews.llvm.org/D27918



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27918: [analyzer] OStreamChecker

2017-01-11 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added a comment.

Hello,

Thanks for the patch, and for the impressing amount of work you put into this. 
Because the patch is huge, so it's going to take some time for somebody to 
understand how everything works.

I'd probably like to learn a bit more about the motivation behind the checker. 
You must be working on a project that uses a lot of `std` streams, and the 
checker seems to verify a particular coding guideline you're following (revert 
all changes to the stream locally). I wonder how universally useful this 
guideline is. For instance, there might exist a project that enjoys writing 
code like this:

  void set_my_favorite_format_specifiers() {
std::cout << std::setprecision(12) << std::hex; // warning?
  }
  
  void revert_my_favorite_format_specifiers() {
std::cout << std::setprecision(6) << std::dec;
  }
  
  void foo() {
set_my_favorite_format_specifiers();
std::cout << 100 << std::endl;
revert_my_favorite_format_specifiers();
  }

Do you expect such pattern to be common? If we enable the checker by default, 
would positives on such code cause annoyance, and would there be a way to 
suppress them?


https://reviews.llvm.org/D27918



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits