forked from OSchip/llvm-project
Pull some cases of initialization with self-reference warnings out of
-Wconditional-uninitialized into -Wuninitialized. llvm-svn: 156512
This commit is contained in:
parent
fd02a89960
commit
43a2fc7b9e
|
@ -464,44 +464,36 @@ static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) {
|
|||
static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
|
||||
const Expr *E, bool isAlwaysUninit,
|
||||
bool alwaysReportSelfInit = false) {
|
||||
bool isSelfInit = false;
|
||||
|
||||
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
|
||||
if (isAlwaysUninit) {
|
||||
// Inspect the initializer of the variable declaration which is
|
||||
// being referenced prior to its initialization. We emit
|
||||
// specialized diagnostics for self-initialization, and we
|
||||
// specifically avoid warning about self references which take the
|
||||
// form of:
|
||||
//
|
||||
// int x = x;
|
||||
//
|
||||
// This is used to indicate to GCC that 'x' is intentionally left
|
||||
// uninitialized. Proven code paths which access 'x' in
|
||||
// an uninitialized state after this will still warn.
|
||||
//
|
||||
// TODO: Should we suppress maybe-uninitialized warnings for
|
||||
// variables initialized in this way?
|
||||
if (const Expr *Initializer = VD->getInit()) {
|
||||
if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts())
|
||||
return false;
|
||||
// Inspect the initializer of the variable declaration which is
|
||||
// being referenced prior to its initialization. We emit
|
||||
// specialized diagnostics for self-initialization, and we
|
||||
// specifically avoid warning about self references which take the
|
||||
// form of:
|
||||
//
|
||||
// int x = x;
|
||||
//
|
||||
// This is used to indicate to GCC that 'x' is intentionally left
|
||||
// uninitialized. Proven code paths which access 'x' in
|
||||
// an uninitialized state after this will still warn.
|
||||
if (const Expr *Initializer = VD->getInit()) {
|
||||
if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts())
|
||||
return false;
|
||||
|
||||
ContainsReference CR(S.Context, DRE);
|
||||
CR.Visit(const_cast<Expr*>(Initializer));
|
||||
isSelfInit = CR.doesContainReference();
|
||||
}
|
||||
if (isSelfInit) {
|
||||
ContainsReference CR(S.Context, DRE);
|
||||
CR.Visit(const_cast<Expr*>(Initializer));
|
||||
if (CR.doesContainReference()) {
|
||||
S.Diag(DRE->getLocStart(),
|
||||
diag::warn_uninit_self_reference_in_init)
|
||||
<< VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
|
||||
} else {
|
||||
S.Diag(DRE->getLocStart(), diag::warn_uninit_var)
|
||||
<< VD->getDeclName() << DRE->getSourceRange();
|
||||
<< VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
S.Diag(DRE->getLocStart(), diag::warn_maybe_uninit_var)
|
||||
<< VD->getDeclName() << DRE->getSourceRange();
|
||||
}
|
||||
|
||||
S.Diag(DRE->getLocStart(), isAlwaysUninit ? diag::warn_uninit_var
|
||||
: diag::warn_maybe_uninit_var)
|
||||
<< VD->getDeclName() << DRE->getSourceRange();
|
||||
} else {
|
||||
const BlockExpr *BE = cast<BlockExpr>(E);
|
||||
if (VD->getType()->isBlockPointerType() &&
|
||||
|
@ -518,7 +510,7 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
|
|||
// Report where the variable was declared when the use wasn't within
|
||||
// the initializer of that declaration & we didn't already suggest
|
||||
// an initialization fixit.
|
||||
if (!isSelfInit && !SuggestInitializationFixit(S, VD))
|
||||
if (!SuggestInitializationFixit(S, VD))
|
||||
S.Diag(VD->getLocStart(), diag::note_uninit_var_def)
|
||||
<< VD->getDeclName();
|
||||
|
||||
|
|
|
@ -10,9 +10,6 @@ int far(const int& x);
|
|||
int a = a; // no-warning: used to signal intended lack of initialization.
|
||||
int b = b + 1; // expected-warning {{variable 'b' is uninitialized when used within its own initialization}}
|
||||
int c = (c + c); // expected-warning 2 {{variable 'c' is uninitialized when used within its own initialization}}
|
||||
void test() {
|
||||
int d = ({ d + d ;}); // expected-warning {{variable 'd' is uninitialized when used within its own initialization}}
|
||||
}
|
||||
int e = static_cast<long>(e) + 1; // expected-warning {{variable 'e' is uninitialized when used within its own initialization}}
|
||||
int f = foo(f); // expected-warning {{variable 'f' is uninitialized when used within its own initialization}}
|
||||
|
||||
|
@ -28,6 +25,48 @@ int l = k ? l : l; // expected-warning 2{{variable 'l' is uninitialized when us
|
|||
int m = 1 + (k ? m : m); // expected-warning 2{{variable 'm' is uninitialized when used within its own initialization}}
|
||||
int n = -n; // expected-warning {{variable 'n' is uninitialized when used within its own initialization}}
|
||||
|
||||
void test () {
|
||||
int a = a; // no-warning: used to signal intended lack of initialization.
|
||||
int b = b + 1; // expected-warning {{variable 'b' is uninitialized when used within its own initialization}}
|
||||
int c = (c + c); // expected-warning {{variable 'c' is uninitialized when used within its own initialization}}
|
||||
int d = ({ d + d ;}); // expected-warning {{variable 'd' is uninitialized when used within its own initialization}}
|
||||
int e = static_cast<long>(e) + 1; // expected-warning {{variable 'e' is uninitialized when used within its own initialization}}
|
||||
int f = foo(f); // expected-warning {{variable 'f' is uninitialized when used within its own initialization}}
|
||||
|
||||
// Thes don't warn as they don't require the value.
|
||||
int g = sizeof(g);
|
||||
void* ptr = &ptr;
|
||||
int h = bar(&h);
|
||||
int i = boo(i);
|
||||
int j = far(j);
|
||||
int k = __alignof__(k);
|
||||
|
||||
int l = k ? l : l; // FIXME: warn here
|
||||
int m = 1 + (k ? m : m); // FIXME: warn here
|
||||
int n = -n; // expected-warning {{variable 'n' is uninitialized when used within its own initialization}}
|
||||
|
||||
for (;;) {
|
||||
int a = a; // no-warning: used to signal intended lack of initialization.
|
||||
int b = b + 1; // expected-warning {{variable 'b' is uninitialized when used within its own initialization}}
|
||||
int c = (c + c); // expected-warning {{variable 'c' is uninitialized when used within its own initialization}}
|
||||
int d = ({ d + d ;}); // expected-warning {{variable 'd' is uninitialized when used within its own initialization}}
|
||||
int e = static_cast<long>(e) + 1; // expected-warning {{variable 'e' is uninitialized when used within its own initialization}}
|
||||
int f = foo(f); // expected-warning {{variable 'f' is uninitialized when used within its own initialization}}
|
||||
|
||||
// Thes don't warn as they don't require the value.
|
||||
int g = sizeof(g);
|
||||
void* ptr = &ptr;
|
||||
int h = bar(&h);
|
||||
int i = boo(i);
|
||||
int j = far(j);
|
||||
int k = __alignof__(k);
|
||||
|
||||
int l = k ? l : l; // FIXME: warn here
|
||||
int m = 1 + (k ? m : m); // FIXME: warn here
|
||||
int n = -n; // expected-warning {{variable 'n' is uninitialized when used within its own initialization}}
|
||||
}
|
||||
}
|
||||
|
||||
// Test self-references with record types.
|
||||
class A {
|
||||
// Non-POD class.
|
||||
|
|
Loading…
Reference in New Issue