https://github.com/AaronBallman created 
https://github.com/llvm/llvm-project/pull/137967

This adds a new diagnostic to warn about redeclaration of a tentative 
definition in C. This is incompatible with C++, so the new diagnostic group is 
under -Wc++-compat.

>From b685a553da0b3f9ecf019ceddb1052de60a9a4e6 Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aa...@aaronballman.com>
Date: Wed, 30 Apr 2025 10:11:17 -0400
Subject: [PATCH] [C] Add -Wtentative-definition-compat

This adds a new diagnostic to warn about redeclaration of a tentative
definition in C. This is incompatible with C++, so the new diagnostic
group is under -Wc++-compat.
---
 clang/docs/ReleaseNotes.rst                   |  9 ++++++++
 clang/include/clang/Basic/DiagnosticGroups.td |  4 +++-
 .../clang/Basic/DiagnosticSemaKinds.td        |  3 +++
 clang/lib/Sema/SemaDecl.cpp                   |  3 +++
 clang/test/Sema/warn-default-const-init.c     |  2 +-
 clang/test/Sema/warn-tentative-defn-compat.c  | 23 +++++++++++++++++++
 6 files changed, 42 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Sema/warn-tentative-defn-compat.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bc68bb8b70b3d..0c667745f2613 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -171,6 +171,15 @@ C Language Changes
   ``-Wenum-conversion`` and ``-Wimplicit-int-enum-cast``. This conversion is an
   int-to-enum conversion because the enumeration on the right-hand side is
   promoted to ``int`` before the assignment.
+- Added ``-Wtentative-definition-compat``, grouped under ``-Wc++-compat``,
+  which diagnoses tentative definitions in C with multiple declarations as
+  being incompatible with C++. e.g.,
+
+  .. code-block:: c
+
+    // File scope
+    int i;
+    int i; // Vaild C, invalid C++, now diagnosed
 
 C2y Feature Support
 ^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index fc1ce197ef134..0ac7b2d39d12e 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -162,8 +162,10 @@ def DefaultConstInit : DiagGroup<"default-const-init", 
[DefaultConstInitUnsafe]>
 def ImplicitVoidPtrCast : DiagGroup<"implicit-void-ptr-cast">;
 def ImplicitIntToEnumCast : DiagGroup<"implicit-int-enum-cast",
                                       [ImplicitEnumEnumCast]>;
+def TentativeDefnCompat : DiagGroup<"tentative-definition-compat">;
 def CXXCompat: DiagGroup<"c++-compat", [ImplicitVoidPtrCast, DefaultConstInit,
-                                        ImplicitIntToEnumCast, HiddenCppDecl]>;
+                                        ImplicitIntToEnumCast, HiddenCppDecl,
+                                        TentativeDefnCompat]>;
 
 def ExternCCompat : DiagGroup<"extern-c-compat">;
 def KeywordCompat : DiagGroup<"keyword-compat">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index ad5bf26be2590..7cba120cbd924 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7443,6 +7443,9 @@ def err_tentative_def_incomplete_type : Error<
 def warn_tentative_incomplete_array : Warning<
   "tentative array definition assumed to have one element">,
   InGroup<DiagGroup<"tentative-definition-array">>;
+def warn_cxx_compat_tentative_definition : Warning<
+  "duplicate declaration of %0 is invalid in C++">,
+  InGroup<TentativeDefnCompat>, DefaultIgnore;
 def err_typecheck_incomplete_array_needs_initializer : Error<
   "definition of variable with array type needs an explicit size "
   "or an initializer">;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index dfc718eedc1d9..3789eff818e08 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4750,6 +4750,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult 
&Previous) {
       if (Def && checkVarDeclRedefinition(Def, New))
         return;
     }
+  } else {
+    Diag(New->getLocation(), diag::warn_cxx_compat_tentative_definition) << 
New;
+    Diag(Old->getLocation(), diag::note_previous_declaration);
   }
 
   if (haveIncompatibleLanguageLinkages(Old, New)) {
diff --git a/clang/test/Sema/warn-default-const-init.c 
b/clang/test/Sema/warn-default-const-init.c
index b8da41b333f3d..ed211e366428e 100644
--- a/clang/test/Sema/warn-default-const-init.c
+++ b/clang/test/Sema/warn-default-const-init.c
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify=c,unsafe -Wdefault-const-init %s
-// RUN: %clang_cc1 -fsyntax-only -verify=c,unsafe -Wc++-compat %s
+// RUN: %clang_cc1 -fsyntax-only -verify=c,unsafe -Wc++-compat 
-Wno-tentative-definition-compat %s
 // RUN: %clang_cc1 -fsyntax-only -verify=unsafe %s
 // RUN: %clang_cc1 -fsyntax-only -verify=c -Wdefault-const-init 
-Wno-default-const-init-unsafe %s
 // RUN: %clang_cc1 -fsyntax-only -verify=good -Wno-default-const-init-unsafe %s
diff --git a/clang/test/Sema/warn-tentative-defn-compat.c 
b/clang/test/Sema/warn-tentative-defn-compat.c
new file mode 100644
index 0000000000000..02f3db99992f1
--- /dev/null
+++ b/clang/test/Sema/warn-tentative-defn-compat.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wtentative-definition-compat %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wc++-compat %s
+// RUN: %clang_cc1 -fsyntax-only -verify=good %s
+// RUN: %clang_cc1 -fsyntax-only -verify=cxx -x c++ %s
+// good-no-diagnostics
+
+int i;      // expected-note {{previous declaration is here}} \
+               cxx-note {{previous definition is here}}
+int i;      // expected-warning {{duplicate declaration of 'i' is invalid in 
C++}} \
+               cxx-error {{redefinition of 'i'}}
+
+int j = 12; // expected-note {{previous declaration is here}} \
+               cxx-note {{previous definition is here}}
+int j;      // expected-warning {{duplicate declaration of 'j' is invalid in 
C++}} \
+               cxx-error {{redefinition of 'j'}}
+
+int k;      // expected-note {{previous declaration is here}} \
+               cxx-note {{previous definition is here}}
+int k = 12; // expected-warning {{duplicate declaration of 'k' is invalid in 
C++}} \
+               cxx-error {{redefinition of 'k'}}
+
+// Cannot have two declarations with initializers, that is a redefinition in
+// both C and C++.

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to