summaryrefslogtreecommitdiff
path: root/clang/test/SemaCXX/uninit-variables.cpp
blob: eb6428d631f2b2995c99ffd85e4317a67fb994b7 (about) (plain)
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
// RUN: %clang_cc1 -fsyntax-only -Wuninitialized -fsyntax-only -fcxx-exceptions %s -verify

// Stub out types for 'typeid' to work.
namespace std { class type_info {}; }

int test1_aux(int &x);
int test1() {
  int x;
  test1_aux(x);
  return x; // no-warning
}

int test2_aux() {
  int x;
  int &y = x;
  return x; // no-warning
}

// Don't warn on unevaluated contexts.
void unevaluated_tests() {
  int x;
  (void)sizeof(x);
  (void)typeid(x);
}

// Warn for glvalue arguments to typeid whose type is polymorphic.
struct A { virtual ~A() {} };
void polymorphic_test() {
  A *a; // expected-note{{initialize the variable 'a' to silence this warning}}
  (void)typeid(*a); // expected-warning{{variable 'a' is uninitialized when used here}}
}

// Handle cases where the CFG may constant fold some branches, thus
// mitigating the need for some path-sensitivity in the analysis.
unsigned test3_aux();
unsigned test3() {
  unsigned x = 0;
  const bool flag = true;
  if (flag && (x = test3_aux()) == 0) {
    return x;
  }
  return x;
}
unsigned test3_b() {
  unsigned x ;
  const bool flag = true;
  if (flag && (x = test3_aux()) == 0) {
    x = 1;
  }
  return x; // no-warning
}
unsigned test3_c() {
  unsigned x; // expected-note{{initialize the variable 'x' to silence this warning}}
  const bool flag = false;
  if (flag && (x = test3_aux()) == 0) {
    x = 1;
  }
  return x; // expected-warning{{variable 'x' is uninitialized when used here}}
}

enum test4_A {
 test4_A_a, test_4_A_b
};
test4_A test4() {
 test4_A a; // expected-note{{variable 'a' is declared here}}
 return a; // expected-warning{{variable 'a' is uninitialized when used here}}
}

// Test variables getting invalidated by function calls with reference arguments
// *AND* there are multiple invalidated arguments.
void test5_aux(int &, int &);

int test5() {
  int x, y;
  test5_aux(x, y);
  return x + y; // no-warning
}

// This test previously crashed Sema.
class Rdar9188004A {
public: 
  virtual ~Rdar9188004A();
};

template< typename T > class Rdar9188004B : public Rdar9188004A {
virtual double *foo(Rdar9188004B *next) const  {
    double *values = next->foo(0);
    try {
    }
    catch(double e) {
      values[0] = e;
    }
    return 0;
  }
};
class Rdar9188004C : public Rdar9188004B<Rdar9188004A> {
  virtual void bar(void) const;
};
void Rdar9188004C::bar(void) const {}

// Don't warn about uninitialized variables in unreachable code.
void PR9625() {
  if (false) {
    int x;
    (void)static_cast<float>(x); // no-warning
  }
}

// Don't warn about variables declared in "catch"
void RDar9251392_bar(const char *msg);

void RDar9251392() {
  try {
    throw "hi";
  }
  catch (const char* msg) {
    RDar9251392_bar(msg); // no-warning
  }
}

// Test handling of "no-op" casts.
void test_noop_cast()
{
    int x = 1;
    int y = (int&)x; // no-warning
}

void test_noop_cast2() {
    int x; // expected-note {{initialize the variable 'x' to silence this warning}}
    int y = (int&)x; // expected-warning {{uninitialized when used here}}
}

// Test handling of bit casts.
void test_bitcasts() {
  int x = 1;
  int y = (float &)x; // no-warning
}

void test_bitcasts_2() {
  int x;  // expected-note {{initialize the variable 'x' to silence this warning}}
  int y = (float &)x; // expected-warning {{uninitialized when used here}}
}