Home | History | Annotate | Download | only in SemaCXX
      1 // RUN: %clang_cc1 %s -fcxx-exceptions -fexceptions -fsyntax-only -verify -fblocks -std=c++11 -Wunreachable-code-aggressive -Wno-unused-value -Wno-tautological-compare
      2 
      3 int &halt() __attribute__((noreturn));
      4 int &live();
      5 int dead();
      6 int liveti() throw(int);
      7 int (*livetip)() throw(int);
      8 
      9 int test1() {
     10   try {
     11     live();
     12   } catch (int i) {
     13     live();
     14   }
     15   return 1;
     16 }
     17 
     18 void test2() {
     19   try {
     20     live();
     21   } catch (int i) {
     22     live();
     23   }
     24   try {
     25     liveti();
     26   } catch (int i) {
     27     live();
     28   }
     29   try {
     30     livetip();
     31   } catch (int i) {
     32     live();
     33   }
     34   throw 1;
     35   dead();       // expected-warning {{will never be executed}}
     36 }
     37 
     38 
     39 void test3() {
     40   halt()
     41     --;         // expected-warning {{will never be executed}}
     42   // FIXME: The unreachable part is just the '?', but really all of this
     43   // code is unreachable and shouldn't be separately reported.
     44   halt()        // expected-warning {{will never be executed}}
     45     ?
     46     dead() : dead();
     47   live(),
     48     float
     49       (halt()); // expected-warning {{will never be executed}}
     50 }
     51 
     52 void test4() {
     53   struct S {
     54     int mem;
     55   } s;
     56   S &foor();
     57   halt(), foor()// expected-warning {{will never be executed}}
     58     .mem;
     59 }
     60 
     61 void test5() {
     62   struct S {
     63     int mem;
     64   } s;
     65   S &foonr() __attribute__((noreturn));
     66   foonr()
     67     .mem;       // expected-warning {{will never be executed}}
     68 }
     69 
     70 void test6() {
     71   struct S {
     72     ~S() { }
     73     S(int i) { }
     74   };
     75   live(),
     76     S
     77       (halt());  // expected-warning {{will never be executed}}
     78 }
     79 
     80 // Don't warn about unreachable code in template instantiations, as
     81 // they may only be unreachable in that specific instantiation.
     82 void isUnreachable();
     83 
     84 template <typename T> void test_unreachable_templates() {
     85   T::foo();
     86   isUnreachable();  // no-warning
     87 }
     88 
     89 struct TestUnreachableA {
     90   static void foo() __attribute__((noreturn));
     91 };
     92 struct TestUnreachableB {
     93   static void foo();
     94 };
     95 
     96 void test_unreachable_templates_harness() {
     97   test_unreachable_templates<TestUnreachableA>();
     98   test_unreachable_templates<TestUnreachableB>();
     99 }
    100 
    101 // Do warn about explict template specializations, as they represent
    102 // actual concrete functions that somebody wrote.
    103 
    104 template <typename T> void funcToSpecialize() {}
    105 template <> void funcToSpecialize<int>() {
    106   halt();
    107   dead(); // expected-warning {{will never be executed}}
    108 }
    109 
    110 // Handle 'try' code dominating a dead return.
    111 enum PR19040_test_return_t
    112 { PR19040_TEST_FAILURE };
    113 namespace PR19040_libtest
    114 {
    115   class A {
    116   public:
    117     ~A ();
    118   };
    119 }
    120 PR19040_test_return_t PR19040_fn1 ()
    121 {
    122     try
    123     {
    124         throw PR19040_libtest::A ();
    125     } catch (...)
    126     {
    127         return PR19040_TEST_FAILURE;
    128     }
    129     return PR19040_TEST_FAILURE; // expected-warning {{will never be executed}}
    130 }
    131 
    132 __attribute__((noreturn))
    133 void raze();
    134 
    135 namespace std {
    136 template<typename T> struct basic_string {
    137   basic_string(const T* x) {}
    138   ~basic_string() {};
    139 };
    140 typedef basic_string<char> string;
    141 }
    142 
    143 std::string testStr() {
    144   raze();
    145   return ""; // expected-warning {{'return' will never be executed}}
    146 }
    147 
    148 std::string testStrWarn(const char *s) {
    149   raze();
    150   return s; // expected-warning {{will never be executed}}
    151 }
    152 
    153 bool testBool() {
    154   raze();
    155   return true; // expected-warning {{'return' will never be executed}}
    156 }
    157 
    158 static const bool ConditionVar = 1;
    159 int test_global_as_conditionVariable() {
    160   if (ConditionVar)
    161     return 1;
    162   return 0; // no-warning
    163 }
    164 
    165 // Handle unreachable temporary destructors.
    166 class A {
    167 public:
    168   A();
    169   ~A();
    170 };
    171 
    172 __attribute__((noreturn))
    173 void raze(const A& x);
    174 
    175 void test_with_unreachable_tmp_dtors(int x) {
    176   raze(x ? A() : A()); // no-warning
    177 }
    178 
    179 // Test sizeof - sizeof in enum declaration.
    180 enum { BrownCow = sizeof(long) - sizeof(char) };
    181 enum { CowBrown = 8 - 1 };
    182 
    183 
    184 int test_enum_sizeof_arithmetic() {
    185   if (BrownCow)
    186     return 1;
    187   return 2;
    188 }
    189 
    190 int test_enum_arithmetic() {
    191   if (CowBrown)
    192     return 1;
    193   return 2; // expected-warning {{never be executed}}
    194 }
    195 
    196 int test_arithmetic() {
    197   if (8 -1)
    198     return 1;
    199   return 2; // expected-warning {{never be executed}}
    200 }
    201 
    202 int test_treat_const_bool_local_as_config_value() {
    203   const bool controlValue = false;
    204   if (!controlValue)
    205     return 1;
    206   test_treat_const_bool_local_as_config_value(); // no-warning
    207   return 0;
    208 }
    209 
    210 int test_treat_non_const_bool_local_as_non_config_value() {
    211   bool controlValue = false;
    212   if (!controlValue)
    213     return 1;
    214   // There is no warning here because 'controlValue' isn't really
    215   // a control value at all.  The CFG will not treat this
    216   // branch as unreachable.
    217   test_treat_non_const_bool_local_as_non_config_value(); // no-warning
    218   return 0;
    219 }
    220 
    221 void test_do_while(int x) {
    222   // Handle trivial expressions with
    223   // implicit casts to bool.
    224   do {
    225     break;
    226   } while (0); // no-warning
    227 }
    228 
    229 class Frobozz {
    230 public:
    231   Frobozz(int x);
    232   ~Frobozz();
    233 };
    234 
    235 Frobozz test_return_object(int flag) {
    236   return Frobozz(flag);
    237   return Frobozz(42);  // expected-warning {{'return' will never be executed}}
    238 }
    239 
    240 Frobozz test_return_object_control_flow(int flag) {
    241   return Frobozz(flag);
    242   return Frobozz(flag ? 42 : 24); // expected-warning {{code will never be executed}}
    243 }
    244 
    245 void somethingToCall();
    246 
    247 static constexpr bool isConstExprConfigValue() { return true; }
    248 
    249 int test_const_expr_config_value() {
    250  if (isConstExprConfigValue()) {
    251    somethingToCall();
    252    return 0;
    253  }
    254  somethingToCall(); // no-warning
    255  return 1;
    256 }
    257 int test_const_expr_config_value_2() {
    258  if (!isConstExprConfigValue()) {
    259    somethingToCall(); // no-warning
    260    return 0;
    261  }
    262  somethingToCall();
    263  return 1;
    264 }
    265 
    266 class Frodo {
    267 public:
    268   static const bool aHobbit = true;
    269 };
    270 
    271 void test_static_class_var() {
    272   if (Frodo::aHobbit)
    273     somethingToCall();
    274   else
    275     somethingToCall(); // no-warning
    276 }
    277 
    278 void test_static_class_var(Frodo &F) {
    279   if (F.aHobbit)
    280     somethingToCall();
    281   else
    282     somethingToCall(); // no-warning
    283 }
    284 
    285 void test_unreachable_for_null_increment() {
    286   for (unsigned i = 0; i < 10 ; ) // no-warning
    287     break;
    288 }
    289 
    290 void test_unreachable_forrange_increment() {
    291   int x[10] = { 0 };
    292   for (auto i : x) { // expected-warning {{loop will run at most once (loop increment never executed)}}
    293     break;
    294   }
    295 }
    296 
    297 void calledFun() {}
    298 
    299 // Test "silencing" with parentheses.
    300 void test_with_paren_silencing(int x) {
    301   if (false) calledFun(); // expected-warning {{will never be executed}} expected-note {{silence by adding parentheses to mark code as explicitly dead}}
    302   if ((false)) calledFun(); // no-warning
    303 
    304   if (true) // expected-note {{silence by adding parentheses to mark code as explicitly dead}}
    305     calledFun();
    306   else
    307     calledFun(); // expected-warning {{will never be executed}}
    308 
    309   if ((true))
    310     calledFun();
    311   else
    312     calledFun(); // no-warning
    313 
    314   if (!true) // expected-note {{silence by adding parentheses to mark code as explicitly dead}}
    315     calledFun(); // expected-warning {{code will never be executed}}
    316   else
    317     calledFun();
    318 
    319   if ((!true))
    320     calledFun(); // no-warning
    321   else
    322     calledFun();
    323 
    324   if (!(true))
    325     calledFun(); // no-warning
    326   else
    327     calledFun();
    328 }
    329 
    330 void test_with_paren_silencing_impcast(int x) {
    331   if (0) calledFun(); // expected-warning {{will never be executed}} expected-note {{silence by adding parentheses to mark code as explicitly dead}}
    332   if ((0)) calledFun(); // no-warning
    333 
    334   if (1) // expected-note {{silence by adding parentheses to mark code as explicitly dead}}
    335     calledFun();
    336   else
    337     calledFun(); // expected-warning {{will never be executed}}
    338 
    339   if ((1))
    340     calledFun();
    341   else
    342     calledFun(); // no-warning
    343 
    344   if (!1) // expected-note {{silence by adding parentheses to mark code as explicitly dead}}
    345     calledFun(); // expected-warning {{code will never be executed}}
    346   else
    347     calledFun();
    348 
    349   if ((!1))
    350     calledFun(); // no-warning
    351   else
    352     calledFun();
    353 
    354   if (!(1))
    355     calledFun(); // no-warning
    356   else
    357     calledFun();
    358 }
    359 
    360 void tautological_compare(bool x, int y) {
    361   if (x > 10)           // expected-note {{silence}}
    362     calledFun();        // expected-warning {{will never be executed}}
    363   if (10 < x)           // expected-note {{silence}}
    364     calledFun();        // expected-warning {{will never be executed}}
    365   if (x == 10)          // expected-note {{silence}}
    366     calledFun();        // expected-warning {{will never be executed}}
    367 
    368   if (x < 10)           // expected-note {{silence}}
    369     calledFun();
    370   else
    371     calledFun();        // expected-warning {{will never be executed}}
    372   if (10 > x)           // expected-note {{silence}}
    373     calledFun();
    374   else
    375     calledFun();        // expected-warning {{will never be executed}}
    376   if (x != 10)          // expected-note {{silence}}
    377     calledFun();
    378   else
    379     calledFun();        // expected-warning {{will never be executed}}
    380 
    381   if (y != 5 && y == 5) // expected-note {{silence}}
    382     calledFun();        // expected-warning {{will never be executed}}
    383 
    384   if (y > 5 && y < 4)   // expected-note {{silence}}
    385     calledFun();        // expected-warning {{will never be executed}}
    386 
    387   if (y < 10 || y > 5)  // expected-note {{silence}}
    388     calledFun();
    389   else
    390     calledFun();        // expected-warning {{will never be executed}}
    391 
    392   // TODO: Extend warning to the following code:
    393   if (x < -1)
    394     calledFun();
    395   if (x == -1)
    396     calledFun();
    397 
    398   if (x != -1)
    399     calledFun();
    400   else
    401     calledFun();
    402   if (-1 > x)
    403     calledFun();
    404   else
    405     calledFun();
    406 
    407   if (y == -1 && y != -1)
    408     calledFun();
    409 }
    410