[clang] [clang] fix merging of UsingShadowDecl (PR #80245)

Matheus Izvekov via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 1 11:18:46 PST 2024


https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/80245

>From 8823a7ec248c7220395f53634467aa25f5007206 Mon Sep 17 00:00:00 2001
From: Matheus Izvekov <mizvekov at gmail.com>
Date: Thu, 1 Feb 2024 02:07:16 -0300
Subject: [PATCH 1/2] [NFC] [clang] add tests for merging of UsingShadowDecl

---
 clang/test/Modules/GH80252.cppm     | 42 +++++++++++++++++++++++++++
 clang/test/Modules/cxx20-decls.cppm | 44 +++++++++++++++++++++++++++++
 2 files changed, 86 insertions(+)
 create mode 100644 clang/test/Modules/GH80252.cppm
 create mode 100644 clang/test/Modules/cxx20-decls.cppm

diff --git a/clang/test/Modules/GH80252.cppm b/clang/test/Modules/GH80252.cppm
new file mode 100644
index 0000000000000..3212404fbe14c
--- /dev/null
+++ b/clang/test/Modules/GH80252.cppm
@@ -0,0 +1,42 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 -I %t %t/A.cppm -emit-module-interface -o %t/A.pcm -verify
+// RUN: %clang_cc1 -std=c++20 -I %t %t/B.cppm -emit-module-interface -o %t/B.pcm -verify
+// RUN: %clang_cc1 -std=c++20 -I %t %t/C.cpp -fmodule-file=A=%t/A.pcm -fmodule-file=B=%t/B.pcm -fsyntax-only -verify
+
+//--- foo.h
+namespace baz {
+  using foo = char;
+  using baz::foo;
+}
+
+//--- bar.h
+class bar {
+  bar(baz::foo);
+};
+
+//--- A.cppm
+// expected-no-diagnostics
+module;
+#include "foo.h"
+export module A;
+
+//--- B.cppm
+// expected-no-diagnostics
+module;
+#include "foo.h"
+#include "bar.h"
+export module B;
+
+//--- C.cpp
+#include "foo.h"
+import A;
+#include "bar.h"
+import B;
+// Since modules are loaded lazily, force loading by performing a lookup.
+using xxx = bar;
+// FIXME: This is a false positive ODR violation.
+// expected-error at bar.h:2 {{'bar' has different definitions in different modules; first difference is defined here found constructor with 1st parameter of type 'baz::foo' (aka 'char')}}
+// expected-note at bar.h:2 {{but in 'B.<global>' found constructor with 1st parameter of type 'baz::foo' (aka 'char')}}
diff --git a/clang/test/Modules/cxx20-decls.cppm b/clang/test/Modules/cxx20-decls.cppm
new file mode 100644
index 0000000000000..052c8e73be247
--- /dev/null
+++ b/clang/test/Modules/cxx20-decls.cppm
@@ -0,0 +1,44 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 -I %t %t/A.cppm -emit-module-interface -o %t/A.pcm -verify
+// RUN: %clang_cc1 -std=c++20 -I %t %t/B.cpp -fmodule-file=A=%t/A.pcm -fsyntax-only -verify -ast-dump-all -ast-dump-filter baz | FileCheck %s
+
+//--- foo.h
+namespace baz {
+  using foo = char;
+  using baz::foo;
+}
+
+//--- A.cppm
+// expected-no-diagnostics
+module;
+#include "foo.h"
+export module A;
+
+//--- B.cpp
+// expected-no-diagnostics
+#include "foo.h"
+import A;
+// Since modules are loaded lazily, force loading by performing a lookup.
+using xxx = baz::foo;
+
+// CHECK-LABEL: Dumping baz:
+// CHECK-NEXT: NamespaceDecl 0x[[BAZ_REDECL_ADDR:[^ ]*]] prev 0x[[BAZ_ADDR:[^ ]*]] <{{.*}}> line:{{.*}} imported in A.<global> hidden <undeserialized declarations> baz
+// CHECK-NEXT: |-original Namespace 0x[[BAZ_ADDR]] 'baz'
+// CHECK-NEXT: |-TypeAliasDecl 0x[[ALIAS_REDECL_ADDR:[^ ]*]] prev 0x[[ALIAS_ADDR:[^ ]*]] <{{.*}}> col:{{.*}} imported in A.<global> hidden foo 'char'
+// CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'char'
+// CHECK-NEXT: |-UsingDecl 0x{{[^ ]*}} first 0x[[USING_ADDR:[^ ]*]] <{{.*}}> col:{{.*}} imported in A.<global> hidden baz::foo
+// CHECK-NEXT: | `-NestedNameSpecifier Namespace 0x[[BAZ_REDECL_ADDR]] 'baz'
+// FIXME: UsingShadowDecl should have been merged
+// CHECK-NOT:  `-UsingShadowDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} <{{.*}}> col:{{.*}} imported in A.<global> hidden implicit TypeAlias 0x[[ALIAS_REDECL_ADDR]] 'foo'
+// CHECK-NEXT: `-UsingShadowDecl 0x{{[^ ]*}} <{{.*}}> col:{{.*}} imported in A.<global> hidden implicit TypeAlias 0x[[ALIAS_REDECL_ADDR]] 'foo'
+
+// CHECK-LABEL: Dumping baz:
+// CHECK-NEXT: NamespaceDecl 0x[[BAZ_ADDR]] <{{.*}}> line:{{.*}} baz
+// CHECK-NEXT: |-TypeAliasDecl 0x[[ALIAS_ADDR]] <{{.*}}> col:{{.*}} referenced foo 'char'
+// CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'char'
+// CHECK-NEXT: |-UsingDecl 0x[[USING_ADDR]] <{{.*}}> col:{{.*}} baz::foo
+// CHECK-NEXT: | `-NestedNameSpecifier Namespace 0x[[BAZ_ADDR]] 'baz'
+// CHECK-NEXT:  `-UsingShadowDecl 0x[[SHADOW_ADDR:[^ ]*]] <{{.*}}> col:{{.*}} implicit TypeAlias 0x[[ALIAS_ADDR]] 'foo'

>From f2e37f079cecdd95ba32912aaea739be68959f9e Mon Sep 17 00:00:00 2001
From: Matheus Izvekov <mizvekov at gmail.com>
Date: Thu, 1 Feb 2024 02:26:10 -0300
Subject: [PATCH 2/2] [clang] fix merging of UsingShadowDecl

Previously, when deciding if two UsingShadowDecls where mergeable,
we would incorrectly only look for both pointing to the exact redecla
ration, whereas the correct thing is to look for declarations to the
same entity.

This problem has existed as far back as 2013, introduced in commit
fd8634a09de71.

This problem could manifest itself as ODR check false positives
when importing modules.

Fixes: #80252
---
 clang/docs/ReleaseNotes.rst         | 3 +++
 clang/lib/AST/ASTContext.cpp        | 2 +-
 clang/test/Modules/GH80252.cppm     | 4 +---
 clang/test/Modules/cxx20-decls.cppm | 6 ++----
 4 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 53040aa0f9074..0a9cd242f9d95 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -188,6 +188,9 @@ Bug Fixes to C++ Support
   and (`#79745 <https://github.com/llvm/llvm-project/issues/79745>`_)
 - Fix incorrect code generation caused by the object argument of ``static operator()`` and ``static operator[]`` calls not being evaluated.
   Fixes (`#67976 <https://github.com/llvm/llvm-project/issues/67976>`_)
+- Fix incorrect merging of modules which contain using declarations which shadow
+  other declarations. This could manifest as ODR checker false positives.
+  Fixes (`#80252 <https://github.com/llvm/llvm-project/issues/80252>`_)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 78a04b4c69426..f3e83955c429a 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -6733,7 +6733,7 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) const {
   // Using shadow declarations with the same target match.
   if (const auto *USX = dyn_cast<UsingShadowDecl>(X)) {
     const auto *USY = cast<UsingShadowDecl>(Y);
-    return USX->getTargetDecl() == USY->getTargetDecl();
+    return declaresSameEntity(USX->getTargetDecl(), USY->getTargetDecl());
   }
 
   // Using declarations with the same qualifier match. (We already know that
diff --git a/clang/test/Modules/GH80252.cppm b/clang/test/Modules/GH80252.cppm
index 3212404fbe14c..e3963f4ca8038 100644
--- a/clang/test/Modules/GH80252.cppm
+++ b/clang/test/Modules/GH80252.cppm
@@ -37,6 +37,4 @@ import A;
 import B;
 // Since modules are loaded lazily, force loading by performing a lookup.
 using xxx = bar;
-// FIXME: This is a false positive ODR violation.
-// expected-error at bar.h:2 {{'bar' has different definitions in different modules; first difference is defined here found constructor with 1st parameter of type 'baz::foo' (aka 'char')}}
-// expected-note at bar.h:2 {{but in 'B.<global>' found constructor with 1st parameter of type 'baz::foo' (aka 'char')}}
+// expected-no-diagnostics
diff --git a/clang/test/Modules/cxx20-decls.cppm b/clang/test/Modules/cxx20-decls.cppm
index 052c8e73be247..ee9f117278884 100644
--- a/clang/test/Modules/cxx20-decls.cppm
+++ b/clang/test/Modules/cxx20-decls.cppm
@@ -31,9 +31,7 @@ using xxx = baz::foo;
 // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'char'
 // CHECK-NEXT: |-UsingDecl 0x{{[^ ]*}} first 0x[[USING_ADDR:[^ ]*]] <{{.*}}> col:{{.*}} imported in A.<global> hidden baz::foo
 // CHECK-NEXT: | `-NestedNameSpecifier Namespace 0x[[BAZ_REDECL_ADDR]] 'baz'
-// FIXME: UsingShadowDecl should have been merged
-// CHECK-NOT:  `-UsingShadowDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} <{{.*}}> col:{{.*}} imported in A.<global> hidden implicit TypeAlias 0x[[ALIAS_REDECL_ADDR]] 'foo'
-// CHECK-NEXT: `-UsingShadowDecl 0x{{[^ ]*}} <{{.*}}> col:{{.*}} imported in A.<global> hidden implicit TypeAlias 0x[[ALIAS_REDECL_ADDR]] 'foo'
+// CHECK-NEXT: `-UsingShadowDecl 0x{{[^ ]*}} prev 0x[[SHADOW_ADDR:[^ ]*]] <{{.*}}> col:{{.*}} imported in A.<global> hidden implicit TypeAlias 0x[[ALIAS_REDECL_ADDR]] 'foo'
 
 // CHECK-LABEL: Dumping baz:
 // CHECK-NEXT: NamespaceDecl 0x[[BAZ_ADDR]] <{{.*}}> line:{{.*}} baz
@@ -41,4 +39,4 @@ using xxx = baz::foo;
 // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'char'
 // CHECK-NEXT: |-UsingDecl 0x[[USING_ADDR]] <{{.*}}> col:{{.*}} baz::foo
 // CHECK-NEXT: | `-NestedNameSpecifier Namespace 0x[[BAZ_ADDR]] 'baz'
-// CHECK-NEXT:  `-UsingShadowDecl 0x[[SHADOW_ADDR:[^ ]*]] <{{.*}}> col:{{.*}} implicit TypeAlias 0x[[ALIAS_ADDR]] 'foo'
+// CHECK-NEXT:  `-UsingShadowDecl 0x[[SHADOW_ADDR]] <{{.*}}> col:{{.*}} implicit TypeAlias 0x[[ALIAS_ADDR]] 'foo'



More information about the cfe-commits mailing list