Home | History | Annotate | Download | only in SemaCXX
      1 // RUN: %clang_cc1 %s -fsyntax-only -fcxx-exceptions -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default
      2 // RUN: %clang_cc1 %s -fsyntax-only -fcxx-exceptions -std=c++11 -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default
      3 
      4 // A destructor may be marked noreturn and should still influence the CFG.
      5 void pr6884_abort() __attribute__((noreturn));
      6 
      7 struct pr6884_abort_struct {
      8   pr6884_abort_struct() {}
      9   ~pr6884_abort_struct() __attribute__((noreturn)) { pr6884_abort(); }
     10 };
     11 
     12 struct other { ~other() {} };
     13 
     14 // Ensure that destructors from objects are properly modeled in the CFG despite
     15 // the presence of switches, case statements, labels, and blocks. These tests
     16 // try to cover bugs reported in both PR6884 and PR10063.
     17 namespace abort_struct_complex_cfgs {
     18   int basic(int x) {
     19     switch (x) { default: pr6884_abort(); }
     20   }
     21   int f1(int x) {
     22     switch (x) default: pr6884_abort_struct();
     23   }
     24   int f2(int x) {
     25     switch (x) { default: pr6884_abort_struct(); }
     26   }
     27   int f2_positive(int x) {
     28     switch (x) { default: ; }
     29   } // expected-warning {{control reaches end of non-void function}}
     30   int f3(int x) {
     31     switch (x) { default: { pr6884_abort_struct(); } }
     32   }
     33   int f4(int x) {
     34     switch (x) default: L1: L2: case 4: pr6884_abort_struct();
     35   }
     36   int f5(int x) {
     37     switch (x) default: L1: { L2: case 4: pr6884_abort_struct(); }
     38   }
     39   int f6(int x) {
     40     switch (x) default: L1: L2: case 4: { pr6884_abort_struct(); }
     41   }
     42 
     43   // FIXME: detect noreturn destructors triggered by calls to delete.
     44   int f7(int x) {
     45     switch (x) default: L1: L2: case 4: {
     46       pr6884_abort_struct *p = new pr6884_abort_struct();
     47       delete p;
     48     }
     49   } // expected-warning {{control reaches end of non-void function}}
     50 
     51   // Test that these constructs work even when extraneous blocks are created
     52   // before and after the switch due to implicit destructors.
     53   int g1(int x) {
     54     other o;
     55     switch (x) default: pr6884_abort_struct();
     56   }
     57   int g2(int x) {
     58     other o;
     59     switch (x) { default: pr6884_abort_struct(); }
     60   }
     61   int g2_positive(int x) {
     62     other o;
     63     switch (x) { default: ; }
     64   } // expected-warning {{control reaches end of non-void function}}
     65   int g3(int x) {
     66     other o;
     67     switch (x) { default: { pr6884_abort_struct(); } }
     68   }
     69   int g4(int x) {
     70     other o;
     71     switch (x) default: L1: L2: case 4: pr6884_abort_struct();
     72   }
     73   int g5(int x) {
     74     other o;
     75     switch (x) default: L1: { L2: case 4: pr6884_abort_struct(); }
     76   }
     77   int g6(int x) {
     78     other o;
     79     switch (x) default: L1: L2: case 4: { pr6884_abort_struct(); }
     80   }
     81 
     82   // Test that these constructs work even with variables carrying the no-return
     83   // destructor instead of temporaries.
     84   int h1(int x) {
     85     other o;
     86     switch (x) default: pr6884_abort_struct a;
     87   }
     88   int h2(int x) {
     89     other o;
     90     switch (x) { default: pr6884_abort_struct a; }
     91   }
     92   int h3(int x) {
     93     other o;
     94     switch (x) { default: { pr6884_abort_struct a; } }
     95   }
     96   int h4(int x) {
     97     other o;
     98     switch (x) default: L1: L2: case 4: pr6884_abort_struct a;
     99   }
    100   int h5(int x) {
    101     other o;
    102     switch (x) default: L1: { L2: case 4: pr6884_abort_struct a; }
    103   }
    104   int h6(int x) {
    105     other o;
    106     switch (x) default: L1: L2: case 4: { pr6884_abort_struct a; }
    107   }
    108 }
    109 
    110 // PR9380
    111 struct PR9380 {
    112   ~PR9380();
    113 };
    114 struct PR9380_B : public PR9380 {
    115   PR9380_B( const PR9380& str );
    116 };
    117 void test_PR9380(const PR9380& aKey) {
    118   const PR9380& flatKey = PR9380_B(aKey);
    119 }
    120 
    121 // Array of objects with destructors.  This is purely a coverage test case.
    122 void test_array() {
    123   PR9380 a[2];
    124 }
    125 
    126 // Test classes wrapped in typedefs.  This is purely a coverage test case
    127 // for CFGImplictDtor::getDestructorDecl().
    128 void test_typedefs() {
    129   typedef PR9380 PR9380_Ty;
    130   PR9380_Ty test;
    131   PR9380_Ty test2[20];
    132 }
    133 
    134 // PR9412 - Handle CFG traversal with null successors.
    135 enum PR9412_MatchType { PR9412_Exact };
    136 
    137 template <PR9412_MatchType type> int PR9412_t() {
    138   switch (type) {
    139     case PR9412_Exact:
    140     default:
    141         break;
    142   }
    143 } // expected-warning {{control reaches end of non-void function}}
    144 
    145 void PR9412_f() {
    146     PR9412_t<PR9412_Exact>(); // expected-note {{in instantiation of function template specialization 'PR9412_t<PR9412_MatchType::PR9412_Exact>' requested here}}
    147 }
    148 
    149 struct NoReturn {
    150   ~NoReturn() __attribute__((noreturn));
    151   operator bool() const;
    152 };
    153 struct Return {
    154   ~Return();
    155   operator bool() const;
    156 };
    157 
    158 int testTernaryUnconditionalNoreturn() {
    159   true ? NoReturn() : NoReturn();
    160 }
    161 
    162 int testTernaryStaticallyConditionalNoretrunOnTrue() {
    163   true ? NoReturn() : Return();
    164 }
    165 
    166 int testTernaryStaticallyConditionalRetrunOnTrue() {
    167   true ? Return() : NoReturn();
    168 } // expected-warning {{control reaches end of non-void function}}
    169 
    170 int testTernaryStaticallyConditionalNoretrunOnFalse() {
    171   false ? Return() : NoReturn();
    172 }
    173 
    174 int testTernaryStaticallyConditionalRetrunOnFalse() {
    175   false ? NoReturn() : Return();
    176 } // expected-warning {{control reaches end of non-void function}}
    177 
    178 int testTernaryConditionalNoreturnTrueBranch(bool value) {
    179   value ? (NoReturn() || NoReturn()) : Return();
    180 } // expected-warning {{control may reach end of non-void function}}
    181 
    182 int testTernaryConditionalNoreturnFalseBranch(bool value) {
    183   value ? Return() : (NoReturn() || NoReturn());
    184 } // expected-warning {{control may reach end of non-void function}}
    185 
    186 int testConditionallyExecutedComplexTernaryTrueBranch(bool value) {
    187   value || (true ? NoReturn() : true);
    188 } // expected-warning {{control may reach end of non-void function}}
    189 
    190 int testConditionallyExecutedComplexTernaryFalseBranch(bool value) {
    191   value || (false ? true : NoReturn());
    192 } // expected-warning {{control may reach end of non-void function}}
    193 
    194 int testStaticallyExecutedLogicalOrBranch() {
    195   false || NoReturn();
    196 }
    197 
    198 int testStaticallyExecutedLogicalAndBranch() {
    199   true && NoReturn();
    200 }
    201 
    202 int testStaticallySkippedLogicalOrBranch() {
    203   true || NoReturn();
    204 } // expected-warning {{control reaches end of non-void function}}
    205 
    206 int testStaticallySkppedLogicalAndBranch() {
    207   false && NoReturn();
    208 } // expected-warning {{control reaches end of non-void function}}
    209 
    210 int testConditionallyExecutedComplexLogicalBranch(bool value) {
    211   value || (true && NoReturn());
    212 } // expected-warning {{control may reach end of non-void function}}
    213 
    214 int testConditionallyExecutedComplexLogicalBranch2(bool value) {
    215   (true && value) || (true && NoReturn());
    216 } // expected-warning {{control may reach end of non-void function}}
    217 
    218 int testConditionallyExecutedComplexLogicalBranch3(bool value) {
    219   (false && (Return() || true)) || (true && NoReturn());
    220 }
    221 
    222 int testConditionallyExecutedComplexLogicalBranch4(bool value) {
    223   false || ((Return() || true) && (true && NoReturn()));
    224 }
    225 
    226 #if __cplusplus >= 201103L
    227 namespace LambdaVsTemporaryDtor {
    228   struct Y { ~Y(); };
    229   struct X { template<typename T> X(T, Y = Y()) {} };
    230 
    231   struct Fatal { ~Fatal() __attribute__((noreturn)); };
    232   struct FatalCopy { FatalCopy(); FatalCopy(const FatalCopy&, Fatal F = Fatal()); };
    233 
    234   void foo();
    235 
    236   int bar() {
    237     X work([](){ Fatal(); });
    238     foo();
    239   } // expected-warning {{control reaches end of non-void function}}
    240 
    241   int baz() {
    242     FatalCopy fc;
    243     X work([fc](){});
    244     foo();
    245   } // ok, initialization of lambda does not return
    246 }
    247 #endif
    248 
    249 // Ensure that function-try-blocks also check for return values properly.
    250 int functionTryBlock1(int s) try {
    251   return 0;
    252 } catch (...) {
    253 } // expected-warning {{control may reach end of non-void function}}
    254 
    255 int functionTryBlock2(int s) try {
    256 } catch (...) {
    257   return 0;
    258 } // expected-warning {{control may reach end of non-void function}}
    259 
    260 int functionTryBlock3(int s) try {
    261   return 0;
    262 } catch (...) {
    263   return 0;
    264 } // ok, both paths return.
    265