Skip to content

Commit e3f87e1

Browse files
authored
[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.
1 parent 936481f commit e3f87e1

File tree

2 files changed

+14
-3
lines changed

2 files changed

+14
-3
lines changed

clang/lib/Sema/SemaDecl.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4755,8 +4755,16 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
47554755
return;
47564756
}
47574757
} else {
4758-
Diag(New->getLocation(), diag::warn_cxx_compat_tentative_definition) << New;
4759-
Diag(Old->getLocation(), diag::note_previous_declaration);
4758+
// C++ may not have a tentative definition rule, but it has a different
4759+
// rule about what constitutes a definition in the first place. See
4760+
// [basic.def]p2 for details, but the basic idea is: if the old declaration
4761+
// contains the extern specifier and doesn't have an initializer, it's fine
4762+
// in C++.
4763+
if (Old->getStorageClass() != SC_Extern || Old->hasInit()) {
4764+
Diag(New->getLocation(), diag::warn_cxx_compat_tentative_definition)
4765+
<< New;
4766+
Diag(Old->getLocation(), diag::note_previous_declaration);
4767+
}
47604768
}
47614769

47624770
if (haveIncompatibleLanguageLinkages(Old, New)) {

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,7 @@ int k = 12; // expected-warning {{duplicate declaration of 'k' is invalid in C++
2020
cxx-error {{redefinition of 'k'}}
2121

2222
// Cannot have two declarations with initializers, that is a redefinition in
23-
// both C and C++.
23+
// both C and C++. However, C++ does have a different definition of what makes
24+
// a declaration a definition.
25+
extern const int a;
26+
const int a = 12; // Okay in C and C++

0 commit comments

Comments
 (0)