Skip to content

Conversation

@AaronBallman
Copy link
Collaborator

The existing diagnostic, already enabled by default in C, will diagnose use of duplicate declaration specifiers (e.g., const const). However, the C++ standard claims that is ill-formed, so the diagnostic is now also controlled via -Wc++-compat.

Note: Clang treats this as a warning in C++ rather than an error, but GCC does treat this as an error in C++, so the compatibility concerns are minor but do exist.

The existing diagnostic, already enabled by default in C, will diagnose
use of duplicate declaration specifiers (e.g., `const const`). However,
the C++ standard claims that is ill-formed, so the diagnostic is now
also controlled via -Wc++-compat.

Note: Clang treats this as a warning in C++ rather than an error, but
GCC does treat this as an error in C++, so the compatibility concerns
are minor but do exist.
@AaronBallman AaronBallman added clang Clang issues not falling into any other category c clang:diagnostics New/improved warning or error message in Clang, but not in clang-tidy or static analyzer labels Apr 30, 2025
@llvmbot llvmbot added the clang:frontend Language frontend issues, e.g. anything involving "Sema" label Apr 30, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 30, 2025

@llvm/pr-subscribers-clang

Author: Aaron Ballman (AaronBallman)

Changes

The existing diagnostic, already enabled by default in C, will diagnose use of duplicate declaration specifiers (e.g., const const). However, the C++ standard claims that is ill-formed, so the diagnostic is now also controlled via -Wc++-compat.

Note: Clang treats this as a warning in C++ rather than an error, but GCC does treat this as an error in C++, so the compatibility concerns are minor but do exist.


Full diff: https://github.com/llvm/llvm-project/pull/138012.diff

3 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+3)
  • (modified) clang/include/clang/Basic/DiagnosticGroups.td (+4-2)
  • (added) clang/test/Sema/warn-duplicate-decl-specifier.c (+17)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5cc1a36fac1e8..3becd3e3e4603 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -188,6 +188,9 @@ C Language Changes
   ``-Wunterminated-string-initialization``. However, this diagnostic is not
   silenced by the ``nonstring`` attribute as these initializations are always
   incompatible with C++.
+- Added the existing ``-Wduplicate-decl-specifier`` diagnostic, which is on by
+  default, to ``-Wc++-compat`` because duplicated declaration specifiers are
+  not valid in C++.
 
 C2y Feature Support
 ^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 75e8fc541305b..de3374962c6b0 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -156,6 +156,8 @@ def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">;
 def C99Compat : DiagGroup<"c99-compat">;
 def C23Compat : DiagGroup<"c23-compat">;
 def : DiagGroup<"c2x-compat", [C23Compat]>;
+
+def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">;
 def InitStringTooLongMissingNonString :
   DiagGroup<"unterminated-string-initialization">;
 def InitStringTooLongForCpp :
@@ -168,7 +170,8 @@ def ImplicitIntToEnumCast : DiagGroup<"implicit-int-enum-cast",
                                       [ImplicitEnumEnumCast]>;
 def CXXCompat: DiagGroup<"c++-compat", [ImplicitVoidPtrCast, DefaultConstInit,
                                         ImplicitIntToEnumCast, HiddenCppDecl,
-                                        InitStringTooLongForCpp]>;
+                                        InitStringTooLongForCpp,
+                                        DuplicateDeclSpecifier]>;
 
 def ExternCCompat : DiagGroup<"extern-c-compat">;
 def KeywordCompat : DiagGroup<"keyword-compat">;
@@ -814,7 +817,6 @@ def TautologicalCompare : DiagGroup<"tautological-compare",
                                      TautologicalObjCBoolCompare,
                                      TautologicalNegationCompare]>;
 def HeaderHygiene : DiagGroup<"header-hygiene">;
-def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">;
 def CompareDistinctPointerType : DiagGroup<"compare-distinct-pointer-types">;
 def GNUUnionCast : DiagGroup<"gnu-union-cast">;
 def GNUVariableSizedTypeNotAtEnd : DiagGroup<"gnu-variable-sized-type-not-at-end">;
diff --git a/clang/test/Sema/warn-duplicate-decl-specifier.c b/clang/test/Sema/warn-duplicate-decl-specifier.c
new file mode 100644
index 0000000000000..d57bb867f66f1
--- /dev/null
+++ b/clang/test/Sema/warn-duplicate-decl-specifier.c
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wduplicate-decl-specifier %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wc++-compat %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-duplicate-decl-specifier -Wc++-compat %s
+// RUN: %clang_cc1 -fsyntax-only -verify=good -Wc++-compat -Wno-duplicate-decl-specifier %s
+// RUN: %clang_cc1 -fsyntax-only -verify=good -Wno-duplicate-decl-specifier %s
+// RUN: %clang_cc1 -fsyntax-only -verify -x c++ %s
+// good-no-diagnostics
+
+// Note: we treat this as a warning in C++, so you get the same diagnostics in
+// either language mode. However, GCC diagnoses this as an error, so the
+// compatibility warning has value.
+const const int i = 12; // expected-warning {{duplicate 'const' declaration specifier}}
+
+__attribute__((address_space(1)))
+__attribute__((address_space(1))) // expected-warning {{multiple identical address spaces specified for type}}
+int j = 12;
+

@AaronBallman AaronBallman merged commit 4b3acfb into llvm:main May 1, 2025
17 checks passed
@AaronBallman AaronBallman deleted the aballman-dup-decl-specifiers branch May 1, 2025 10:52
@llvm-ci
Copy link
Collaborator

llvm-ci commented May 1, 2025

LLVM Buildbot has detected a new failure on builder clang-aarch64-sve-vls running on linaro-g3-02 while building clang at step 7 "ninja check 1".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/143/builds/7381

Here is the relevant piece of the build log for the reference
Step 7 (ninja check 1) failure: stage 1 checked (failure)
******************** TEST 'AddressSanitizer-aarch64-linux :: TestCases/Posix/halt_on_error-signals.c' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
/home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/./bin/clang  -fsanitize=address -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -fno-optimize-sibling-calls -gline-tables-only   -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta   -fsanitize-recover=address -pthread /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/llvm/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c -o /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/runtimes/runtimes-bins/compiler-rt/test/asan/AARCH64LinuxConfig/TestCases/Posix/Output/halt_on_error-signals.c.tmp # RUN: at line 3
+ /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/./bin/clang -fsanitize=address -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -fno-optimize-sibling-calls -gline-tables-only -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta -fsanitize-recover=address -pthread /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/llvm/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c -o /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/runtimes/runtimes-bins/compiler-rt/test/asan/AARCH64LinuxConfig/TestCases/Posix/Output/halt_on_error-signals.c.tmp
In file included from /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/llvm/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c:11:
In file included from /usr/include/stdio.h:27:
In file included from /usr/include/aarch64-linux-gnu/bits/libc-header-start.h:33:
/usr/include/features.h:194:3: warning: "_BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE" [-W#warnings]
  194 | # warning "_BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE"
      |   ^
1 warning generated.
env ASAN_OPTIONS=halt_on_error=false:suppress_equal_pcs=false  /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/runtimes/runtimes-bins/compiler-rt/test/asan/AARCH64LinuxConfig/TestCases/Posix/Output/halt_on_error-signals.c.tmp 100 >/home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/runtimes/runtimes-bins/compiler-rt/test/asan/AARCH64LinuxConfig/TestCases/Posix/Output/halt_on_error-signals.c.tmp.log 2>&1 || true # RUN: at line 5
+ env ASAN_OPTIONS=halt_on_error=false:suppress_equal_pcs=false /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/runtimes/runtimes-bins/compiler-rt/test/asan/AARCH64LinuxConfig/TestCases/Posix/Output/halt_on_error-signals.c.tmp 100
+ true
FileCheck --check-prefix=CHECK-COLLISION /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/llvm/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c </home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/runtimes/runtimes-bins/compiler-rt/test/asan/AARCH64LinuxConfig/TestCases/Posix/Output/halt_on_error-signals.c.tmp.log || FileCheck --check-prefix=CHECK-NO-COLLISION /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/llvm/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c </home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/runtimes/runtimes-bins/compiler-rt/test/asan/AARCH64LinuxConfig/TestCases/Posix/Output/halt_on_error-signals.c.tmp.log # RUN: at line 7
+ FileCheck --check-prefix=CHECK-COLLISION /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/llvm/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c
/home/tcwg-buildbot/worker/clang-aarch64-sve-vls/llvm/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c:29:22: error: CHECK-COLLISION: expected string not found in input
 // CHECK-COLLISION: AddressSanitizer: nested bug in the same thread, aborting
                     ^
<stdin>:1:1: note: scanning from here
=================================================================
^
<stdin>:13:10: note: possible intended match here
SUMMARY: AddressSanitizer: use-after-poison /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/llvm/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c:32:12 in error
         ^

Input file: <stdin>
Check file: /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/llvm/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c

-dump-input=help explains the following input dump.

Input was:
<<<<<<
            1: ================================================================= 
check:29'0     X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
            2: ==1773557==ERROR: AddressSanitizer: use-after-poison on address 0xb073ffbf8bc0 at pc 0xb073ffba7bfc bp 0xe8e47a80e640 sp 0xe8e47a80e638 
check:29'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            3: WRITE of size 1 at 0xb073ffbf8bc0 thread T1 
check:29'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            4:  #0 0xb073ffba7bf8 in error /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/llvm/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c:32:12 
check:29'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            5:  #1 0xb073ffba7fa8 in receiver /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/llvm/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c:66:5 
check:29'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            6:  #2 0xb073ffb65a44 in asan_thread_start(void*) /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/llvm/compiler-rt/lib/asan/asan_interceptors.cpp:239:28 
check:29'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            7:  #3 0xece47de8d5b4 in start_thread nptl/pthread_create.c:442:8 
check:29'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...

IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
The existing diagnostic, already enabled by default in C, will diagnose
use of duplicate declaration specifiers (e.g., `const const`). However,
the C++ standard claims that is ill-formed, so the diagnostic is now
also controlled via -Wc++-compat.

Note: Clang treats this as a warning in C++ rather than an error, but
GCC does treat this as an error in C++, so the compatibility concerns
are minor but do exist.
GeorgeARM pushed a commit to GeorgeARM/llvm-project that referenced this pull request May 7, 2025
The existing diagnostic, already enabled by default in C, will diagnose
use of duplicate declaration specifiers (e.g., `const const`). However,
the C++ standard claims that is ill-formed, so the diagnostic is now
also controlled via -Wc++-compat.

Note: Clang treats this as a warning in C++ rather than an error, but
GCC does treat this as an error in C++, so the compatibility concerns
are minor but do exist.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c clang:diagnostics New/improved warning or error message in Clang, but not in clang-tidy or static analyzer clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants