detect C++ errors to fix 2288 and 18770

detect C++ errors to fix 2288 and 18770
gcc/cp/
	PR c++/2288
	PR c++/18770
	* name-lookup.h (enum scope_kind): Add sk_cond.
	* name-lookup.c (pushdecl_maybe_friend): Get scope of shadowed local.
	Detect and report error for redeclaration from for-init or if
	or switch condition.
	(begin_scope): Handle sk_cond.
	* semantics.c (begin_if_stmt): Use sk_cond.
	(begin switch_stmt): Ditto.
gcc/testsuite/
	PR c++/2288
	PR c++/18770
	* g++.old-deja/g++.jason/cond.C: Remove xfails.
	* g++.dg/parse/pr18770.C: New test.
	* g++.dg/cpp0x/range-for5.C: Add dg-error marker.

Co-Authored-By: Nathan Froyd <froydnj@codesourcery.com>

From-SVN: r174307
This commit is contained in:
Janis Johnson 2011-05-26 20:15:22 +00:00 committed by Nathan Froyd
parent 6a1a787e41
commit 1eb2a14d16
8 changed files with 231 additions and 10 deletions

View File

@ -1,3 +1,16 @@
2011-05-26 Janis Johnson <janis187@us.ibm.com>
Nathan Froyd <froydnj@codesourcery.com>
PR c++/2288
PR c++/18770
* name-lookup.h (enum scope_kind): Add sk_cond.
* name-lookup.c (pushdecl_maybe_friend): Get scope of shadowed local.
Detect and report error for redeclaration from for-init or if
or switch condition.
(begin_scope): Handle sk_cond.
* semantics.c (begin_if_stmt): Use sk_cond.
(begin switch_stmt): Ditto.
2011-05-26 Jason Merrill <jason@redhat.com>
PR c++/48211

View File

@ -935,8 +935,15 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
else
{
/* Here to install a non-global value. */
tree oldlocal = innermost_non_namespace_value (name);
tree oldglobal = IDENTIFIER_NAMESPACE_VALUE (name);
tree oldlocal = NULL_TREE;
cxx_scope *oldscope = NULL;
cxx_binding *oldbinding = outer_binding (name, NULL, true);
if (oldbinding)
{
oldlocal = oldbinding->value;
oldscope = oldbinding->scope;
}
if (need_new_binding)
{
@ -1065,6 +1072,20 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
}
}
}
/* Error if redeclaring a local declared in a
for-init-statement or in the condition of an if or
switch statement when the new declaration is in the
outermost block of the controlled statement.
Redeclaring a variable from a for or while condition is
detected elsewhere. */
else if (TREE_CODE (oldlocal) == VAR_DECL
&& oldscope == current_binding_level->level_chain
&& (oldscope->kind == sk_cond
|| oldscope->kind == sk_for))
{
error ("redeclaration of %q#D", x);
error ("%q+#D previously declared here", oldlocal);
}
if (warn_shadow && !nowarn)
{
@ -1424,6 +1445,7 @@ begin_scope (scope_kind kind, tree entity)
case sk_try:
case sk_catch:
case sk_for:
case sk_cond:
case sk_class:
case sk_scoped_enum:
case sk_function_parms:

View File

@ -109,6 +109,8 @@ typedef enum scope_kind {
sk_catch, /* A catch-block. */
sk_for, /* The scope of the variable declared in a
for-init-statement. */
sk_cond, /* The scope of the variable declared in the condition
of an if or switch statement. */
sk_function_parms, /* The scope containing function parameters. */
sk_class, /* The scope containing the members of a class. */
sk_scoped_enum, /* The scope containing the enumertors of a C++0x

View File

@ -656,7 +656,7 @@ tree
begin_if_stmt (void)
{
tree r, scope;
scope = do_pushlevel (sk_block);
scope = do_pushlevel (sk_cond);
r = build_stmt (input_location, IF_STMT, NULL_TREE,
NULL_TREE, NULL_TREE, scope);
begin_cond (&IF_COND (r));
@ -1013,7 +1013,7 @@ begin_switch_stmt (void)
{
tree r, scope;
scope = do_pushlevel (sk_block);
scope = do_pushlevel (sk_cond);
r = build_stmt (input_location, SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE, scope);
begin_cond (&SWITCH_STMT_COND (r));

View File

@ -1,3 +1,12 @@
2011-05-26 Janis Johnson <janis187@us.ibm.com>
Nathan Froyd <froydnj@codesourcery.com>
PR c++/2288
PR c++/18770
* g++.old-deja/g++.jason/cond.C: Remove xfails.
* g++.dg/parse/pr18770.C: New test.
* g++.dg/cpp0x/range-for5.C: Add dg-error marker.
2011-05-26 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/48955

View File

@ -47,8 +47,8 @@ void test1()
//Check the correct scopes
int i;
for (int i : a)
for (int i : a) // { dg-error "previously declared" }
{
int i;
int i; // { dg-error "redeclaration" }
}
}

View File

@ -0,0 +1,175 @@
/* { dg-do compile } */
/* The ISO C++ standard says, in Section 3.3.2 sentence 4, that a name
declared in the for-init-statement or in the condition of an if, for
while, or switch statement can't be redeclared in the outermost block
of the controlled statement. (Note, this is not an error in C.) */
extern void foo (int);
extern int j;
void
e0 (void)
{
for (int i = 0; // { dg-error "previously declared here" "prev" }
i < 10; ++i)
{
int i = 2; // { dg-error "redeclaration" "redecl" }
foo (i);
}
}
void
e1 (void)
{
int i;
for (i = 0;
int k = j; i++) // { dg-error "previously declared here" "prev" }
{
int k = 2; // { dg-error "redeclaration" "redecl" }
foo (k);
}
}
void
e2 (void)
{
if (int i = 1) // { dg-error "previously declared here" "prev" }
{
int i = 2; // { dg-error "redeclaration" "redecl" }
foo (i);
}
}
void
e3 (void)
{
if (int i = 1) // { dg-error "previously declared here" "prev" }
{
foo (i);
}
else
{
int i = 2; // { dg-error "redeclaration" "redecl" }
foo (i);
}
}
void
e4 (void)
{
while (int i = 1) // { dg-error "previously declared here" "prev" }
{
int i = 2; // { dg-error "redeclaration" "redecl" }
foo (i);
}
}
void
e5 (void)
{
switch (int i = j) // { dg-error "previously declared here" "prev" }
{
int i; // { dg-error "redeclaration" "redecl" }
default:
{
i = 2;
foo (i);
}
}
}
void
f0 (void)
{
for (int i = 0; i < 10; ++i)
{
foo (i);
{
int i = 2; // OK, not outermost block.
foo (i);
}
}
}
void
f1 (void)
{
int i;
for (i = 0; int k = j; i++)
{
foo (k);
{
int k = 2; // OK, not outermost block.
foo (k);
}
}
}
void
f2 (void)
{
if (int i = 1)
{
foo (i);
{
int i = 2; // OK, not outermost block.
foo (i);
}
}
}
void
f3 (void)
{
if (int i = 1)
{
foo (i);
}
else
{
foo (i+2);
{
int i = 2; // OK, not outermost block.
foo (i);
}
}
}
void
f4 (void)
{
while (int i = 1)
{
foo (i);
{
int i = 2; // OK, not outermost block.
foo (i);
}
}
}
void
f5 (void)
{
switch (int i = j)
{
default:
{
int i = 2; // OK, not outermost block.
foo (i);
}
}
}
void
f6 (void)
{
int i = 1;
for (int j = 0; j < 10; j++)
{
int i = 2; // OK, not variable from for-init.
foo (i);
}
}

View File

@ -6,14 +6,14 @@ int main()
{
float i;
if (int i = 1) // { dg-error "" "" { xfail *-*-* } } ,
if (int i = 1) // { dg-error "previously" }
{
char i; // { dg-error "" "" { xfail *-*-* } } ,
char i; // { dg-error "redeclaration" }
char j;
}
else
{
short i; // { dg-error "" "" { xfail *-*-* } } ,
short i; // { dg-error "redeclaration" }
char j;
}
@ -27,10 +27,10 @@ int main()
int i; // { dg-error "redeclaration" }
}
switch (int i = 0) // { dg-error "" "" { xfail *-*-* } }
switch (int i = 0) // { dg-error "previously" }
{
default:
int i; // { dg-error "" "" { xfail *-*-* } }
int i; // { dg-error "redeclaration" }
}
if (struct A { operator int () { return 1; } } *foo = new A) // { dg-error "defined" }