Re: [PATCH][4.6] detect C++ errors to fix 2288 and 18770

2011-05-26 Thread Peter Bergner
On Wed, 2011-05-25 at 21:24 -0400, Nathan Froyd wrote:
 On Wed, May 25, 2011 at 03:22:07PM -0400, Nathan Froyd wrote:
  The patch just requires some shuffling of logic to catch issues now;
  below is a version that works for me on the trunk.
  
  This new checking does require modifying g++.dg/cpp0x/range-for5.C.
  
  Tested with g++ testsuite on x86_64-unknown-linux-gnu; tests in progress
  for libstdc++.  OK to commit?
 
 Below is a slightly revised patch that actually adds all the necessary
 dg-error directives to range-for5.C.  Tested the same way; Peter Bergner
 was kind enough to bootstrap and test the previous patch on
 powerpc64-linux-gnu with (almost) clean results as well.

FYI, the revised patch passes bootstrap and regtesting (-m32 and -m64) with
no regressions on powerpc64-linux.

Peter





Re: [PATCH][4.6] detect C++ errors to fix 2288 and 18770

2011-05-26 Thread Jason Merrill

OK for 4.7.

Jason


Re: [PATCH][4.6] detect C++ errors to fix 2288 and 18770

2011-05-25 Thread Nathan Froyd
On Sun, May 22, 2011 at 03:25:41PM -0700, H.J. Lu wrote:
 FWIW, I tried Janis's patch on 4.6 branch and I got
 
 /export/gnu/import/git/gcc/gcc/testsuite/g++.dg/parse/pr18770.C: In
 function 'void e1()':^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.dg/parse/pr18770.C:29:11:
 error: redeclaration of 'int k'^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.dg/parse/pr18770.C:27:12:
 error: 'int k' previously declared here^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.dg/parse/pr18770.C: In
 function 'void e4()':^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.dg/parse/pr18770.C:63:11:
 error: redeclaration of 'int i'^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.dg/parse/pr18770.C:61:14:
 error: 'int i' previously declared here^M
 
 FAIL: g++.dg/parse/pr18770.C prev (test for errors, line 14)
 FAIL: g++.dg/parse/pr18770.C redecl (test for errors, line 17)
 PASS: g++.dg/parse/pr18770.C prev (test for errors, line 27)
 PASS: g++.dg/parse/pr18770.C redecl (test for errors, line 29)
 FAIL: g++.dg/parse/pr18770.C prev (test for errors, line 37)
 FAIL: g++.dg/parse/pr18770.C redecl (test for errors, line 39)
 FAIL: g++.dg/parse/pr18770.C prev (test for errors, line 47)
 FAIL: g++.dg/parse/pr18770.C redecl (test for errors, line 53)
 PASS: g++.dg/parse/pr18770.C prev (test for errors, line 61)
 PASS: g++.dg/parse/pr18770.C redecl (test for errors, line 63)
 FAIL: g++.dg/parse/pr18770.C prev (test for errors, line 71)
 FAIL: g++.dg/parse/pr18770.C redecl (test for errors, line 73)
 PASS: g++.dg/parse/pr18770.C (test for excess errors)
 
 /export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:
 In function 'int main()':^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:22:11:
 error: redeclaration of 'int i'^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:20:14:
 error: 'int i' previously declared here^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:27:11:
 error: redeclaration of 'int i'^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:25:14:
 error: 'int i' previously declared here^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:36:16:
 error: types may not be defined in conditions^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:39:3:
 error: 'A' was not declared in this scope^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:39:5:
 error: expected ';' before 'bar'^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:42:12:
 error: types may not be defined in conditions^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:42:40:
 error: 'one' was not declared in this scope^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:51:14:
 warning: declaration of 'int f()' has 'extern' and is initialized
 [enabled by default]^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:51:18:
 error: function 'int f()' is initialized like a variable^M
 /export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:55:23:
 error: extended initializer lists only available with -std=c++0x or
 -std=gnu++0x^M
 
 FAIL: g++.old-deja/g++.jason/cond.C  (test for errors, line 9)
 FAIL: g++.old-deja/g++.jason/cond.C  (test for errors, line 11)
 FAIL: g++.old-deja/g++.jason/cond.C  (test for errors, line 16)
 PASS: g++.old-deja/g++.jason/cond.C  (test for errors, line 20)
 PASS: g++.old-deja/g++.jason/cond.C  (test for errors, line 22)
 PASS: g++.old-deja/g++.jason/cond.C  (test for errors, line 25)
 PASS: g++.old-deja/g++.jason/cond.C  (test for errors, line 27)
 FAIL: g++.old-deja/g++.jason/cond.C  (test for errors, line 30)
 FAIL: g++.old-deja/g++.jason/cond.C  (test for errors, line 33)
 PASS: g++.old-deja/g++.jason/cond.C  (test for errors, line 36)
 PASS: g++.old-deja/g++.jason/cond.C decl (test for errors, line 39)
 PASS: g++.old-deja/g++.jason/cond.C exp (test for errors, line 39)
 PASS: g++.old-deja/g++.jason/cond.C def (test for errors, line 42)
 PASS: g++.old-deja/g++.jason/cond.C expected (test for errors, line 42)
 PASS: g++.old-deja/g++.jason/cond.C extern (test for warnings, line 51)
 
 The patch no longer catches all problems.

The patch just requires some shuffling of logic to catch issues now;
below is a version that works for me on the trunk.

This new checking does require modifying g++.dg/cpp0x/range-for5.C.  The
new logic of the patch claims that:

  int i;
  for (int i : a)
  {
int i;
  }

is incorrect (the innermost `i' is an erroneous redeclaration).  If you
apply the expansion of range-based for loops from [stmt.ranged]p1, you'd
get something like:

  for (...; ...; ...)
   {
 int i = ...;
 int i;
   }

which is bad.  I believe [basic.scope.local]p4 says much the same thing.

Tested with g++ testsuite on x86_64-unknown-linux-gnu; tests in progress
for libstdc++.  OK to commit?

-Nathan

gcc/cp/
2011-xx-xx  Janis 

Re: [PATCH][4.6] detect C++ errors to fix 2288 and 18770

2011-05-22 Thread Jack Howarth
On Thu, Mar 18, 2010 at 01:50:54PM -0700, Janis Johnson wrote:
 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 (this is not an error in C).  This patch
 detects those errors that were not already detected elsewhere, adds
 a new test, and removes xfails from an existing test.
 
 Tested on powerpc64-linux with bootstrap of all languages but Ada and
 regtest for -m32/-m64.  OK for stage 1 of GCC 4.6?
 
 2010-03-18  Janis Johnson  janis...@us.ibm.com
 
 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.
 
 Index: gcc/cp/name-lookup.h
 ===
 --- gcc/cp/name-lookup.h  (revision 157490)
 +++ gcc/cp/name-lookup.h  (working copy)
 @@ -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
 Index: gcc/cp/name-lookup.c
 ===
 --- gcc/cp/name-lookup.c  (revision 157490)
 +++ gcc/cp/name-lookup.c  (working copy)
 @@ -946,8 +946,15 @@ pushdecl_maybe_friend (tree x, bool is_f
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)
   {
 @@ -1051,6 +1058,21 @@ pushdecl_maybe_friend (tree x, bool is_f
   }
   }
  
 +   /* 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 (oldlocal != NULL_TREE
 + 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);
 + }
 +
 /* Maybe warn if shadowing something else.  */
 else if (warn_shadow  !DECL_EXTERNAL (x)
 /* No shadow warnings for internally generated vars.  */
 @@ -1383,6 +1405,7 @@ begin_scope (scope_kind kind, tree entit
  case sk_try:
  case sk_catch:
  case sk_for:
 +case sk_cond:
  case sk_class:
  case sk_scoped_enum:
  case sk_function_parms:
 Index: gcc/cp/semantics.c
 ===
 --- gcc/cp/semantics.c(revision 157490)
 +++ gcc/cp/semantics.c(working copy)
 @@ -644,7 +644,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);
TREE_CHAIN (r) = scope;
begin_cond (IF_COND (r));
 @@ -929,7 +929,7 @@ begin_switch_stmt (void)
  
r = build_stmt (input_location, SWITCH_STMT, NULL_TREE, NULL_TREE, 
 NULL_TREE);
  
 -  scope = do_pushlevel (sk_block);
 +  scope = do_pushlevel (sk_cond);
TREE_CHAIN (r) = scope;
begin_cond (SWITCH_STMT_COND (r));
  
 Index: gcc/testsuite/g++.old-deja/g++.jason/cond.C
 ===
 --- gcc/testsuite/g++.old-deja/g++.jason/cond.C   (revision 157490)
 +++ gcc/testsuite/g++.old-deja/g++.jason/cond.C   (working copy)
 @@ -6,14 +6,14 @@ int main()
  {

Re: [PATCH][4.6] detect C++ errors to fix 2288 and 18770

2011-05-22 Thread H.J. Lu
On Sun, May 22, 2011 at 2:29 PM, Gerald Pfeifer ger...@pfeifer.com wrote:
 On Sun, 22 May 2011, Jack Howarth wrote:
 2010-03-18  Janis Johnson  janis...@us.ibm.com

 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.
 Any chance we can get this committed to gcc trunk while in 4.7 stage 1
 (since it was already approved for 4.6 stage 1 and never applied...
 http://gcc.gnu.org/ml/gcc-patches/2010-05/msg00264.html). It would be
 nice to have in gcc 4.7 so that other open source projects that only
 build against g++ would be alerted to fix their sources.

 It's my understanding that an approved patch can be committed by anyone
 with write access unless it is retracted or there is some other reason
 not to. Customary that is left to the submitter if she has write access,
 of course.


FWIW, I tried Janis's patch on 4.6 branch and I got

/export/gnu/import/git/gcc/gcc/testsuite/g++.dg/parse/pr18770.C: In
function 'void e1()':^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.dg/parse/pr18770.C:29:11:
error: redeclaration of 'int k'^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.dg/parse/pr18770.C:27:12:
error: 'int k' previously declared here^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.dg/parse/pr18770.C: In
function 'void e4()':^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.dg/parse/pr18770.C:63:11:
error: redeclaration of 'int i'^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.dg/parse/pr18770.C:61:14:
error: 'int i' previously declared here^M

FAIL: g++.dg/parse/pr18770.C prev (test for errors, line 14)
FAIL: g++.dg/parse/pr18770.C redecl (test for errors, line 17)
PASS: g++.dg/parse/pr18770.C prev (test for errors, line 27)
PASS: g++.dg/parse/pr18770.C redecl (test for errors, line 29)
FAIL: g++.dg/parse/pr18770.C prev (test for errors, line 37)
FAIL: g++.dg/parse/pr18770.C redecl (test for errors, line 39)
FAIL: g++.dg/parse/pr18770.C prev (test for errors, line 47)
FAIL: g++.dg/parse/pr18770.C redecl (test for errors, line 53)
PASS: g++.dg/parse/pr18770.C prev (test for errors, line 61)
PASS: g++.dg/parse/pr18770.C redecl (test for errors, line 63)
FAIL: g++.dg/parse/pr18770.C prev (test for errors, line 71)
FAIL: g++.dg/parse/pr18770.C redecl (test for errors, line 73)
PASS: g++.dg/parse/pr18770.C (test for excess errors)

/export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:
In function 'int main()':^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:22:11:
error: redeclaration of 'int i'^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:20:14:
error: 'int i' previously declared here^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:27:11:
error: redeclaration of 'int i'^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:25:14:
error: 'int i' previously declared here^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:36:16:
error: types may not be defined in conditions^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:39:3:
error: 'A' was not declared in this scope^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:39:5:
error: expected ';' before 'bar'^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:42:12:
error: types may not be defined in conditions^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:42:40:
error: 'one' was not declared in this scope^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:51:14:
warning: declaration of 'int f()' has 'extern' and is initialized
[enabled by default]^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:51:18:
error: function 'int f()' is initialized like a variable^M
/export/gnu/import/git/gcc/gcc/testsuite/g++.old-deja/g++.jason/cond.C:55:23:
error: extended initializer lists only available with -std=c++0x or
-std=gnu++0x^M

FAIL: g++.old-deja/g++.jason/cond.C  (test for errors, line 9)
FAIL: g++.old-deja/g++.jason/cond.C  (test for errors, line 11)
FAIL: g++.old-deja/g++.jason/cond.C  (test for errors, line 16)
PASS: g++.old-deja/g++.jason/cond.C  (test for errors, line 20)
PASS: g++.old-deja/g++.jason/cond.C  (test for errors, line 22)
PASS: g++.old-deja/g++.jason/cond.C  (test for errors, line 25)
PASS: g++.old-deja/g++.jason/cond.C  (test for errors, line 27)
FAIL: g++.old-deja/g++.jason/cond.C  (test for errors, line 30)
FAIL: g++.old-deja/g++.jason/cond.C  (test for errors, line 33)
PASS: