[clang] 5c1f7b2 - [C++20] [Modules] Only check decls under namespace scope in CheckRedeclarationExported

Chuanqi Xu via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 25 18:56:06 PST 2022


Author: Chuanqi Xu
Date: 2022-01-26T10:54:52+08:00
New Revision: 5c1f7b296ac0dddeca02891976e6ab5cfc006719

URL: https://github.com/llvm/llvm-project/commit/5c1f7b296ac0dddeca02891976e6ab5cfc006719
DIFF: https://github.com/llvm/llvm-project/commit/5c1f7b296ac0dddeca02891976e6ab5cfc006719.diff

LOG: [C++20] [Modules] Only check decls under namespace scope in CheckRedeclarationExported

Since only the decls inhabit in a namespace scope could be exported, it
is not meaningful to check it in CheckRedeclarationExported, which
implements [module.interface]/p6.

Reviewed By: urnathan

Differential Revision: https://reviews.llvm.org/D118120

Added: 
    

Modified: 
    clang/lib/Sema/SemaDecl.cpp
    clang/test/CXX/module/module.interface/p6.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 673631a12eee0..7c5f6b318e973 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1635,6 +1635,19 @@ bool Sema::CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old) {
 // A redeclaration of an entity X is implicitly exported if X was introduced by
 // an exported declaration; otherwise it shall not be exported.
 bool Sema::CheckRedeclarationExported(NamedDecl *New, NamedDecl *Old) {
+  // [module.interface]p1:
+  // An export-declaration shall inhabit a namespace scope.
+  //
+  // So it is meaningless to talk about redeclaration which is not at namespace
+  // scope.
+  if (!New->getLexicalDeclContext()
+           ->getNonTransparentContext()
+           ->isFileContext() ||
+      !Old->getLexicalDeclContext()
+           ->getNonTransparentContext()
+           ->isFileContext())
+    return false;
+
   bool IsNewExported = New->isInExportDeclContext();
   bool IsOldExported = Old->isInExportDeclContext();
 

diff  --git a/clang/test/CXX/module/module.interface/p6.cpp b/clang/test/CXX/module/module.interface/p6.cpp
index a696851ccbff4..070aa62f5800a 100644
--- a/clang/test/CXX/module/module.interface/p6.cpp
+++ b/clang/test/CXX/module/module.interface/p6.cpp
@@ -91,3 +91,24 @@ template <typename T>
 T TemplVar; // expected-note {{previous declaration is here}}
 export template <typename T>
 T TemplVar; // expected-error {{cannot export redeclaration 'TemplVar' here since the previous declaration is not exported}}
+
+// Test the compiler wouldn't complain about the redeclaration of friend in exported class.
+namespace Friend {
+template <typename T>
+class bar;
+class gua;
+template <typename T>
+void hello();
+void hi();
+export class foo;
+bool operator<(const foo &a, const foo &b);
+export class foo {
+  template <typename T>
+  friend class bar;
+  friend class gua;
+  template <typename T>
+  friend void hello();
+  friend void hi();
+  friend bool operator<(const foo &a, const foo &b);
+};
+} // namespace Friend


        


More information about the cfe-commits mailing list