================
@@ -1,45 +1,123 @@
-// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic -Wno-unused %s
+// RUN: %clang_cc1 -verify=expected,c2y -std=c2y -Wall -pedantic -Wno-unused %s
+// RUN: %clang_cc1 -verify=expected,c89-23 -std=c23 -Wall -pedantic 
-Wno-unused %s
+// RUN: %clang_cc1 -verify=expected,c89-23 -std=c17 -Wall -pedantic 
-Wno-unused %s
+// RUN: %clang_cc1 -verify=expected,c89-23 -std=c11 -Wall -pedantic 
-Wno-unused %s
+// RUN: %clang_cc1 -verify=expected,c89-23 -std=c99 -Wall -pedantic 
-Wno-unused %s
+// RUN: %clang_cc1 -verify=expected,c89-23 -std=c89 -Wall -pedantic 
-Wno-unused -Wno-comment %s
 
-/* WG14 N3410: No
+/* WG14 N3410: Clang 24
  * Slay Some Earthly Demons XI
  *
  * It is now ill-formed for the same identifier within a TU to have both
  * internal and external linkage.
  */
 
-void func1() {
-  extern int a; // #a
+void func1(void) {
+  extern int a; /* #a */
 }
 
-// This 'a' is the same as the one declared extern above.
-static int a; /* expected-error {{static declaration of 'a' follows non-static 
declaration}}
+/* This 'a' is the same as the one declared extern above. */
+static int a; /* c2y-error {{static declaration of 'a' follows non-static 
declaration}}
+                 c89-23-error {{static declaration of 'a' follows non-static 
declaration; behavior is undefined}}
                  expected-note@#a {{previous declaration is here}}
                */
 
 static int b;
-void func2() {
-  // This 'b' is the same as the one declaraed static above, but this is not
-  // ill-formed because of C2y 6.2.2p4, which gives this variable internal
-  // linkage because the previous declaration had internal linkage.
-  extern int b; // Ok
+void func2(void) {
+  /* This 'b' is well-formed, because C2y 6.2.2p6 makes it "inherit" the
+     static linkage of `static int b` above, because the latter is visible.
+   */
+  extern int b; /* Ok */
 }
 
-static int c, d;
-void func3() {
-  int c; // no linkage, different object from the one declared above.
-  for (int d;;) {
-    // This 'c' is the same as the one declared at file scope, but because of
-    // the local scope 'c', the file scope 'c' is not visible.
-    // FIXME: This should be diagnosed under N3410.
-    extern int c;
-    // This 'd' is the same as the one declared at file scope as well, but
-    // because of the 'd' declared within the for loop, the file scope 'd' is
-    // also not visible, same as with 'c'.
-    // FIXME: This should be diagnosed under N3410.
-    extern int d;
+static int c, d; /* expected-note 2 {{previous definition is here}} */
+void func3(void) {
+  int c; /* no linkage, different object from the one declared above. */
+  {
+    int d; /* no linkage, different object from the file-scope 'd'. */
+    {
+      /* This 'c' is the same as the one declared at file scope, but because
+         of the local scope 'c', the file scope 'c' is not visible. */
+      extern int c; /* c2y-error {{variable 'c' cannot be declared with 
external linkage following a declaration with internal linkage}}
+                       c89-23-error {{variable 'c' declared with external 
linkage following a declaration with internal linkage; behavior is undefined}}
+                     */
+      /* This 'd' is the same as the one declared at file scope as well, but
+         because of the enclosing block-scope 'd', the file scope 'd' is also
+         not visible, same as with 'c'. */
+      extern int d; /* c2y-error {{variable 'd' cannot be declared with 
external linkage following a declaration with internal linkage}}
+                       c89-23-error {{variable 'd' declared with external 
linkage following a declaration with internal linkage; behavior is undefined}}
+                     */
+    }
   }
-  for (static int e;;) {
-    extern int e; // Ok for the same reason as 'b' above.
+  {
+    static int e;
+    {
+      extern int e; /* Ok for the same reason as 'b' above. */
+    }
   }
 }
 
+/* A function parameter shadows the file-scope 'p' the same way a local
+   variable does, so the block-scope 'extern' does not inherit internal
+   linkage and conflicts. */
+static int p; /* expected-note {{previous definition is here}} */
+void func4(int p) {
+  {
+    extern int p; /* c2y-error {{variable 'p' cannot be declared with external 
linkage following a declaration with internal linkage}}
+                     c89-23-error {{variable 'p' declared with external 
linkage following a declaration with internal linkage; behavior is undefined}}
+                   */
+  }
+}
+
+static int q;
+void func5(void) {
+  /* No shadow intervenes here, so this 'q' inherits the internal linkage of
+     the file-scope 'q', which is fine. */
+  extern int q; /* #q */
+  {
+    int q; /* no linkage; shadows the declarations above. */
+    {
+      /* The file-scope 'q' is now hidden, so this 'extern' has external
+         linkage and conflicts with the internal-linkage declaration above. */
+      extern int q; /* c2y-error {{variable 'q' cannot be declared with 
external linkage following a declaration with internal linkage}}
+                       c89-23-error {{variable 'q' declared with external 
linkage following a declaration with internal linkage; behavior is undefined}}
+                       expected-note@#q {{previous declaration is here}}
+                     */
+    }
+  }
+}
+
+void func6(void) {
+  /* No file-scope declaration of 'r' exists, so the block-scope 'extern' just
+     has external linkage and there is no conflict. */
+  {
+    int r; /* no linkage. */
+    {
+      extern int r; /* Ok */
+    }
+  }
+}
+
+static int s; /* expected-note {{previous definition is here}} */
+void func7(void) {
+  {
+    /* The file-scope 's' is visible here, so this 'extern' inherits its
+       internal linkage, which may be surprising. */
+    extern int s; /* Ok */
+  }
+  {
+    int s; /* no linkage; shadows the file-scope 's'. */
+    {
+      /* The file-scope 's' is hidden by the local 's' above, so this 'extern'
+         has external linkage and conflicts.
+
+         FIXME: the diagnostic here is correct but potentially confusing: the
----------------
AaronBallman wrote:

Oh! I think we can drop the FIXME because this is less confusing than I was 
expecting (yay for happy surprises!). I was expecting we were associating the 
note with the declaration of `s` on line 106 instead of the one on line 101. 
That would have been confusing behavior because the one on 106 says `extern` 
but actually has internal linkage. But because of the local variable declared 
on line 109, we never see it when trying to determine what to note.

Let's reword the fixme to:

This tests that we do not accidentally note the internal linkage declaration 
using the `extern` specifier in the function scope; we want the note to point 
to the declaration using the `static` specifier at global scope because the 
function scope identifier is hidden at this point.

https://github.com/llvm/llvm-project/pull/193567
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to