[clang] 78abeca - [clang][Sema] Fix diagnostic for function overloading in extern "C" (#106033)

via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 2 21:22:37 PDT 2024


Author: s-watanabe314
Date: 2024-09-03T13:22:33+09:00
New Revision: 78abeca1d88593d7f2a27f3c3e140abe77236e7e

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

LOG: [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 <aeternalmail at gmail.com>

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaDecl.cpp
    clang/test/SemaCXX/extern-c.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index fc940db4813948..49c4b0c601159b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -266,6 +266,8 @@ Improvements to Clang's diagnostics
   compilation speed with modules. This warning is disabled by default and it needs
   to be explicitly enabled or by ``-Weverything``.
 
+- Improved diagnostic when trying to overload a function in an ``extern "C"`` context. (#GH80235)
+
 Improvements to Clang's time-trace
 ----------------------------------
 

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 8ae1baa1b521bc..0f63c764536ecb 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -3866,6 +3866,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S,
         if (New->isCXXClassMember() && New->isOutOfLine())
           Diag(New->getLocation(), diag::err_member_def_does_not_match_ret_type)
               << New << New->getReturnTypeSourceRange();
+        else if (Old->isExternC() && New->isExternC() &&
+                 !Old->hasAttr<OverloadableAttr>() &&
+                 !New->hasAttr<OverloadableAttr>())
+          Diag(New->getLocation(), diag::err_conflicting_types) << New;
         else
           Diag(New->getLocation(), diag::err_ovl_
diff _return_type)
               << New->getReturnTypeSourceRange();

diff  --git a/clang/test/SemaCXX/extern-c.cpp b/clang/test/SemaCXX/extern-c.cpp
index 68d1494b94918f..86012670ddcd57 100644
--- a/clang/test/SemaCXX/extern-c.cpp
+++ b/clang/test/SemaCXX/extern-c.cpp
@@ -77,6 +77,19 @@ namespace foo {
   }
 }
 
+namespace extern_ovl {
+  extern "C" {
+    __attribute__((overloadable))
+    void ovl_decl(void); // expected-note {{previous}}
+
+    __attribute__((overloadable))
+    int ovl_decl(int);
+
+    __attribute__((overloadable))
+    int ovl_decl(void); // expected-error {{functions that 
diff er only in their return type}}
+  }
+}
+
 namespace linkage {
   namespace redecl {
     extern "C" {
@@ -88,6 +101,12 @@ namespace linkage {
       void linkage_redecl(double); // expected-error {{conflicting types}}
     }
   }
+  namespace redecl_2 {
+    extern "C" {
+      void linkage_redecl_2(); // expected-note {{previous}}
+      int linkage_redecl_2(int); // expected-error {{conflicting types}}
+    }
+  }
   namespace from_outer {
     void linkage_from_outer_1(); // expected-note {{previous}}
     void linkage_from_outer_2(); // expected-note {{previous}}


        


More information about the cfe-commits mailing list