From 8ac9ea616e01991beb4164c1a44647763d33302c Mon Sep 17 00:00:00 2001 From: Neil Booth Date: Thu, 8 Nov 2001 19:04:43 +0000 Subject: [PATCH] decl.c (shadow_warning): New function. * cp/decl.c (shadow_warning): New function. (pushdecl): Improve -Wshadow warnings. Don't give both a warning and an error when a block scope decl shadows a parameter. * g++.dg/warn/Wshadow-1.C: New tests. * g++.old-deja/g++.mike/for3.C: Update. From-SVN: r46852 --- gcc/ChangeLog | 6 ++ gcc/cp/decl.c | 75 ++++++++++++++-------- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.dg/warn/Wshadow-1.C | 42 ++++++++++++ gcc/testsuite/g++.old-deja/g++.mike/for3.C | 6 +- 5 files changed, 104 insertions(+), 30 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/Wshadow-1.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d442d111c3a..b410b511bf0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2001-11-08 Neil Booth + + * cp/decl.c (shadow_warning): New function. + (pushdecl): Improve -Wshadow warnings. Don't give both a warning + and an error when a block scope decl shadows a parameter. + 2001-11-08 Richard Henderson * config/fp-bit.h (usi_to_float): Define for US_SOFTWARE_GOFAST diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 1b3fc9e83f4..a210a7b830f 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -147,6 +147,7 @@ static tree push_cp_library_fn PARAMS ((enum tree_code, tree)); static tree build_cp_library_fn PARAMS ((tree, enum tree_code, tree)); static void store_parm_decls PARAMS ((tree)); static int cp_missing_noreturn_ok_p PARAMS ((tree)); +static void shadow_warning PARAMS ((const char *, tree, tree)); #if defined (DEBUG_CP_BINDING_LEVELS) static void indent PARAMS ((void)); @@ -3788,6 +3789,20 @@ duplicate_decls (newdecl, olddecl) return 1; } +/* Output a -Wshadow warning MSGID, if non-NULL, and give the location + of the previous declaration. */ +static void +shadow_warning (msgid, name, decl) + const char *msgid; + tree name, decl; +{ + warning ("declaration of `%s' shadows %s", IDENTIFIER_POINTER (name), msgid); + warning_with_file_and_line (DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl), + "shadowed declaration is here"); +} + + /* Record a decl-node X as belonging to the current lexical scope. Check for errors (such as an incompatible declaration for the same name already seen in the same scope). @@ -4173,47 +4188,53 @@ pushdecl (x) if (oldlocal != NULL_TREE && !DECL_EXTERNAL (x) /* Inline decls shadow nothing. */ && !DECL_FROM_INLINE (x) - && TREE_CODE (oldlocal) == PARM_DECL - /* Don't complain if it's from an enclosing function. */ - && DECL_CONTEXT (oldlocal) == current_function_decl - && TREE_CODE (x) != PARM_DECL) + && TREE_CODE (oldlocal) == PARM_DECL) { - /* Go to where the parms should be and see if we - find them there. */ - struct binding_level *b = current_binding_level->level_chain; + bool err = false; - if (cleanup_label) - b = b->level_chain; + /* Don't complain if it's from an enclosing function. */ + if (DECL_CONTEXT (oldlocal) == current_function_decl + && TREE_CODE (x) != PARM_DECL) + { + /* Go to where the parms should be and see if we find + them there. */ + struct binding_level *b = current_binding_level->level_chain; - /* ARM $8.3 */ - if (b->parm_flag == 1) - cp_error ("declaration of `%#D' shadows a parameter", name); + if (cleanup_label) + b = b->level_chain; + + /* ARM $8.3 */ + if (b->parm_flag == 1) + { + cp_error ("declaration of `%#D' shadows a parameter", + name); + err = true; + } + } + + if (warn_shadow && !err) + shadow_warning ("a parameter", name, oldlocal); } /* Maybe warn if shadowing something else. */ - if (warn_shadow && !DECL_EXTERNAL (x) - /* Inline decls shadow nothing. */ - && !DECL_FROM_INLINE (x) + else if (warn_shadow && !DECL_EXTERNAL (x) /* No shadow warnings for internally generated vars. */ && ! DECL_ARTIFICIAL (x) /* No shadow warnings for vars made for inlining. */ && ! DECL_FROM_INLINE (x)) { - if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL) - warning ("declaration of `%s' shadows a parameter", - IDENTIFIER_POINTER (name)); - else if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE + if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE && current_class_ptr && !TREE_STATIC (name)) - warning ("declaration of `%s' shadows a member of `this'", - IDENTIFIER_POINTER (name)); - else if (oldlocal != NULL_TREE) - warning ("declaration of `%s' shadows previous local", - IDENTIFIER_POINTER (name)); - else if (oldglobal != NULL_TREE) + cp_warning ("declaration of `%s' shadows a member of `this'", + IDENTIFIER_POINTER (name)); + else if (oldlocal != NULL_TREE + && TREE_CODE (oldlocal) == VAR_DECL) + shadow_warning ("a previous local", name, oldlocal); + else if (oldglobal != NULL_TREE + && TREE_CODE (oldglobal) == VAR_DECL) /* XXX shadow warnings in outer-more namespaces */ - warning ("declaration of `%s' shadows global declaration", - IDENTIFIER_POINTER (name)); + shadow_warning ("a global declaration", name, oldglobal); } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d11a53d18b5..cd31ce70834 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2001-11-08 Neil Booth + + * g++.dg/warn/Wshadow-1.C: New tests. + * g++.old-deja/g++.mike/for3.C: Update. + 2001-11-06 Joseph S. Myers * gcc.dg/c90-array-lval-1.c, gcc.dg/c90-array-lval-2.c, diff --git a/gcc/testsuite/g++.dg/warn/Wshadow-1.C b/gcc/testsuite/g++.dg/warn/Wshadow-1.C new file mode 100644 index 00000000000..b7d95e5b7d7 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wshadow-1.C @@ -0,0 +1,42 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. */ + +/* { dg-do compile } */ +/* { dg-options -Wshadow } */ + +/* Source: Neil Booth, 3 Nov 2001, and PR 16, 713. -Wshadow was + giving a bunch of warnings we didn't want, and wasn't giving the + location of the shadowed variable. */ + +struct status // { dg-bogus "shadowed declaration" } +{ + int member; + void foo2 (); + + inline static int foo3 (int member) // { dg-bogus "shadows" } + { + return member; + } +}; + +int decl1; // { dg-warning "shadowed declaration" } +int decl2; // { dg-warning "shadowed declaration" } +void foo (struct status &status,// { dg-bogus "shadows a global decl" } + double decl1) +{ // { dg-warning "shadows a global decl" } +} + +void foo1 (int d) +{ + double d; // { dg-error "shadows a parameter" } +} + +// { dg-error "In member function" "ignored" { target *-*-* } 0 } +void status::foo2 () +{ + int member; // { dg-warning "shadows a member" } + int decl2; // { dg-warning "shadows a global decl" } + int local; // { dg-warning "shadowed declaration" } + { + int local; // { dg-warning "shadows a previous local" } + } +} diff --git a/gcc/testsuite/g++.old-deja/g++.mike/for3.C b/gcc/testsuite/g++.old-deja/g++.mike/for3.C index a8276a4133b..7e88d7e5bae 100644 --- a/gcc/testsuite/g++.old-deja/g++.mike/for3.C +++ b/gcc/testsuite/g++.old-deja/g++.mike/for3.C @@ -1,9 +1,9 @@ // Special g++ Options: -Wshadow int -main(int i) { - for(int i=1; i < 3; i++); // WARNING - shadows parm - for(int i=1; i < 3; i++); // WARNING - shadows parm +main(int i) { // WARNING - shadowed decl + for(int i=1; i < 3; i++); // WARNING - declaration of + for(int i=1; i < 3; i++); // WARNING - declaration of for(int j=1; j < 3; j++); for(int j=1; j < 3; j++); }