Author: Aaron Ballman
Date: 2025-05-01T07:31:48-04:00
New Revision: bc9aa0f4c4c6ad9dd6207097478f4e461a8fe5cb

URL: 
https://github.com/llvm/llvm-project/commit/bc9aa0f4c4c6ad9dd6207097478f4e461a8fe5cb
DIFF: 
https://github.com/llvm/llvm-project/commit/bc9aa0f4c4c6ad9dd6207097478f4e461a8fe5cb.diff

LOG: [C] Add -Wtentative-definition-compat (#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.

Added: 
    clang/test/Sema/warn-tentative-defn-compat.c

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticGroups.td
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaDecl.cpp
    clang/test/Sema/warn-default-const-init.c

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 65ae5945ca27c..1dd97bcc67364 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -175,6 +175,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
 - Added ``-Wunterminated-string-initialization``, grouped under ``-Wextra``,
   which diagnoses an initialization from a string literal where only the null
   terminator cannot be stored. e.g.,

diff  --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 21d5d54e9c8c5..4f235fecf4cf9 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -176,9 +176,11 @@ def DefaultConstInit : DiagGroup<"default-const-init",
 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,
                                         InitStringTooLongForCpp,
+                                        TentativeDefnCompat,
                                         DuplicateDeclSpecifier]>;
 
 def ExternCCompat : DiagGroup<"extern-c-compat">;

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c6c52f471479e..bf7017436f38c 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7455,6 +7455,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 25ee19e0ba5f1..517b3067696a0 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 da11f4189047f..ddd4aba2b5de3 100644
--- a/clang/test/Sema/warn-default-const-init.c
+++ b/clang/test/Sema/warn-default-const-init.c
@@ -1,5 +1,5 @@
 // Both of these should enable everything.
-// RUN: %clang_cc1 -fsyntax-only 
-verify=unsafe-var,unsafe-field,zero-init-var,zero-init-field -Wc++-compat %s
+// RUN: %clang_cc1 -fsyntax-only 
-verify=unsafe-var,unsafe-field,zero-init-var,zero-init-field -Wc++-compat 
-Wno-tentative-definition-compat %s
 // RUN: %clang_cc1 -fsyntax-only 
-verify=unsafe-var,unsafe-field,zero-init-var,zero-init-field 
-Wdefault-const-init %s
 
 // This should enable nothing.

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