Skip to content

Commit 78abeca

Browse files
[clang][Sema] Fix diagnostic for function overloading in extern "C" (#106033)
Fixes #80235 When trying to overload a function within `extern "C"`, the diagnostic `functions that differ only in their return type cannot be overloaded` is given. This diagnostic is inappropriate because overloading is basically not allowed in the C language. However, if the redeclared function has the `((overloadable))` attribute, it should be diagnosed as `functions that differ only in their return type cannot be overloaded`. This patch uses `isExternC()` to provide an appropriate diagnostic during the diagnostic process. `isExternC()` updates the linkage information cache internally, so calling it before merging functions can cause clang to crash. An example is declaring `static void foo()` and `void foo()` within an `extern "C"` block. Therefore, I decided to call `isExternC()` after the compilation error is confirmed and select the diagnostic message. The diagnostic message is `conflicting types for 'func'` similar to the diagnostic in C, and `functions that differ only in their return type cannot be overloaded` if the `((overloadable))` attribute is given. Regression tests verify that the expected diagnostics are given when trying to overload functions within `extern "C"` and when the `((overloadable))` attribute is present. --------- Co-authored-by: Sirraide <[email protected]>
1 parent 2cbd1bc commit 78abeca

File tree

3 files changed

+25
-0
lines changed

3 files changed

+25
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,8 @@ Improvements to Clang's diagnostics
266266
compilation speed with modules. This warning is disabled by default and it needs
267267
to be explicitly enabled or by ``-Weverything``.
268268

269+
- Improved diagnostic when trying to overload a function in an ``extern "C"`` context. (#GH80235)
270+
269271
Improvements to Clang's time-trace
270272
----------------------------------
271273

clang/lib/Sema/SemaDecl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3866,6 +3866,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S,
38663866
if (New->isCXXClassMember() && New->isOutOfLine())
38673867
Diag(New->getLocation(), diag::err_member_def_does_not_match_ret_type)
38683868
<< New << New->getReturnTypeSourceRange();
3869+
else if (Old->isExternC() && New->isExternC() &&
3870+
!Old->hasAttr<OverloadableAttr>() &&
3871+
!New->hasAttr<OverloadableAttr>())
3872+
Diag(New->getLocation(), diag::err_conflicting_types) << New;
38693873
else
38703874
Diag(New->getLocation(), diag::err_ovl_diff_return_type)
38713875
<< New->getReturnTypeSourceRange();

clang/test/SemaCXX/extern-c.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,19 @@ namespace foo {
7777
}
7878
}
7979

80+
namespace extern_ovl {
81+
extern "C" {
82+
__attribute__((overloadable))
83+
void ovl_decl(void); // expected-note {{previous}}
84+
85+
__attribute__((overloadable))
86+
int ovl_decl(int);
87+
88+
__attribute__((overloadable))
89+
int ovl_decl(void); // expected-error {{functions that differ only in their return type}}
90+
}
91+
}
92+
8093
namespace linkage {
8194
namespace redecl {
8295
extern "C" {
@@ -88,6 +101,12 @@ namespace linkage {
88101
void linkage_redecl(double); // expected-error {{conflicting types}}
89102
}
90103
}
104+
namespace redecl_2 {
105+
extern "C" {
106+
void linkage_redecl_2(); // expected-note {{previous}}
107+
int linkage_redecl_2(int); // expected-error {{conflicting types}}
108+
}
109+
}
91110
namespace from_outer {
92111
void linkage_from_outer_1(); // expected-note {{previous}}
93112
void linkage_from_outer_2(); // expected-note {{previous}}

0 commit comments

Comments
 (0)