forked from OSchip/llvm-project
Fix PR9624 by explicitly disabling uninitialized warnings for direct self-init:
int x = x; GCC disables its warnings on this construct as a way of indicating that the programmer intentionally wants the variable to be uninitialized. Only the warning on the initializer is turned off in this iteration. This makes the code a lot more ugly, but starts commenting the surprising behavior here. This is a WIP, I want to refactor it substantially for clarity, and to determine whether subsequent warnings should be suppressed or not. llvm-svn: 128894
This commit is contained in:
parent
7522abd3ce
commit
b5d4831f83
|
@ -410,16 +410,6 @@ public:
|
|||
};
|
||||
}
|
||||
|
||||
static bool isSelfInit(ASTContext &Context,
|
||||
const VarDecl *VD, const DeclRefExpr *DR) {
|
||||
if (const Expr *E = VD->getInit()) {
|
||||
ContainsReference CR(Context, DR);
|
||||
CR.Visit(const_cast<Expr*>(E));
|
||||
return CR.doesContainReference();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef std::pair<const Expr*, bool> UninitUse;
|
||||
|
||||
namespace {
|
||||
|
@ -473,17 +463,37 @@ public:
|
|||
for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; ++vi)
|
||||
{
|
||||
const bool isAlwaysUninit = vi->second;
|
||||
bool showDefinition = true;
|
||||
bool isSelfInit = false;
|
||||
|
||||
if (const DeclRefExpr *dr = dyn_cast<DeclRefExpr>(vi->first)) {
|
||||
if (isAlwaysUninit) {
|
||||
if (isSelfInit(S.Context, vd, dr)) {
|
||||
// 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 *E = vd->getInit()) {
|
||||
if (dr == E->IgnoreParenImpCasts())
|
||||
continue;
|
||||
|
||||
ContainsReference CR(S.Context, dr);
|
||||
CR.Visit(const_cast<Expr*>(E));
|
||||
isSelfInit = CR.doesContainReference();
|
||||
}
|
||||
if (isSelfInit) {
|
||||
S.Diag(dr->getLocStart(),
|
||||
diag::warn_uninit_self_reference_in_init)
|
||||
<< vd->getDeclName() << vd->getLocation() << dr->getSourceRange();
|
||||
showDefinition = false;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
S.Diag(dr->getLocStart(), diag::warn_uninit_var)
|
||||
<< vd->getDeclName() << dr->getSourceRange();
|
||||
}
|
||||
|
@ -501,8 +511,9 @@ public:
|
|||
<< vd->getDeclName();
|
||||
}
|
||||
|
||||
// Report where the variable was declared.
|
||||
if (showDefinition)
|
||||
// Report where the variable was declared when the use wasn't within
|
||||
// the initializer of that declaration.
|
||||
if (!isSelfInit)
|
||||
S.Diag(vd->getLocStart(), diag::note_uninit_var_def)
|
||||
<< vd->getDeclName();
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ void test14() {
|
|||
}
|
||||
|
||||
void test15() {
|
||||
int x = x; // expected-warning{{variable 'x' is uninitialized when used within its own initialization}}
|
||||
int x = x; // no-warning: signals intended lack of initialization.
|
||||
}
|
||||
|
||||
// Don't warn in the following example; shows dataflow confluence.
|
||||
|
|
|
@ -7,7 +7,7 @@ int far(const int& x);
|
|||
|
||||
// Test self-references within initializers which are guaranteed to be
|
||||
// uninitialized.
|
||||
int a = a; // FIXME: This doesn't warn!? Seems it doesn't cast 'a' to an RValue.
|
||||
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() {
|
||||
|
|
Loading…
Reference in New Issue