[clang] e3f87e1 - [C] Fix a false-positive with tentative defn compat (#139738)
via cfe-commits
cfe-commits at lists.llvm.org
Tue May 13 07:59:59 PDT 2025
Author: Aaron Ballman
Date: 2025-05-13T10:59:55-04:00
New Revision: e3f87e15910a5f1c5552fc3ef57e7dda3f68901a
URL: https://github.com/llvm/llvm-project/commit/e3f87e15910a5f1c5552fc3ef57e7dda3f68901a
DIFF: https://github.com/llvm/llvm-project/commit/e3f87e15910a5f1c5552fc3ef57e7dda3f68901a.diff
LOG: [C] Fix a false-positive with tentative defn compat (#139738)
C++ has a carve-out that makes a declaration with 'extern' explicitly
specified and no initializer be a declaration rather than a definition.
We now account for that to silence a diagnostic with:
```
extern const int i;
const int i = 12;
```
which is valid C++.
Addresses an issue that was brought up via post-commit review.
Added:
Modified:
clang/lib/Sema/SemaDecl.cpp
clang/test/Sema/warn-tentative-defn-compat.c
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 5a45198a7ce02..152f3f340cd50 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4755,8 +4755,16 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
return;
}
} else {
- Diag(New->getLocation(), diag::warn_cxx_compat_tentative_definition) << New;
- Diag(Old->getLocation(), diag::note_previous_declaration);
+ // C++ may not have a tentative definition rule, but it has a
diff erent
+ // rule about what constitutes a definition in the first place. See
+ // [basic.def]p2 for details, but the basic idea is: if the old declaration
+ // contains the extern specifier and doesn't have an initializer, it's fine
+ // in C++.
+ if (Old->getStorageClass() != SC_Extern || Old->hasInit()) {
+ 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-tentative-defn-compat.c b/clang/test/Sema/warn-tentative-defn-compat.c
index 02f3db99992f1..6e6b70df2cf7b 100644
--- a/clang/test/Sema/warn-tentative-defn-compat.c
+++ b/clang/test/Sema/warn-tentative-defn-compat.c
@@ -20,4 +20,7 @@ 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++.
+// both C and C++. However, C++ does have a
diff erent definition of what makes
+// a declaration a definition.
+extern const int a;
+const int a = 12; // Okay in C and C++
More information about the cfe-commits
mailing list