public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [RFC PATCH] c++: Diagnose [basic.scope.block]/2 violations even for block externs [PR52953]
@ 2023-08-31  8:08 Jakub Jelinek
  2023-08-31 21:46 ` Jason Merrill
  0 siblings, 1 reply; 4+ messages in thread
From: Jakub Jelinek @ 2023-08-31  8:08 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

Hi!

C++17 had in [basic.block.scope]/2
"A parameter name shall not be redeclared in the outermost block of the function
definition nor in the outermost block of any handler associated with a
function-try-block."
and in [basic.block.scope]/4 similar rule for selection/iteration
statements.  My reading of that is that it applied even for block local
externs in all those spots, while they declare something at namespace scope,
the redeclaration happens in that outermost block etc. and introduces names
into that.
Those wordings seemed to have been moved somewhere else in C++20, but what's
worse, they were moved back and completely rewritten in
P1787R6: Declarations and where to find them
which has been applied as a DR (but admittedly, we don't claim yet to
implement that).
The current wording at https://eel.is/c++draft/basic.scope#block-2
and https://eel.is/c++draft/basic.scope#scope-2.10 seem to imply at least
to me that it doesn't apply to extern block local decls because their
target scope is the namespace scope and [basic.scope.block]/2 says
"and whose target scope is the block scope"...
Now, it is unclear if that is actually the intent or not.

There seems to be quite large implementation divergence on this as well.

Unpatched g++ e.g. on the redeclaration-5.C testcase diagnoses just
lines 55,58,67,70 (i.e. where the previous declaration is in for's
condition).

clang++ trunk diagnoses just lines 8 and 27, i.e. redeclaration in the
function body vs. parameter both in normal fn and lambda (but not e.g.
function-try-block and others, including ctors, but it diagnoses those
for non-extern decls).

ICC 19 diagnoses lines 8,32,38,41,45,52,55,58,61,64,67,70,76.

And MSCV trunk diagnoses 8,27,32,38,41,45,48,52,55,58,67,70,76,87,100,137
although the last 4 are just warnings.

g++ with the patch diagnoses
8,15,27,32,38,41,45,48,52,55,58,61,64,67,70,76,87,100,121,137
as the dg-error directives test.

So, I'm not really sure what to do.  Intuitively the patch seems right
because even block externs redeclare stuff and change meaning of the
identifiers and void foo () { int i; extern int i (int); } is rejected
by all compilers.

2023-08-31  Jakub Jelinek  <jakub@redhat.com>

	PR c++/52953
	* name-lookup.cc (check_local_shadow): Defer punting on
	DECL_EXTERNAL (decl) from the start of function to right before
	the -Wshadow* checks.

	* g++.dg/diagnostic/redeclaration-4.C: New test.
	* g++.dg/diagnostic/redeclaration-5.C: New test.

--- gcc/cp/name-lookup.cc.jj	2023-08-30 20:07:18.584830291 +0200
+++ gcc/cp/name-lookup.cc	2023-08-30 20:01:05.796967755 +0200
@@ -3096,10 +3096,6 @@ check_local_shadow (tree decl)
   if (TREE_CODE (decl) == PARM_DECL && !DECL_CONTEXT (decl))
     return;
 
-  /* External decls are something else.  */
-  if (DECL_EXTERNAL (decl))
-    return;
-
   tree old = NULL_TREE;
   cp_binding_level *old_scope = NULL;
   if (cxx_binding *binding = outer_binding (DECL_NAME (decl), NULL, true))
@@ -3219,6 +3215,9 @@ check_local_shadow (tree decl)
 	  return;
 	}
 
+      if (DECL_EXTERNAL (decl))
+	return;
+
       /* If '-Wshadow=compatible-local' is specified without other
 	 -Wshadow= flags, we will warn only when the type of the
 	 shadowing variable (DECL) can be converted to that of the
@@ -3274,6 +3273,9 @@ check_local_shadow (tree decl)
       return;
     }
 
+  if (DECL_EXTERNAL (decl))
+    return;
+
   if (!warn_shadow)
     return;
 
--- gcc/testsuite/g++.dg/diagnostic/redeclaration-4.C.jj	2023-08-30 20:01:37.013537549 +0200
+++ gcc/testsuite/g++.dg/diagnostic/redeclaration-4.C	2023-08-30 20:12:03.763900190 +0200
@@ -0,0 +1,167 @@
+// PR c++/52953
+// { dg-do compile }
+// { dg-options "-pedantic-errors -Wno-switch-unreachable" }
+
+void
+foo (int x)				// { dg-message "'int x' previously declared here" }
+{
+  extern int x;				// { dg-error "declaration of 'int x' shadows a parameter" }
+}
+
+void
+bar (int x)				// { dg-message "'int x' previously declared here" }
+try
+{
+  extern int x;				// { dg-error "declaration of 'int x' shadows a parameter" }
+}
+catch (...)
+{
+}
+
+volatile int v;
+
+void
+baz ()
+{
+#if __cplusplus >= 201103L
+  auto f = [] (int x) { extern int x; };// { dg-error "declaration of 'int x' shadows a parameter" "" { target c++11 } }
+					// { dg-message "'int x' previously declared here" "" { target c++11 } .-1 }
+#endif
+  if (int x = 1)			// { dg-message "'int x' previously declared here" }
+    {
+      extern int x;			// { dg-error "redeclaration of 'int x'" }
+    }
+  if (int x = 0)			// { dg-message "'int x' previously declared here" }
+    ;
+  else
+    {
+      extern int x;			// { dg-error "redeclaration of 'int x'" }
+    }
+  if (int x = 1)			// { dg-message "'int x' previously declared here" }
+    extern int x;			// { dg-error "redeclaration of 'int x'" }
+  if (int x = 0)			// { dg-message "'int x' previously declared here" }
+    ;
+  else
+    extern int x;			// { dg-error "redeclaration of 'int x'" }
+  switch (int x = 1)			// { dg-message "'int x' previously declared here" }
+    {
+      extern int x;			// { dg-error "redeclaration of 'int x'" }
+    default:;
+    }
+  switch (int x = 1)			// { dg-message "'int x' previously declared here" }
+    extern int x;			// { dg-error "redeclaration of 'int x'" }
+  while (int x = v)
+    {
+      extern int x;			// { dg-error "'int x' conflicts with a previous declaration" }
+    }
+  while (int x = v)
+    extern int x;			// { dg-error "'int x' conflicts with a previous declaration" }
+  for (int x = v; x; ++x)		// { dg-message "'int x' previously declared here" }
+    {
+      extern int x;			// { dg-error "redeclaration of 'int x'" }
+    }
+  for (int x = v; x; ++x)		// { dg-message "'int x' previously declared here" }
+    extern int x;			// { dg-error "redeclaration of 'int x'" }
+  for (; int x = v; )
+    {
+      extern int x;			// { dg-error "'int x' conflicts with a previous declaration" }
+    }
+  for (; int x = v; )
+    extern int x;			// { dg-error "'int x' conflicts with a previous declaration" }
+  try
+    {
+    }
+  catch (int x)				// { dg-message "'int x' previously declared here" }
+    {
+      extern int x;			// { dg-error "redeclaration of 'int x'" }
+    }
+}
+
+void
+corge (int x)				// { dg-message "'int x' previously declared here" }
+try
+{
+}
+catch (...)
+{
+  extern int x;				// { dg-error "redeclaration of 'int x'" }
+}
+
+void
+fred (int x)				// { dg-message "'int x' previously declared here" }
+try
+{
+}
+catch (int)
+{
+}
+catch (long)
+{
+  extern int x;				// { dg-error "redeclaration of 'int x'" }
+}
+
+void
+garply (int x)
+{
+  try
+    {
+      extern int x;
+    }
+  catch (...)
+    {
+      extern int x;
+    }
+}
+
+struct S
+{
+  S (int x)				// { dg-message "'int x' previously declared here" }
+  try : s (x)
+  {
+    extern int x;				// { dg-error "declaration of 'int x' shadows a parameter" }
+  }
+  catch (...)
+  {
+  }
+  int s;
+};
+
+struct T
+{
+  T (int x)				// { dg-message "'int x' previously declared here" }
+  try : t (x)
+  {
+  }
+  catch (...)
+  {
+    extern int x;				// { dg-error "redeclaration of 'int x'" }
+  }
+  int t;
+};
+
+struct U
+{
+  U (int x) : u (x)
+  {
+    try
+    {
+      extern int x;
+    }
+    catch (...)
+    {
+      extern int x;
+    }
+  }
+  int u;
+};
+
+struct V
+{
+  V (int x) : v (x)
+  {
+    {
+      extern int x;
+    }
+  }
+  int v;
+};
--- gcc/testsuite/g++.dg/diagnostic/redeclaration-5.C.jj	2023-08-30 20:03:56.662613023 +0200
+++ gcc/testsuite/g++.dg/diagnostic/redeclaration-5.C	2023-08-30 20:16:00.749641990 +0200
@@ -0,0 +1,167 @@
+// PR c++/52953
+// { dg-do compile }
+// { dg-options "-pedantic-errors -Wno-switch-unreachable" }
+
+void
+foo (int x)				// { dg-message "'int x' previously declared here" }
+{
+  extern int x (int);			// { dg-error "declaration of 'int x\\\(int\\\)' shadows a parameter" }
+}
+
+void
+bar (int x)				// { dg-message "'int x' previously declared here" }
+try
+{
+  extern int x (int);			// { dg-error "declaration of 'int x\\\(int\\\)' shadows a parameter" }
+}
+catch (...)
+{
+}
+
+volatile int v;
+
+void
+baz ()
+{
+#if __cplusplus >= 201103L
+  auto f = [] (int x) { extern int x (int); };// { dg-error "declaration of 'int x\\\(int\\\)' shadows a parameter" "" { target c++11 } }
+					// { dg-message "'int x' previously declared here" "" { target c++11 } .-1 }
+#endif
+  if (int x = 1)			// { dg-message "'int x' previously declared here" }
+    {
+      extern int x (int);		// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+    }
+  if (int x = 0)			// { dg-message "'int x' previously declared here" }
+    ;
+  else
+    {
+      extern int x (int);		// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+    }
+  if (int x = 1)			// { dg-message "'int x' previously declared here" }
+    extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+  if (int x = 0)			// { dg-message "'int x' previously declared here" }
+    ;
+  else
+    extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+  switch (int x = 1)			// { dg-message "'int x' previously declared here" }
+    {
+      extern int x (int);		// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+    default:;
+    }
+  switch (int x = 1)			// { dg-message "'int x' previously declared here" }
+    extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+  while (int x = v)
+    {
+      extern int x (int);		// { dg-error "'int x\\\(int\\\)' redeclared as different kind of entity" }
+    }
+  while (int x = v)
+    extern int x (int);			// { dg-error "'int x\\\(int\\\)' redeclared as different kind of entity" }
+  for (int x = v; x; ++x)		// { dg-message "'int x' previously declared here" }
+    {
+      extern int x (int);		// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+    }
+  for (int x = v; x; ++x)		// { dg-message "'int x' previously declared here" }
+    extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+  for (; int x = v; )
+    {
+      extern int x (int);		// { dg-error "'int x\\\(int\\\)' redeclared as different kind of entity" }
+    }
+  for (; int x = v; )
+    extern int x (int);			// { dg-error "'int x\\\(int\\\)' redeclared as different kind of entity" }
+  try
+    {
+    }
+  catch (int x)				// { dg-message "'int x' previously declared here" }
+    {
+      extern int x (int);		// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+    }
+}
+
+void
+corge (int x)				// { dg-message "'int x' previously declared here" }
+try
+{
+}
+catch (...)
+{
+  extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+}
+
+void
+fred (int x)				// { dg-message "'int x' previously declared here" }
+try
+{
+}
+catch (int)
+{
+}
+catch (long)
+{
+  extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+}
+
+void
+garply (int x)
+{
+  try
+    {
+      extern int x (int);
+    }
+  catch (...)
+    {
+      extern int x (int);
+    }
+}
+
+struct S
+{
+  S (int x)				// { dg-message "'int x' previously declared here" }
+  try : s (x)
+  {
+    extern int x (int);			// { dg-error "declaration of 'int x\\\(int\\\)' shadows a parameter" }
+  }
+  catch (...)
+  {
+  }
+  int s;
+};
+
+struct T
+{
+  T (int x)				// { dg-message "'int x' previously declared here" }
+  try : t (x)
+  {
+  }
+  catch (...)
+  {
+    extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+  }
+  int t;
+};
+
+struct U
+{
+  U (int x) : u (x)
+  {
+    try
+    {
+      extern int x (int);
+    }
+    catch (...)
+    {
+      extern int x (int);
+    }
+  }
+  int u;
+};
+
+struct V
+{
+  V (int x) : v (x)
+  {
+    {
+      extern int x (int);
+    }
+  }
+  int v;
+};

	Jakub


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC PATCH] c++: Diagnose [basic.scope.block]/2 violations even for block externs [PR52953]
  2023-08-31  8:08 [RFC PATCH] c++: Diagnose [basic.scope.block]/2 violations even for block externs [PR52953] Jakub Jelinek
@ 2023-08-31 21:46 ` Jason Merrill
  2023-09-01 13:34   ` [PATCH] c++, v2: " Jakub Jelinek
  0 siblings, 1 reply; 4+ messages in thread
From: Jason Merrill @ 2023-08-31 21:46 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

On 8/31/23 04:08, Jakub Jelinek wrote:
> Hi!
> 
> C++17 had in [basic.block.scope]/2
> "A parameter name shall not be redeclared in the outermost block of the function
> definition nor in the outermost block of any handler associated with a
> function-try-block."
> and in [basic.block.scope]/4 similar rule for selection/iteration
> statements.  My reading of that is that it applied even for block local
> externs in all those spots, while they declare something at namespace scope,
> the redeclaration happens in that outermost block etc. and introduces names
> into that.
> Those wordings seemed to have been moved somewhere else in C++20, but what's
> worse, they were moved back and completely rewritten in
> P1787R6: Declarations and where to find them
> which has been applied as a DR (but admittedly, we don't claim yet to
> implement that).
> The current wording at https://eel.is/c++draft/basic.scope#block-2
> and https://eel.is/c++draft/basic.scope#scope-2.10 seem to imply at least
> to me that it doesn't apply to extern block local decls because their
> target scope is the namespace scope and [basic.scope.block]/2 says
> "and whose target scope is the block scope"...
> Now, it is unclear if that is actually the intent or not.

Yes, I suspect that should be

If a declaration that is not a name-independent declaration and 
<del>whose target scope is</del><ins>that binds a name in</ins> the 
block scope S of a

which seems to also be needed to prohibit the already-diagnosed

void f(int i) { union { int i; }; }
void g(int i) { enum { i }; }

I've suggested this to Core.

> There seems to be quite large implementation divergence on this as well.
> 
> Unpatched g++ e.g. on the redeclaration-5.C testcase diagnoses just
> lines 55,58,67,70 (i.e. where the previous declaration is in for's
> condition).
> 
> clang++ trunk diagnoses just lines 8 and 27, i.e. redeclaration in the
> function body vs. parameter both in normal fn and lambda (but not e.g.
> function-try-block and others, including ctors, but it diagnoses those
> for non-extern decls).
> 
> ICC 19 diagnoses lines 8,32,38,41,45,52,55,58,61,64,67,70,76.
> 
> And MSCV trunk diagnoses 8,27,32,38,41,45,48,52,55,58,67,70,76,87,100,137
> although the last 4 are just warnings.
> 
> g++ with the patch diagnoses
> 8,15,27,32,38,41,45,48,52,55,58,61,64,67,70,76,87,100,121,137
> as the dg-error directives test.
> 
> So, I'm not really sure what to do.  Intuitively the patch seems right
> because even block externs redeclare stuff and change meaning of the
> identifiers and void foo () { int i; extern int i (int); } is rejected
> by all compilers.

I think this direction makes sense, though we might pedwarn on these 
rather than error to reduce possible breakage.

> 2023-08-31  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR c++/52953
> 	* name-lookup.cc (check_local_shadow): Defer punting on
> 	DECL_EXTERNAL (decl) from the start of function to right before
> 	the -Wshadow* checks.

Don't we want to consider externs for the -Wshadow* checks as well?

Jason


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] c++, v2: Diagnose [basic.scope.block]/2 violations even for block externs [PR52953]
  2023-08-31 21:46 ` Jason Merrill
@ 2023-09-01 13:34   ` Jakub Jelinek
  2023-09-05 14:00     ` Jason Merrill
  0 siblings, 1 reply; 4+ messages in thread
From: Jakub Jelinek @ 2023-09-01 13:34 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

On Thu, Aug 31, 2023 at 05:46:28PM -0400, Jason Merrill wrote:
> I've suggested this to Core.

Thanks.

> > So, I'm not really sure what to do.  Intuitively the patch seems right
> > because even block externs redeclare stuff and change meaning of the
> > identifiers and void foo () { int i; extern int i (int); } is rejected
> > by all compilers.
> 
> I think this direction makes sense, though we might pedwarn on these rather
> than error to reduce possible breakage.

It wasn't clear to me whether you want to make those pedwarns just for the
DECL_EXTERNAL cases, ones that actually changed, or all others as well
(which were errors or permerrors depending on the case).
I've implemented the former, kept existing behavior of !DECL_EXTERNAL.

> > 2023-08-31  Jakub Jelinek  <jakub@redhat.com>
> > 
> > 	PR c++/52953
> > 	* name-lookup.cc (check_local_shadow): Defer punting on
> > 	DECL_EXTERNAL (decl) from the start of function to right before
> > 	the -Wshadow* checks.
> 
> Don't we want to consider externs for the -Wshadow* checks as well?

I think that is a good idea (though dunno how much it will trigger in
real-world), but there is one case I've excluded, the global variable
shadowing case, because warning that
int z;
void foo () { extern int z; z = 1; }
shadows the global var would be incorrect, it is the same var.
It is true that
int y; namespace N { void bar () { extern int y; y = 1; } }
shadows ::y but it is unclear how to differentiate those two cases with
the information we have at check_local_shadow time.

I've also found one spot which wasn't using auto_diagnostic_group d;
on a pair of error_at/inform.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2023-09-01  Jakub Jelinek  <jakub@redhat.com>

	PR c++/52953
	* name-lookup.cc (check_local_shadow): Don't punt early for
	DECL_EXTERNAL decls, instead just disable the shadowing of namespace
	decls check for those and emit a pedwarn rather than error_at for
	those.  Add missing auto_diagnostic_group.  Formatting fix.

	* g++.dg/diagnostic/redeclaration-4.C: New test.
	* g++.dg/diagnostic/redeclaration-5.C: New test.
	* g++.dg/warn/Wshadow-19.C: New test.

--- gcc/cp/name-lookup.cc.jj	2023-09-01 10:21:03.658118594 +0200
+++ gcc/cp/name-lookup.cc	2023-09-01 11:30:10.868516494 +0200
@@ -3096,10 +3096,6 @@ check_local_shadow (tree decl)
   if (TREE_CODE (decl) == PARM_DECL && !DECL_CONTEXT (decl))
     return;
 
-  /* External decls are something else.  */
-  if (DECL_EXTERNAL (decl))
-    return;
-
   tree old = NULL_TREE;
   cp_binding_level *old_scope = NULL;
   if (cxx_binding *binding = outer_binding (DECL_NAME (decl), NULL, true))
@@ -3130,11 +3126,9 @@ check_local_shadow (tree decl)
 	      && DECL_CONTEXT (old) == lambda_function (current_lambda_expr ())
 	      && TREE_CODE (old) == PARM_DECL
 	      && DECL_NAME (decl) != this_identifier)
-	    {
-	      error_at (DECL_SOURCE_LOCATION (old),
-			"lambda parameter %qD "
-			"previously declared as a capture", old);
-	    }
+	    error_at (DECL_SOURCE_LOCATION (old),
+		      "lambda parameter %qD "
+		      "previously declared as a capture", old);
 	  return;
 	}
       /* Don't complain if it's from an enclosing function.  */
@@ -3156,10 +3150,18 @@ check_local_shadow (tree decl)
 	     in the outermost block of the function definition.  */
 	  if (b->kind == sk_function_parms)
 	    {
-	      error_at (DECL_SOURCE_LOCATION (decl),
-			"declaration of %q#D shadows a parameter", decl);
-	      inform (DECL_SOURCE_LOCATION (old),
-		      "%q#D previously declared here", old);
+	      auto_diagnostic_group d;
+	      bool emit = true;
+	      if (DECL_EXTERNAL (decl))
+		emit = pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic,
+				"declaration of %q#D shadows a parameter",
+				decl);
+	      else
+		error_at (DECL_SOURCE_LOCATION (decl),
+			  "declaration of %q#D shadows a parameter", decl);
+	      if (emit)
+		inform (DECL_SOURCE_LOCATION (old),
+			"%q#D previously declared here", old);
 	      return;
 	    }
 	}
@@ -3185,10 +3187,16 @@ check_local_shadow (tree decl)
 	       && (old_scope->kind == sk_cond || old_scope->kind == sk_for))
 	{
 	  auto_diagnostic_group d;
-	  error_at (DECL_SOURCE_LOCATION (decl),
-		    "redeclaration of %q#D", decl);
-	  inform (DECL_SOURCE_LOCATION (old),
-		  "%q#D previously declared here", old);
+	  bool emit = true;
+	  if (DECL_EXTERNAL (decl))
+	    emit = pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic,
+			    "redeclaration of %q#D", decl);
+	  else
+	    error_at (DECL_SOURCE_LOCATION (decl),
+		      "redeclaration of %q#D", decl);
+	  if (emit)
+	    inform (DECL_SOURCE_LOCATION (old),
+		    "%q#D previously declared here", old);
 	  return;
 	}
       /* C++11:
@@ -3314,6 +3322,7 @@ check_local_shadow (tree decl)
 	  || (TREE_CODE (old) == TYPE_DECL
 	      && (!DECL_ARTIFICIAL (old)
 		  || TREE_CODE (decl) == TYPE_DECL)))
+      && !DECL_EXTERNAL (decl)
       && !instantiating_current_function_p ()
       && !warning_suppressed_p (decl, OPT_Wshadow))
     /* XXX shadow warnings in outer-more namespaces */
--- gcc/testsuite/g++.dg/diagnostic/redeclaration-4.C.jj	2023-09-01 10:46:15.646025458 +0200
+++ gcc/testsuite/g++.dg/diagnostic/redeclaration-4.C	2023-09-01 10:46:15.646025458 +0200
@@ -0,0 +1,167 @@
+// PR c++/52953
+// { dg-do compile }
+// { dg-options "-pedantic-errors -Wno-switch-unreachable" }
+
+void
+foo (int x)				// { dg-message "'int x' previously declared here" }
+{
+  extern int x;				// { dg-error "declaration of 'int x' shadows a parameter" }
+}
+
+void
+bar (int x)				// { dg-message "'int x' previously declared here" }
+try
+{
+  extern int x;				// { dg-error "declaration of 'int x' shadows a parameter" }
+}
+catch (...)
+{
+}
+
+volatile int v;
+
+void
+baz ()
+{
+#if __cplusplus >= 201103L
+  auto f = [] (int x) { extern int x; };// { dg-error "declaration of 'int x' shadows a parameter" "" { target c++11 } }
+					// { dg-message "'int x' previously declared here" "" { target c++11 } .-1 }
+#endif
+  if (int x = 1)			// { dg-message "'int x' previously declared here" }
+    {
+      extern int x;			// { dg-error "redeclaration of 'int x'" }
+    }
+  if (int x = 0)			// { dg-message "'int x' previously declared here" }
+    ;
+  else
+    {
+      extern int x;			// { dg-error "redeclaration of 'int x'" }
+    }
+  if (int x = 1)			// { dg-message "'int x' previously declared here" }
+    extern int x;			// { dg-error "redeclaration of 'int x'" }
+  if (int x = 0)			// { dg-message "'int x' previously declared here" }
+    ;
+  else
+    extern int x;			// { dg-error "redeclaration of 'int x'" }
+  switch (int x = 1)			// { dg-message "'int x' previously declared here" }
+    {
+      extern int x;			// { dg-error "redeclaration of 'int x'" }
+    default:;
+    }
+  switch (int x = 1)			// { dg-message "'int x' previously declared here" }
+    extern int x;			// { dg-error "redeclaration of 'int x'" }
+  while (int x = v)
+    {
+      extern int x;			// { dg-error "'int x' conflicts with a previous declaration" }
+    }
+  while (int x = v)
+    extern int x;			// { dg-error "'int x' conflicts with a previous declaration" }
+  for (int x = v; x; ++x)		// { dg-message "'int x' previously declared here" }
+    {
+      extern int x;			// { dg-error "redeclaration of 'int x'" }
+    }
+  for (int x = v; x; ++x)		// { dg-message "'int x' previously declared here" }
+    extern int x;			// { dg-error "redeclaration of 'int x'" }
+  for (; int x = v; )
+    {
+      extern int x;			// { dg-error "'int x' conflicts with a previous declaration" }
+    }
+  for (; int x = v; )
+    extern int x;			// { dg-error "'int x' conflicts with a previous declaration" }
+  try
+    {
+    }
+  catch (int x)				// { dg-message "'int x' previously declared here" }
+    {
+      extern int x;			// { dg-error "redeclaration of 'int x'" }
+    }
+}
+
+void
+corge (int x)				// { dg-message "'int x' previously declared here" }
+try
+{
+}
+catch (...)
+{
+  extern int x;				// { dg-error "redeclaration of 'int x'" }
+}
+
+void
+fred (int x)				// { dg-message "'int x' previously declared here" }
+try
+{
+}
+catch (int)
+{
+}
+catch (long)
+{
+  extern int x;				// { dg-error "redeclaration of 'int x'" }
+}
+
+void
+garply (int x)
+{
+  try
+    {
+      extern int x;
+    }
+  catch (...)
+    {
+      extern int x;
+    }
+}
+
+struct S
+{
+  S (int x)				// { dg-message "'int x' previously declared here" }
+  try : s (x)
+  {
+    extern int x;				// { dg-error "declaration of 'int x' shadows a parameter" }
+  }
+  catch (...)
+  {
+  }
+  int s;
+};
+
+struct T
+{
+  T (int x)				// { dg-message "'int x' previously declared here" }
+  try : t (x)
+  {
+  }
+  catch (...)
+  {
+    extern int x;				// { dg-error "redeclaration of 'int x'" }
+  }
+  int t;
+};
+
+struct U
+{
+  U (int x) : u (x)
+  {
+    try
+    {
+      extern int x;
+    }
+    catch (...)
+    {
+      extern int x;
+    }
+  }
+  int u;
+};
+
+struct V
+{
+  V (int x) : v (x)
+  {
+    {
+      extern int x;
+    }
+  }
+  int v;
+};
--- gcc/testsuite/g++.dg/diagnostic/redeclaration-5.C.jj	2023-09-01 10:46:15.646025458 +0200
+++ gcc/testsuite/g++.dg/diagnostic/redeclaration-5.C	2023-09-01 10:46:15.646025458 +0200
@@ -0,0 +1,167 @@
+// PR c++/52953
+// { dg-do compile }
+// { dg-options "-pedantic-errors -Wno-switch-unreachable" }
+
+void
+foo (int x)				// { dg-message "'int x' previously declared here" }
+{
+  extern int x (int);			// { dg-error "declaration of 'int x\\\(int\\\)' shadows a parameter" }
+}
+
+void
+bar (int x)				// { dg-message "'int x' previously declared here" }
+try
+{
+  extern int x (int);			// { dg-error "declaration of 'int x\\\(int\\\)' shadows a parameter" }
+}
+catch (...)
+{
+}
+
+volatile int v;
+
+void
+baz ()
+{
+#if __cplusplus >= 201103L
+  auto f = [] (int x) { extern int x (int); };// { dg-error "declaration of 'int x\\\(int\\\)' shadows a parameter" "" { target c++11 } }
+					// { dg-message "'int x' previously declared here" "" { target c++11 } .-1 }
+#endif
+  if (int x = 1)			// { dg-message "'int x' previously declared here" }
+    {
+      extern int x (int);		// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+    }
+  if (int x = 0)			// { dg-message "'int x' previously declared here" }
+    ;
+  else
+    {
+      extern int x (int);		// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+    }
+  if (int x = 1)			// { dg-message "'int x' previously declared here" }
+    extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+  if (int x = 0)			// { dg-message "'int x' previously declared here" }
+    ;
+  else
+    extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+  switch (int x = 1)			// { dg-message "'int x' previously declared here" }
+    {
+      extern int x (int);		// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+    default:;
+    }
+  switch (int x = 1)			// { dg-message "'int x' previously declared here" }
+    extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+  while (int x = v)
+    {
+      extern int x (int);		// { dg-error "'int x\\\(int\\\)' redeclared as different kind of entity" }
+    }
+  while (int x = v)
+    extern int x (int);			// { dg-error "'int x\\\(int\\\)' redeclared as different kind of entity" }
+  for (int x = v; x; ++x)		// { dg-message "'int x' previously declared here" }
+    {
+      extern int x (int);		// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+    }
+  for (int x = v; x; ++x)		// { dg-message "'int x' previously declared here" }
+    extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+  for (; int x = v; )
+    {
+      extern int x (int);		// { dg-error "'int x\\\(int\\\)' redeclared as different kind of entity" }
+    }
+  for (; int x = v; )
+    extern int x (int);			// { dg-error "'int x\\\(int\\\)' redeclared as different kind of entity" }
+  try
+    {
+    }
+  catch (int x)				// { dg-message "'int x' previously declared here" }
+    {
+      extern int x (int);		// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+    }
+}
+
+void
+corge (int x)				// { dg-message "'int x' previously declared here" }
+try
+{
+}
+catch (...)
+{
+  extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+}
+
+void
+fred (int x)				// { dg-message "'int x' previously declared here" }
+try
+{
+}
+catch (int)
+{
+}
+catch (long)
+{
+  extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+}
+
+void
+garply (int x)
+{
+  try
+    {
+      extern int x (int);
+    }
+  catch (...)
+    {
+      extern int x (int);
+    }
+}
+
+struct S
+{
+  S (int x)				// { dg-message "'int x' previously declared here" }
+  try : s (x)
+  {
+    extern int x (int);			// { dg-error "declaration of 'int x\\\(int\\\)' shadows a parameter" }
+  }
+  catch (...)
+  {
+  }
+  int s;
+};
+
+struct T
+{
+  T (int x)				// { dg-message "'int x' previously declared here" }
+  try : t (x)
+  {
+  }
+  catch (...)
+  {
+    extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
+  }
+  int t;
+};
+
+struct U
+{
+  U (int x) : u (x)
+  {
+    try
+    {
+      extern int x (int);
+    }
+    catch (...)
+    {
+      extern int x (int);
+    }
+  }
+  int u;
+};
+
+struct V
+{
+  V (int x) : v (x)
+  {
+    {
+      extern int x (int);
+    }
+  }
+  int v;
+};
--- gcc/testsuite/g++.dg/warn/Wshadow-19.C.jj	2023-09-01 11:35:21.092200057 +0200
+++ gcc/testsuite/g++.dg/warn/Wshadow-19.C	2023-09-01 11:37:15.997598483 +0200
@@ -0,0 +1,27 @@
+// { dg-do compile }
+// { dg-options "-Wshadow" }
+
+void
+foo (int x)
+{
+  int y = 1;
+  {
+    extern int x;				// { dg-warning "declaration of 'int x' shadows a parameter" }
+    extern int y;				// { dg-warning "declaration of 'y' shadows a previous local" }
+  }
+#if __cplusplus >= 201102L
+  auto fn = [x] () { extern int x; return 0; };	// { dg-warning "declaration of 'x' shadows a lambda capture" "" { target c++11 } }
+#endif
+}
+
+int z;
+
+struct S
+{
+  int x;
+  void foo ()
+  {
+    extern int x;				// { dg-warning "declaration of 'x' shadows a member of 'S'" }
+    extern int z;
+  }
+};


	Jakub


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] c++, v2: Diagnose [basic.scope.block]/2 violations even for block externs [PR52953]
  2023-09-01 13:34   ` [PATCH] c++, v2: " Jakub Jelinek
@ 2023-09-05 14:00     ` Jason Merrill
  0 siblings, 0 replies; 4+ messages in thread
From: Jason Merrill @ 2023-09-05 14:00 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

On 9/1/23 09:34, Jakub Jelinek wrote:
> On Thu, Aug 31, 2023 at 05:46:28PM -0400, Jason Merrill wrote:
>> I've suggested this to Core.
> 
> Thanks.
> 
>>> So, I'm not really sure what to do.  Intuitively the patch seems right
>>> because even block externs redeclare stuff and change meaning of the
>>> identifiers and void foo () { int i; extern int i (int); } is rejected
>>> by all compilers.
>>
>> I think this direction makes sense, though we might pedwarn on these rather
>> than error to reduce possible breakage.
> 
> It wasn't clear to me whether you want to make those pedwarns just for the
> DECL_EXTERNAL cases, ones that actually changed, or all others as well
> (which were errors or permerrors depending on the case).
> I've implemented the former, kept existing behavior of !DECL_EXTERNAL.
> 
>>> 2023-08-31  Jakub Jelinek  <jakub@redhat.com>
>>>
>>> 	PR c++/52953
>>> 	* name-lookup.cc (check_local_shadow): Defer punting on
>>> 	DECL_EXTERNAL (decl) from the start of function to right before
>>> 	the -Wshadow* checks.
>>
>> Don't we want to consider externs for the -Wshadow* checks as well?
> 
> I think that is a good idea (though dunno how much it will trigger in
> real-world), but there is one case I've excluded, the global variable
> shadowing case, because warning that
> int z;
> void foo () { extern int z; z = 1; }
> shadows the global var would be incorrect, it is the same var.
> It is true that
> int y; namespace N { void bar () { extern int y; y = 1; } }
> shadows ::y but it is unclear how to differentiate those two cases with
> the information we have at check_local_shadow time.
> 
> I've also found one spot which wasn't using auto_diagnostic_group d;
> on a pair of error_at/inform.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

> 2023-09-01  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR c++/52953
> 	* name-lookup.cc (check_local_shadow): Don't punt early for
> 	DECL_EXTERNAL decls, instead just disable the shadowing of namespace
> 	decls check for those and emit a pedwarn rather than error_at for
> 	those.  Add missing auto_diagnostic_group.  Formatting fix.
> 
> 	* g++.dg/diagnostic/redeclaration-4.C: New test.
> 	* g++.dg/diagnostic/redeclaration-5.C: New test.
> 	* g++.dg/warn/Wshadow-19.C: New test.
> 
> --- gcc/cp/name-lookup.cc.jj	2023-09-01 10:21:03.658118594 +0200
> +++ gcc/cp/name-lookup.cc	2023-09-01 11:30:10.868516494 +0200
> @@ -3096,10 +3096,6 @@ check_local_shadow (tree decl)
>     if (TREE_CODE (decl) == PARM_DECL && !DECL_CONTEXT (decl))
>       return;
>   
> -  /* External decls are something else.  */
> -  if (DECL_EXTERNAL (decl))
> -    return;
> -
>     tree old = NULL_TREE;
>     cp_binding_level *old_scope = NULL;
>     if (cxx_binding *binding = outer_binding (DECL_NAME (decl), NULL, true))
> @@ -3130,11 +3126,9 @@ check_local_shadow (tree decl)
>   	      && DECL_CONTEXT (old) == lambda_function (current_lambda_expr ())
>   	      && TREE_CODE (old) == PARM_DECL
>   	      && DECL_NAME (decl) != this_identifier)
> -	    {
> -	      error_at (DECL_SOURCE_LOCATION (old),
> -			"lambda parameter %qD "
> -			"previously declared as a capture", old);
> -	    }
> +	    error_at (DECL_SOURCE_LOCATION (old),
> +		      "lambda parameter %qD "
> +		      "previously declared as a capture", old);
>   	  return;
>   	}
>         /* Don't complain if it's from an enclosing function.  */
> @@ -3156,10 +3150,18 @@ check_local_shadow (tree decl)
>   	     in the outermost block of the function definition.  */
>   	  if (b->kind == sk_function_parms)
>   	    {
> -	      error_at (DECL_SOURCE_LOCATION (decl),
> -			"declaration of %q#D shadows a parameter", decl);
> -	      inform (DECL_SOURCE_LOCATION (old),
> -		      "%q#D previously declared here", old);
> +	      auto_diagnostic_group d;
> +	      bool emit = true;
> +	      if (DECL_EXTERNAL (decl))
> +		emit = pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic,
> +				"declaration of %q#D shadows a parameter",
> +				decl);
> +	      else
> +		error_at (DECL_SOURCE_LOCATION (decl),
> +			  "declaration of %q#D shadows a parameter", decl);
> +	      if (emit)
> +		inform (DECL_SOURCE_LOCATION (old),
> +			"%q#D previously declared here", old);
>   	      return;
>   	    }
>   	}
> @@ -3185,10 +3187,16 @@ check_local_shadow (tree decl)
>   	       && (old_scope->kind == sk_cond || old_scope->kind == sk_for))
>   	{
>   	  auto_diagnostic_group d;
> -	  error_at (DECL_SOURCE_LOCATION (decl),
> -		    "redeclaration of %q#D", decl);
> -	  inform (DECL_SOURCE_LOCATION (old),
> -		  "%q#D previously declared here", old);
> +	  bool emit = true;
> +	  if (DECL_EXTERNAL (decl))
> +	    emit = pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic,
> +			    "redeclaration of %q#D", decl);
> +	  else
> +	    error_at (DECL_SOURCE_LOCATION (decl),
> +		      "redeclaration of %q#D", decl);
> +	  if (emit)
> +	    inform (DECL_SOURCE_LOCATION (old),
> +		    "%q#D previously declared here", old);
>   	  return;
>   	}
>         /* C++11:
> @@ -3314,6 +3322,7 @@ check_local_shadow (tree decl)
>   	  || (TREE_CODE (old) == TYPE_DECL
>   	      && (!DECL_ARTIFICIAL (old)
>   		  || TREE_CODE (decl) == TYPE_DECL)))
> +      && !DECL_EXTERNAL (decl)
>         && !instantiating_current_function_p ()
>         && !warning_suppressed_p (decl, OPT_Wshadow))
>       /* XXX shadow warnings in outer-more namespaces */
> --- gcc/testsuite/g++.dg/diagnostic/redeclaration-4.C.jj	2023-09-01 10:46:15.646025458 +0200
> +++ gcc/testsuite/g++.dg/diagnostic/redeclaration-4.C	2023-09-01 10:46:15.646025458 +0200
> @@ -0,0 +1,167 @@
> +// PR c++/52953
> +// { dg-do compile }
> +// { dg-options "-pedantic-errors -Wno-switch-unreachable" }
> +
> +void
> +foo (int x)				// { dg-message "'int x' previously declared here" }
> +{
> +  extern int x;				// { dg-error "declaration of 'int x' shadows a parameter" }
> +}
> +
> +void
> +bar (int x)				// { dg-message "'int x' previously declared here" }
> +try
> +{
> +  extern int x;				// { dg-error "declaration of 'int x' shadows a parameter" }
> +}
> +catch (...)
> +{
> +}
> +
> +volatile int v;
> +
> +void
> +baz ()
> +{
> +#if __cplusplus >= 201103L
> +  auto f = [] (int x) { extern int x; };// { dg-error "declaration of 'int x' shadows a parameter" "" { target c++11 } }
> +					// { dg-message "'int x' previously declared here" "" { target c++11 } .-1 }
> +#endif
> +  if (int x = 1)			// { dg-message "'int x' previously declared here" }
> +    {
> +      extern int x;			// { dg-error "redeclaration of 'int x'" }
> +    }
> +  if (int x = 0)			// { dg-message "'int x' previously declared here" }
> +    ;
> +  else
> +    {
> +      extern int x;			// { dg-error "redeclaration of 'int x'" }
> +    }
> +  if (int x = 1)			// { dg-message "'int x' previously declared here" }
> +    extern int x;			// { dg-error "redeclaration of 'int x'" }
> +  if (int x = 0)			// { dg-message "'int x' previously declared here" }
> +    ;
> +  else
> +    extern int x;			// { dg-error "redeclaration of 'int x'" }
> +  switch (int x = 1)			// { dg-message "'int x' previously declared here" }
> +    {
> +      extern int x;			// { dg-error "redeclaration of 'int x'" }
> +    default:;
> +    }
> +  switch (int x = 1)			// { dg-message "'int x' previously declared here" }
> +    extern int x;			// { dg-error "redeclaration of 'int x'" }
> +  while (int x = v)
> +    {
> +      extern int x;			// { dg-error "'int x' conflicts with a previous declaration" }
> +    }
> +  while (int x = v)
> +    extern int x;			// { dg-error "'int x' conflicts with a previous declaration" }
> +  for (int x = v; x; ++x)		// { dg-message "'int x' previously declared here" }
> +    {
> +      extern int x;			// { dg-error "redeclaration of 'int x'" }
> +    }
> +  for (int x = v; x; ++x)		// { dg-message "'int x' previously declared here" }
> +    extern int x;			// { dg-error "redeclaration of 'int x'" }
> +  for (; int x = v; )
> +    {
> +      extern int x;			// { dg-error "'int x' conflicts with a previous declaration" }
> +    }
> +  for (; int x = v; )
> +    extern int x;			// { dg-error "'int x' conflicts with a previous declaration" }
> +  try
> +    {
> +    }
> +  catch (int x)				// { dg-message "'int x' previously declared here" }
> +    {
> +      extern int x;			// { dg-error "redeclaration of 'int x'" }
> +    }
> +}
> +
> +void
> +corge (int x)				// { dg-message "'int x' previously declared here" }
> +try
> +{
> +}
> +catch (...)
> +{
> +  extern int x;				// { dg-error "redeclaration of 'int x'" }
> +}
> +
> +void
> +fred (int x)				// { dg-message "'int x' previously declared here" }
> +try
> +{
> +}
> +catch (int)
> +{
> +}
> +catch (long)
> +{
> +  extern int x;				// { dg-error "redeclaration of 'int x'" }
> +}
> +
> +void
> +garply (int x)
> +{
> +  try
> +    {
> +      extern int x;
> +    }
> +  catch (...)
> +    {
> +      extern int x;
> +    }
> +}
> +
> +struct S
> +{
> +  S (int x)				// { dg-message "'int x' previously declared here" }
> +  try : s (x)
> +  {
> +    extern int x;				// { dg-error "declaration of 'int x' shadows a parameter" }
> +  }
> +  catch (...)
> +  {
> +  }
> +  int s;
> +};
> +
> +struct T
> +{
> +  T (int x)				// { dg-message "'int x' previously declared here" }
> +  try : t (x)
> +  {
> +  }
> +  catch (...)
> +  {
> +    extern int x;				// { dg-error "redeclaration of 'int x'" }
> +  }
> +  int t;
> +};
> +
> +struct U
> +{
> +  U (int x) : u (x)
> +  {
> +    try
> +    {
> +      extern int x;
> +    }
> +    catch (...)
> +    {
> +      extern int x;
> +    }
> +  }
> +  int u;
> +};
> +
> +struct V
> +{
> +  V (int x) : v (x)
> +  {
> +    {
> +      extern int x;
> +    }
> +  }
> +  int v;
> +};
> --- gcc/testsuite/g++.dg/diagnostic/redeclaration-5.C.jj	2023-09-01 10:46:15.646025458 +0200
> +++ gcc/testsuite/g++.dg/diagnostic/redeclaration-5.C	2023-09-01 10:46:15.646025458 +0200
> @@ -0,0 +1,167 @@
> +// PR c++/52953
> +// { dg-do compile }
> +// { dg-options "-pedantic-errors -Wno-switch-unreachable" }
> +
> +void
> +foo (int x)				// { dg-message "'int x' previously declared here" }
> +{
> +  extern int x (int);			// { dg-error "declaration of 'int x\\\(int\\\)' shadows a parameter" }
> +}
> +
> +void
> +bar (int x)				// { dg-message "'int x' previously declared here" }
> +try
> +{
> +  extern int x (int);			// { dg-error "declaration of 'int x\\\(int\\\)' shadows a parameter" }
> +}
> +catch (...)
> +{
> +}
> +
> +volatile int v;
> +
> +void
> +baz ()
> +{
> +#if __cplusplus >= 201103L
> +  auto f = [] (int x) { extern int x (int); };// { dg-error "declaration of 'int x\\\(int\\\)' shadows a parameter" "" { target c++11 } }
> +					// { dg-message "'int x' previously declared here" "" { target c++11 } .-1 }
> +#endif
> +  if (int x = 1)			// { dg-message "'int x' previously declared here" }
> +    {
> +      extern int x (int);		// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
> +    }
> +  if (int x = 0)			// { dg-message "'int x' previously declared here" }
> +    ;
> +  else
> +    {
> +      extern int x (int);		// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
> +    }
> +  if (int x = 1)			// { dg-message "'int x' previously declared here" }
> +    extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
> +  if (int x = 0)			// { dg-message "'int x' previously declared here" }
> +    ;
> +  else
> +    extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
> +  switch (int x = 1)			// { dg-message "'int x' previously declared here" }
> +    {
> +      extern int x (int);		// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
> +    default:;
> +    }
> +  switch (int x = 1)			// { dg-message "'int x' previously declared here" }
> +    extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
> +  while (int x = v)
> +    {
> +      extern int x (int);		// { dg-error "'int x\\\(int\\\)' redeclared as different kind of entity" }
> +    }
> +  while (int x = v)
> +    extern int x (int);			// { dg-error "'int x\\\(int\\\)' redeclared as different kind of entity" }
> +  for (int x = v; x; ++x)		// { dg-message "'int x' previously declared here" }
> +    {
> +      extern int x (int);		// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
> +    }
> +  for (int x = v; x; ++x)		// { dg-message "'int x' previously declared here" }
> +    extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
> +  for (; int x = v; )
> +    {
> +      extern int x (int);		// { dg-error "'int x\\\(int\\\)' redeclared as different kind of entity" }
> +    }
> +  for (; int x = v; )
> +    extern int x (int);			// { dg-error "'int x\\\(int\\\)' redeclared as different kind of entity" }
> +  try
> +    {
> +    }
> +  catch (int x)				// { dg-message "'int x' previously declared here" }
> +    {
> +      extern int x (int);		// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
> +    }
> +}
> +
> +void
> +corge (int x)				// { dg-message "'int x' previously declared here" }
> +try
> +{
> +}
> +catch (...)
> +{
> +  extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
> +}
> +
> +void
> +fred (int x)				// { dg-message "'int x' previously declared here" }
> +try
> +{
> +}
> +catch (int)
> +{
> +}
> +catch (long)
> +{
> +  extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
> +}
> +
> +void
> +garply (int x)
> +{
> +  try
> +    {
> +      extern int x (int);
> +    }
> +  catch (...)
> +    {
> +      extern int x (int);
> +    }
> +}
> +
> +struct S
> +{
> +  S (int x)				// { dg-message "'int x' previously declared here" }
> +  try : s (x)
> +  {
> +    extern int x (int);			// { dg-error "declaration of 'int x\\\(int\\\)' shadows a parameter" }
> +  }
> +  catch (...)
> +  {
> +  }
> +  int s;
> +};
> +
> +struct T
> +{
> +  T (int x)				// { dg-message "'int x' previously declared here" }
> +  try : t (x)
> +  {
> +  }
> +  catch (...)
> +  {
> +    extern int x (int);			// { dg-error "redeclaration of 'int x\\\(int\\\)'" }
> +  }
> +  int t;
> +};
> +
> +struct U
> +{
> +  U (int x) : u (x)
> +  {
> +    try
> +    {
> +      extern int x (int);
> +    }
> +    catch (...)
> +    {
> +      extern int x (int);
> +    }
> +  }
> +  int u;
> +};
> +
> +struct V
> +{
> +  V (int x) : v (x)
> +  {
> +    {
> +      extern int x (int);
> +    }
> +  }
> +  int v;
> +};
> --- gcc/testsuite/g++.dg/warn/Wshadow-19.C.jj	2023-09-01 11:35:21.092200057 +0200
> +++ gcc/testsuite/g++.dg/warn/Wshadow-19.C	2023-09-01 11:37:15.997598483 +0200
> @@ -0,0 +1,27 @@
> +// { dg-do compile }
> +// { dg-options "-Wshadow" }
> +
> +void
> +foo (int x)
> +{
> +  int y = 1;
> +  {
> +    extern int x;				// { dg-warning "declaration of 'int x' shadows a parameter" }
> +    extern int y;				// { dg-warning "declaration of 'y' shadows a previous local" }
> +  }
> +#if __cplusplus >= 201102L
> +  auto fn = [x] () { extern int x; return 0; };	// { dg-warning "declaration of 'x' shadows a lambda capture" "" { target c++11 } }
> +#endif
> +}
> +
> +int z;
> +
> +struct S
> +{
> +  int x;
> +  void foo ()
> +  {
> +    extern int x;				// { dg-warning "declaration of 'x' shadows a member of 'S'" }
> +    extern int z;
> +  }
> +};
> 
> 
> 	Jakub
> 


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-09-05 14:01 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-31  8:08 [RFC PATCH] c++: Diagnose [basic.scope.block]/2 violations even for block externs [PR52953] Jakub Jelinek
2023-08-31 21:46 ` Jason Merrill
2023-09-01 13:34   ` [PATCH] c++, v2: " Jakub Jelinek
2023-09-05 14:00     ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).