[PATCH] check for Incorrect logic in operator

Richard Trieu rtrieu at google.com
Tue Oct 29 21:36:09 PDT 2013


A few more comments for you.

+
+#define mydefine 2
+
...
+
+    if ((x < mydefine) <= 10) {}
+} // no-warning

Why have you chosen to ignore warnings on macros?

+std::vector<CFGCallback*> CFGObserver::Observers;
+void CFGObserver::attach(CFGCallback *Observer) {
+  Observers.push_back(Observer);
+}
Add the null pointer check here.  Since the notify functions are called
more often, it makes sense to check for null once here instead of at every
call later.

+void CFGObserver::detach(CFGCallback *Observer) {
+  Observers.erase(std::remove(Observers.begin(), Observers.end(),
Observer),
+                  Observers.end());
+}
Use the one argument erase() here.
+
+void CFGObserver::notifyCompareAlwaysTrue(const BinaryOperator* B,
+                                          bool IsAlwaysTrue) {
+  for(std::vector<CFGCallback*>::const_iterator I = Observers.begin();
+      I != Observers.end(); ++I) {
+    if(*I != 0) {
Remove null check here.
+      (*I)->compareAlwaysTrue(B,IsAlwaysTrue);
+    }
+  }
+}
+
+void CFGObserver::notifyCompareBoolWithInt(const BinaryOperator* B) {
+  for(std::vector<CFGCallback*>::const_iterator I = Observers.begin();
+      I != Observers.end(); ++I) {
+    if(*I != 0) {
And null check here.
+      (*I)->compareBoolWithInt(B);
+    }
+  }
+}
+

+    SourceRange DiagRange(B->getLHS()->getLocStart(),
B->getRHS()->getLocEnd());
+    S.Diag(B->getExprLoc(), diag::warn_operator_always_true_comparison)
+        << DiagRange << (isAlwaysTrue ? "true" : "false");
+  }
+
We're trying to not pass strings to the diagnostics.  Used
%select{false|true}0 in the .td file then just pass isAlwaysTrue here.

     bool isTemplateInstantiation = false;
     if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
       isTemplateInstantiation = Function->isTemplateInstantiation();
-    if (!isTemplateInstantiation)
-      CheckUnreachable(S, AC);
+      if (!isTemplateInstantiation) {
+        LogicalErrorsHandler Leh(S);
+        CFGObserver::attach(&Leh);
+        CheckUnreachable(S, AC);
+        CFGObserver::detach(&Leh);
+      }
   }
I assume this is why -Wunreachable-code is needed in the tests.  This
introduces a dependency which gives different warnings for
-Wtautological-compare depending on an unrelated warning flag.  Consider
running a separate CFG pass for warnings.  Also, this somehow got indented
an extra two spaces.

 def warn_lunsigned_always_true_comparison : Warning<
   "comparison of unsigned%select{| enum}2 expression %0 is always %1">,
   InGroup<TautologicalCompare>;
+def warn_operator_always_true_comparison : Warning<
+  "logical disjunction always evaluates to %0">,
+  InGroup<TautologicalCompare>;
+def warn_bool_and_int_comparison : Warning<
+  "comparison of a boolean expression with an integer other than 0 or 1">,
+  InGroup<TautologicalCompare>;
 def warn_out_of_range_compare : Warning<
   "comparison of constant %0 with expression of type %1 is always "
   "%select{false|true}2">, InGroup<TautologicalOutOfRangeCompare>;
def warn_bool_and_int_comparison should be in TautologicalOutOfRangeCompare
instead of TautologicalCompare.

+/// \brief Keeps track of all observers. Provides functionality to add and
+/// remove observers and notify observers on found logical operator errors.
+class CFGObserver {
+public:
+  static void attach(CFGCallback *Observer);
+  static void detach(CFGCallback *Observer);
+  static void notifyCompareAlwaysTrue(const BinaryOperator* B,
+                                      bool IsAlwaysTrue);
+  static void notifyCompareBoolWithInt(const BinaryOperator* B);
+private:
+  static std::vector<CFGCallback*> Observers;
+};
+
I don't like the idea of essentially a global vector of callbacks for the
CFG.  Perhaps passing a vector to the CFG builder would be a better way.

That's it for the non-CFG code.  I'll see if I can look at that later.

On Mon, Oct 28, 2013 at 1:55 AM, Anders Rönnholm <
Anders.Ronnholm at evidente.se> wrote:

>  Thanks for your comments.****
>
> I was told that it was preferable to update the CFG. The reason is that
> all analyses built on top on the CFG will benefit: -Wuninitialized, static
> analyzer, warnings, etc. I wonder if Anna or Ted could provide their
> opinions about this patch?****
>
> //Anders****
>
> ** **
>
> *From:* Richard Trieu [mailto:rtrieu at google.com]
> *Sent:* den 26 oktober 2013 01:43
> *To:* Jordan Rose
> *Cc:* Anders Rönnholm; cfe-commits at cs.uiuc.edu
> *Subject:* Re: [PATCH] check for Incorrect logic in operator****
>
> ** **
>
> A few high level comments.****
>
> ** **
>
> "-fblocks -Wunreachable-code" is there any reason your test cases have
> these flags?****
>
> "if (!x == 10) {}" there is an existing warning for this called
> -Wlogical-not-parentheses.  The check should be folded into there.****
>
> "if ((x < y) == 10) {}" ditto this and -Wtautological-compare-out-of-range
> ****
>
> "logical disjunction always evaluates to true"  I wouldn't expect all
> programmers to understand what a logical disjunction is.****
>
> ** **
>
> If you check out -Wlogical-not-parentheses and
> -Wtautological-compare-out-of-range, they are in lib/Sema/SemaChecking.cpp.
>  Why did you use a CFG approach instead?****
>
> ** **
>
> On Fri, Oct 25, 2013 at 10:18 AM, Jordan Rose <jordan_rose at apple.com>
> wrote:****
>
> Richard Trieu has worked on a number of similar warnings. Maybe he can
> take a look?
>
> Jordan****
>
>
>
> On Oct 25, 2013, at 8:18, Anders Rönnholm <Anders.Ronnholm at evidente.se>
> wrote:
>
> > Hi,
> > Resending the patch I sent last week. Anyone want to have a look at it?
> >
> > //Anders
> >
> > -----Original Message-----
> > From: Anders Rönnholm
> > Sent: den 18 oktober 2013 16:05
> > To: cfe-commits at cs.uiuc.edu
> > Subject: [PATCH] check for Incorrect logic in operator
> >
> > Hi,
> >
> > I have a new patch I like to get reviewed. It checks for incorrect
> logics in relational,equal and logic operators in cfgbuilder when trying to
> evaluate bool. A warning is emitted in Sema when an error occurs.
> >
> > eg.
> > if (x != 2 || x != 3) { } always true
> > if ((x < y) <= 10) {}  always true
> >
> > Thanks,
> > Anders****
>
> >
> <incorrectoperatorlogic.diff>_______________________________________________
> > cfe-commits mailing list
> > cfe-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits****
>
> ** **
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131029/f6f87ff2/attachment.html>


More information about the cfe-commits mailing list