Use -Wimplicit-fallthrough (#3464)
authorAndres Noetzli <andres.noetzli@gmail.com>
Mon, 18 Nov 2019 20:28:54 +0000 (12:28 -0800)
committerGitHub <noreply@github.com>
Mon, 18 Nov 2019 20:28:54 +0000 (12:28 -0800)
This commit enables compiler warnings for implicit fallthroughs in
switch statements that are not explicitly marked as such. The commit
introduces a new macro `CVC4_FALLTHROUGH` that can be used to indicate
that a fallthrough is intentional. The commit fixes existing warnings
and a bug in the arithmetic rewriter for `abs` (the bug likely couldn't
be triggered easily because we rewrite `abs` to an `ite` while expanding
definitions).

To have the new macro also available in the parser, the commit changes
`src/base/check.h` to be visible to the parser (it includes
`cvc4_private_library.h` now instead of `cvc4_private.h`).

13 files changed:
CMakeLists.txt
src/base/check.h
src/parser/smt2/smt2.cpp
src/preprocessing/passes/unconstrained_simplifier.cpp
src/printer/smt2/smt2_printer.cpp
src/proof/theory_proof.cpp
src/prop/cnf_stream.cpp
src/theory/arith/arith_rewriter.cpp
src/theory/arith/arith_static_learner.cpp
src/theory/arith/theory_arith_private.cpp
src/theory/uf/symmetry_breaker.cpp
src/util/sampler.cpp
test/unit/theory/theory_arith_white.h

index fbdd05c95f8003f253f56bcee9cab374bc785f27..c2ce3e6ac41bd72621b086ea49102cca4b9c18b8 100644 (file)
@@ -189,6 +189,7 @@ add_check_c_flag("-fexceptions")
 add_check_c_cxx_flag("-Wno-deprecated")
 add_check_cxx_flag("-Wsuggest-override")
 add_check_cxx_flag("-Wnon-virtual-dtor")
+add_check_c_cxx_flag("-Wimplicit-fallthrough")
 
 # Temporarily disable -Wclass-memaccess to suppress 'no trivial copy-assignment'
 # cdlist.h warnings. Remove when fixed.
index 915f6e4cba7406734398fe777ca52d1b925e59a8..93ad7110074a973a51987176848c9ff095002df3 100644 (file)
@@ -29,7 +29,7 @@
  ** AlwaysAssert may be added.
  **/
 
-#include "cvc4_private.h"
+#include "cvc4_private_library.h"
 
 #ifndef CVC4__CHECK_H
 #define CVC4__CHECK_H
 #define CVC4_PREDICT_TRUE(x) x
 #endif
 
+#ifdef __has_cpp_attribute
+#if __has_cpp_attribute(fallthrough)
+#define CVC4_FALLTHROUGH [[fallthrough]]
+#endif // __has_cpp_attribute(fallthrough)
+#endif // __has_cpp_attribute
+#ifndef CVC4_FALLTHROUGH
+#define CVC4_FALLTHROUGH
+#endif
+
 namespace CVC4 {
 
 // Implementation notes:
index ae0607b538ca6807cd7f2f7d3f4bc86e9807f3e0..b693eae5b84c5ad302710e9f378f286ff5898282 100644 (file)
@@ -15,6 +15,9 @@
  **/
 #include "parser/smt2/smt2.h"
 
+#include <algorithm>
+
+#include "base/check.h"
 #include "expr/type.h"
 #include "options/options.h"
 #include "parser/antlr_input.h"
@@ -23,8 +26,6 @@
 #include "printer/sygus_print_callback.h"
 #include "util/bitvector.h"
 
-#include <algorithm>
-
 // ANTLR defines these, which is really bad!
 #undef true
 #undef false
@@ -303,6 +304,7 @@ void Smt2::addTheory(Theory theory) {
     addOperator(kind::IS_INTEGER, "is_int");
     addOperator(kind::TO_REAL, "to_real");
     // falling through on purpose, to add Ints part of Reals_Ints
+    CVC4_FALLTHROUGH;
   case THEORY_INTS:
     defineType("Int", getExprManager()->integerType());
     addArithmeticOperators();
index c41f1fca94cc2a5bfd66b91f541c54e3e2d37bfb..1695ae2ffadd49bdc8cad3e80be02ec5bc0afd46 100644 (file)
@@ -251,6 +251,7 @@ void UnconstrainedSimplifier::processUnconstrained()
             checkParent = true;
             break;
           }
+          CVC4_FALLTHROUGH;
         case kind::BITVECTOR_COMP:
         case kind::LT:
         case kind::LEQ:
@@ -424,6 +425,7 @@ void UnconstrainedSimplifier::processUnconstrained()
           {
             break;
           }
+          CVC4_FALLTHROUGH;
         case kind::XOR:
         case kind::BITVECTOR_XOR:
         case kind::BITVECTOR_XNOR:
index 0d3bab3d09e0ca2b6e4c96c22aad327fc08f9239..1f45d8536f4e17d5fc0d90fb3d476f6dbeef4aaa 100644 (file)
@@ -615,7 +615,7 @@ void Smt2Printer::toStream(std::ostream& out,
 
     // arrays theory
   case kind::SELECT:
-  case kind::STORE: typeChildren = true;
+  case kind::STORE: typeChildren = true; CVC4_FALLTHROUGH;
   case kind::PARTIAL_SELECT_0:
   case kind::PARTIAL_SELECT_1:
   case kind::ARRAY_TYPE:
@@ -751,7 +751,7 @@ void Smt2Printer::toStream(std::ostream& out,
     parametricTypeChildren = true;
     out << smtKindString(k, d_variant) << " ";
     break;
-  case kind::MEMBER: typeChildren = true;
+  case kind::MEMBER: typeChildren = true; CVC4_FALLTHROUGH;
   case kind::INSERT:
   case kind::SET_TYPE:
   case kind::SINGLETON:
index 1f3e6abf1f36c4ea51561de08ec30591abe8fc6b..8b9204a208c32c68e42704c84aed09b1b6d3496d 100644 (file)
@@ -1186,7 +1186,7 @@ void LFSCBooleanProof::printOwnedTerm(Expr term, std::ostream& os, const ProofLe
     }
 
     // If letification is off or there were 2 children, same treatment as the other cases.
-    // (No break is intentional).
+    CVC4_FALLTHROUGH;
   case kind::XOR:
   case kind::IMPLIES:
   case kind::NOT:
index 7df5fb4924f543106b9935bee5e68cf053e894eb..6d60bfafc7a0d6cb9e3c591cb508ddb6d623f17e 100644 (file)
@@ -740,6 +740,7 @@ void TseitinCnfStream::convertAndAssert(TNode node, bool negated) {
       convertAndAssertIff(node, negated);
       break;
     }
+    CVC4_FALLTHROUGH;
   default:
   {
     Node nnode = node;
index c95d6f53dcde1d72836f652e1c4aec912dc9d55d..13ab03b456bd8a6526af026d5f2e72faca0e26a2 100644 (file)
@@ -197,6 +197,7 @@ RewriteResponse ArithRewriter::postRewriteTerm(TNode t){
                                  NodeManager::currentNM()->mkConst(-rat));
         }
       }
+      return RewriteResponse(REWRITE_DONE, t);
     case kind::TO_REAL:
       return RewriteResponse(REWRITE_DONE, t[0]);
     case kind::TO_INTEGER:
index e17605eadd59c48141911c4bb8cf93008ac7099c..810eded82453d40a075babc76050d8e2f721cd4c 100644 (file)
@@ -252,25 +252,23 @@ void ArithStaticLearner::addBound(TNode n) {
   DeltaRational bound = constant;
 
   switch(Kind k = n.getKind()) {
-  case kind::LT:
-    bound = DeltaRational(constant, -1);
-    /* fall through */
-  case kind::LEQ:
-    if (maxFind == d_maxMap.end() || (*maxFind).second > bound) {
-      d_maxMap.insert(n[0], bound);
-      Debug("arith::static") << "adding bound " << n << endl;
-    }
-    break;
-  case kind::GT:
-    bound = DeltaRational(constant, 1);
-    /* fall through */
-  case kind::GEQ:
-    if (minFind == d_minMap.end() || (*minFind).second < bound) {
-      d_minMap.insert(n[0], bound);
-      Debug("arith::static") << "adding bound " << n << endl;
-    }
-    break;
-  default: Unhandled() << k; break;
+    case kind::LT: bound = DeltaRational(constant, -1); CVC4_FALLTHROUGH;
+    case kind::LEQ:
+      if (maxFind == d_maxMap.end() || (*maxFind).second > bound)
+      {
+        d_maxMap.insert(n[0], bound);
+        Debug("arith::static") << "adding bound " << n << endl;
+      }
+      break;
+    case kind::GT: bound = DeltaRational(constant, 1); CVC4_FALLTHROUGH;
+    case kind::GEQ:
+      if (minFind == d_minMap.end() || (*minFind).second < bound)
+      {
+        d_minMap.insert(n[0], bound);
+        Debug("arith::static") << "adding bound " << n << endl;
+      }
+      break;
+    default: Unhandled() << k; break;
   }
 }
 
index 62be1fcc18ad9a7dcdfd9d9180e9336604e775b4..a6a47c73ccc9b69b2d288e342eac1fcc6d7fdc48 100644 (file)
@@ -5392,6 +5392,7 @@ std::pair<bool, Node> TheoryArithPrivate::entailmentCheck(TNode lit, const Arith
       }
       // intentionally fall through to DISTINCT case!
       // entailments of negations are eager exit cases for EQUAL
+      CVC4_FALLTHROUGH;
     case DISTINCT:
       if(!bestPrimDiff.first.isNull()){
         // primDir [dm * dp] <= primDir * dm * U < primDir * sep
index 56d0c59cc07de9007b1d8e21c4938d17fc897a33..49ceebfd697c39eba4c69572f962a662d02fc568 100644 (file)
@@ -370,7 +370,7 @@ Node SymmetryBreaker::normInternal(TNode n, size_t level) {
         Debug("ufsymm:eq") << "UFSYMM " << n[0] << " <==> " << n[1] << endl;
       }
     }
-    /* intentional fall-through! */
+    CVC4_FALLTHROUGH;
   case kind::XOR:
     // commutative binary operator handling
     return n[1] < n[0] ? NodeManager::currentNM()->mkNode(k, n[1], n[0]) : Node(n);
index eeb38f9889037e4f98a001b2cb674d7851e54169..60d38bb3429268b0e5867153167b73f74d7c991f 100644 (file)
@@ -73,37 +73,27 @@ FloatingPoint Sampler::pickFpBiased(unsigned e, unsigned s)
 
       // +/- inf
       // sign = x, exp = 11...11, sig = 00...00
-      case 1:
-        sign = one;
-        // Intentional fall-through
+      case 1: sign = one; CVC4_FALLTHROUGH;
       case 2: exp = BitVector::mkOnes(e); break;
 
       // +/- zero
       // sign = x, exp = 00...00, sig = 00...00
-      case 3:
-        sign = one;
-        // Intentional fall-through
+      case 3: sign = one; CVC4_FALLTHROUGH;
       case 4: break;
 
       // +/- max subnormal
       // sign = x, exp = 00...00, sig = 11...11
-      case 5:
-        sign = one;
-        // Intentional fall-through
+      case 5: sign = one; CVC4_FALLTHROUGH;
       case 6: sig = BitVector::mkOnes(s - 1); break;
 
       // +/- min subnormal
       // sign = x, exp = 00...00, sig = 00...01
-      case 7:
-        sign = one;
-        // Intentional fall-through
+      case 7: sign = one; CVC4_FALLTHROUGH;
       case 8: sig = BitVector(s - 1, static_cast<unsigned int>(1)); break;
 
       // +/- max normal
       // sign = x, exp = 11...10, sig = 11...11
-      case 9:
-        sign = one;
-        // Intentional fall-through
+      case 9: sign = one; CVC4_FALLTHROUGH;
       case 10:
         exp = BitVector::mkOnes(e) - BitVector(e, static_cast<unsigned int>(1));
         sig = BitVector::mkOnes(s - 1);
@@ -111,9 +101,7 @@ FloatingPoint Sampler::pickFpBiased(unsigned e, unsigned s)
 
       // +/- min normal
       // sign = x, exp = 00...01, sig = 00...00
-      case 11:
-        sign = one;
-        // Intentional fall-through
+      case 11: sign = one; CVC4_FALLTHROUGH;
       case 12: exp = BitVector(e, static_cast<unsigned int>(1)); break;
 
       default: Unreachable();
index 235931efd0f777da8553755996b3460cba4f8e70..0e71fe9111d8b6d45913c44cf20db93436e3fbb3 100644 (file)
@@ -323,5 +323,9 @@ public:
 
     TS_ASSERT_EQUALS(Rewriter::rewrite(leq0), Rewriter::rewrite(geq1.notNode()));
     TS_ASSERT_EQUALS(Rewriter::rewrite(leq1), Rewriter::rewrite(geq2.notNode()));
+
+    // (abs x) --> (abs x)
+    Node absX = d_nm->mkNode(ABS, x);
+    TS_ASSERT_EQUALS(Rewriter::rewrite(absX), absX);
   }
 };