[clang] [clang] emit an error when the same identifier appears with both internal and external linkage in a translation unit (PR #78064)

via cfe-commits cfe-commits at lists.llvm.org
Sat Jan 13 12:25:17 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: None (elhewaty)

<details>
<summary>Changes</summary>

Fixes: https://github.com/llvm/llvm-project/issues/54215


---
Full diff: https://github.com/llvm/llvm-project/pull/78064.diff


3 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+2) 
- (modified) clang/lib/Sema/SemaDecl.cpp (+5) 
- (modified) clang/test/Sema/private-extern.c (+18-3) 


``````````diff
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1a79892e40030a..12a95e38786abc 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5940,6 +5940,8 @@ def err_different_language_linkage : Error<
 def ext_retained_language_linkage : Extension<
   "friend function %0 retaining previous language linkage is an extension">,
   InGroup<DiagGroup<"retained-language-linkage">>;
+def err_multiple_linkage: Error<
+  "the same identifier %0 appears with both internal and external linkage">;
 def err_extern_c_global_conflict : Error<
   "declaration of %1 %select{with C language linkage|in global scope}0 "
   "conflicts with declaration %select{in global scope|with C language linkage}0">;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e92fd104d78eb5..9990bb72a8817c 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4754,6 +4754,11 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
     return New->setInvalidDecl();
   }
 
+  if (Old->getFormalLinkage() != New->getFormalLinkage() ) {
+    Diag(New->getLocation(), diag::err_multiple_linkage) << New->getDeclName();
+    return New->setInvalidDecl();
+  }
+
   if (New->isInline() && !Old->getMostRecentDecl()->isInline()) {
     if (VarDecl *Def = Old->getDefinition()) {
       // C++1z [dcl.fcn.spec]p4:
diff --git a/clang/test/Sema/private-extern.c b/clang/test/Sema/private-extern.c
index 7e7fb27416aa8d..7831c1fcfe8bc2 100644
--- a/clang/test/Sema/private-extern.c
+++ b/clang/test/Sema/private-extern.c
@@ -1,3 +1,4 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
 // RUN: %clang_cc1 -verify -fsyntax-only -Wno-private-extern %s
 // RUN: %clang_cc1 -verify -fsyntax-only -Wno-private-extern -fmodules %s
 
@@ -5,10 +6,10 @@ static int g0; // expected-note{{previous definition}}
 int g0; // expected-error{{non-static declaration of 'g0' follows static declaration}}
 
 static int g1;
-extern int g1;
+extern int g1; // expected-error{{the same identifier 'g1' appears with both internal and external linkage}}
 
-static int g2; 
-__private_extern__ int g2;
+static int g2;
+__private_extern__ int g2; // expected-error{{the same identifier 'g2' appears with both internal and external linkage}}
 
 int g3; // expected-note{{previous definition}}
 static int g3; // expected-error{{static declaration of 'g3' follows non-static declaration}}
@@ -83,3 +84,17 @@ __private_extern__ int g19;
 int g19 = 0;
 
 __private_extern__ int g20 = 0;
+
+static int g21;
+extern int g21; // expected-error{{the same identifier 'g21' appears with both internal and external linkage}}
+
+static int g22;
+
+void f10(void) {
+  int g22;
+  {
+    extern int g22; // expected-error{{the same identifier 'g22' appears with both internal and external linkage}}
+  }
+}
+
+

``````````

</details>


https://github.com/llvm/llvm-project/pull/78064


More information about the cfe-commits mailing list