reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
// RUN: %clang_analyze_cc1 -analyzer-checker=core,deadcode.DeadStores,alpha.deadcode.UnreachableCode -verify -analyzer-opt-analyze-nested-blocks -Wno-unused-value %s

extern void foo(int a);

// The first few tests are non-path specific - we should be able to find them

void test(unsigned a) {
  switch (a) {
    a += 5; // expected-warning{{never executed}}
  case 2:
    a *= 10;
  case 3:
    a %= 2;
  }
  foo(a);
}

void test2(unsigned a) {
 help:
  if (a > 0)
    return;
  if (a == 0)
    return;
  foo(a); // expected-warning{{never executed}}
  goto help;
}

void test3(unsigned a) {
  while(1);
  if (a > 5) { // expected-warning{{never executed}}
    return;
  }
}

// These next tests are path-sensitive

void test4() {
  int a = 5;

  while (a > 1)
    a -= 2;

  if (a > 1) {
    a = a + 56; // expected-warning{{never executed}}
  }

  foo(a);
}

extern void bar(char c);

void test5(const char *c) {
  foo(c[0]);

  if (!c) {
    bar(1); // expected-warning{{never executed}}
  }
}

// These next tests are false positives and should not generate warnings

void test6(const char *c) {
  if (c) return;
  if (!c) return;
  __builtin_unreachable(); // no-warning
  __builtin_assume(0); // no-warning
}

// Compile-time constant false positives
#define CONSTANT 0
enum test_enum { Off, On };
void test7() {
  if (CONSTANT)
    return; // no-warning

  if (sizeof(int))
    return; // no-warning

  if (Off)
    return; // no-warning
}

void test8() {
  static unsigned a = 0;

  if (a)
    a = 123; // no-warning

  a = 5;
}

// Check for bugs where multiple statements are reported
void test9(unsigned a) {
  switch (a) {
    if (a) // expected-warning{{never executed}}
      foo(a + 5); // no-warning
    else          // no-warning
      foo(a);     // no-warning
    case 1:
    case 2:
      break;
    default:
      break;
  }
}

// Tests from flow-sensitive version
void test10() {
  goto c;
  d:
  goto e; // expected-warning {{never executed}}
  c: ;
  int i;
  return;
  goto b; // expected-warning {{never executed}}
  goto a; // expected-warning {{never executed}}
  b:
  i = 1; // no-warning
  a:
  i = 2;  // no-warning
  goto f;
  e:
  goto d;
  f: ;
}

// test11: we can actually end up in the default case, even if it is not
// obvious: there might be something wrong with the given argument.
enum foobar { FOO, BAR };
extern void error();
void test11(enum foobar fb) {
  switch (fb) {
    case FOO:
      break;
    case BAR:
      break;
    default:
      error(); // no-warning
      return;
      error(); // expected-warning {{never executed}}
  }
}

void inlined(int condition) {
  if (condition) {
    foo(5); // no-warning
  } else {
    foo(6);
  }
}

void testInlined() {
  extern int coin();
  int cond = coin();
  if (!cond) {
    inlined(0);
    if (cond) {
      foo(5); // expected-warning {{never executed}}
    }
  }
}

// Don't warn about unreachable VarDecl.
void dostuff(int*A);
void varDecl1(int X) {
  switch (X) {
    int A; // No warning here.
  case 1:
    dostuff(&A);
    break;
  case 2:
    dostuff(&A);
    break;
  }
}
void varDecl2(int X) {
  switch (X) {
    int A=1; // expected-warning {{never executed}}
  case 1:
    dostuff(&A);
    break;
  case 2:
    dostuff(&A);
    break;
  }
}

// Ensure that ExplodedGraph and unoptimized CFG match.
void test12(int x) {
  switch (x) {
  case 1:
    break; // not unreachable
  case 2:
    do { } while (0);
    break;
  }
}

// Don't merge return nodes in ExplodedGraph unless they are same.
extern int table[];
static int inlineFunction(const int i) {
  if (table[i] != 0)
    return 1;
  return 0;
}
void test13(int i) {
  int x = inlineFunction(i);
  x && x < 10; // no-warning
}

// Don't warn in a macro
#define RETURN(X)  do { return; } while (0)
void macro(void) {
  RETURN(1); // no-warning
}

// Avoid FP when macro argument is known
void writeSomething(int *x);
#define MACRO(C)        \
  if (!C) {             \
    static int x;       \
    writeSomething(&x); \
  }
void macro2(void) {
  MACRO(1);
}