Author: Chuanqi Xu
Date: 2023-11-10T10:58:07+08:00
New Revision: 0e7b30fa821dd4899227aa643030f4e4164f4e56

URL: 
https://github.com/llvm/llvm-project/commit/0e7b30fa821dd4899227aa643030f4e4164f4e56
DIFF: 
https://github.com/llvm/llvm-project/commit/0e7b30fa821dd4899227aa643030f4e4164f4e56.diff

LOG: [C++20] [Modules] Enhance better diagnostic for implicit global module and 
module partitions

Due to an oversight, when users use an unexported declaration from
implicit global module, the diagnostic will show "please #include"
instead of "please import". This patch corrects the behavior.

Also previously, when users use an unexported declarations from module
partitions, the diagnostic message will always show the partition name
no matter if that partition name is visible to the users. Now the users
may only see the partition name if the users are in the same module with
the partition unit.

Added: 
    

Modified: 
    clang/lib/Sema/SemaLookup.cpp
    clang/test/CXX/module/module.import/p2.cpp
    clang/test/CXX/module/module.reach/ex1.cpp
    clang/test/CXX/module/module.reach/p2.cpp
    clang/test/Modules/export-language-linkage.cppm

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index be011b9f4368d2c..54b48f7ab80eb9c 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -5723,7 +5723,7 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, 
const NamedDecl *Decl,
   llvm::SmallVector<Module*, 8> UniqueModules;
   llvm::SmallDenseSet<Module*, 8> UniqueModuleSet;
   for (auto *M : Modules) {
-    if (M->isGlobalModule() || M->isPrivateModule())
+    if (M->isExplicitGlobalModule() || M->isPrivateModule())
       continue;
     if (UniqueModuleSet.insert(M).second)
       UniqueModules.push_back(M);
@@ -5755,6 +5755,28 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, 
const NamedDecl *Decl,
 
   Modules = UniqueModules;
 
+  auto GetModuleNameForDiagnostic = [this](const Module *M) -> std::string {
+    if (M->isModuleMapModule())
+      return M->getFullModuleName();
+
+    Module *CurrentModule = getCurrentModule();
+
+    if (M->isImplicitGlobalModule())
+      M = M->getTopLevelModule();
+
+    bool IsInTheSameModule =
+        CurrentModule && CurrentModule->getPrimaryModuleInterfaceName() ==
+                             M->getPrimaryModuleInterfaceName();
+
+    // If the current module unit is in the same module with M, it is OK to 
show
+    // the partition name. Otherwise, it'll be sufficient to show the primary
+    // module name.
+    if (IsInTheSameModule)
+      return M->getTopLevelModuleName().str();
+    else
+      return M->getPrimaryModuleInterfaceName().str();
+  };
+
   if (Modules.size() > 1) {
     std::string ModuleList;
     unsigned N = 0;
@@ -5764,7 +5786,7 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, 
const NamedDecl *Decl,
         ModuleList += "[...]";
         break;
       }
-      ModuleList += M->getFullModuleName();
+      ModuleList += GetModuleNameForDiagnostic(M);
     }
 
     Diag(UseLoc, diag::err_module_unimported_use_multiple)
@@ -5772,7 +5794,7 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, 
const NamedDecl *Decl,
   } else {
     // FIXME: Add a FixItHint that imports the corresponding module.
     Diag(UseLoc, diag::err_module_unimported_use)
-      << (int)MIK << Decl << Modules[0]->getFullModuleName();
+        << (int)MIK << Decl << GetModuleNameForDiagnostic(Modules[0]);
   }
 
   NotePrevious();

diff  --git a/clang/test/CXX/module/module.import/p2.cpp 
b/clang/test/CXX/module/module.import/p2.cpp
index 0c02d253f3a898f..ef6006811e77631 100644
--- a/clang/test/CXX/module/module.import/p2.cpp
+++ b/clang/test/CXX/module/module.import/p2.cpp
@@ -23,8 +23,8 @@ export A f();
 //--- Use.cpp
 import M;
 void test() {
-  A a; // expected-error {{declaration of 'A' must be imported from module 
'M:impl'}}
-       // expected-error@-1 {{definition of 'A' must be imported from module 
'M:impl'}} expected-error@-1 {{}}
+  A a; // expected-error {{definition of 'A' must be imported from module 'M' 
before it is required}}
+       // expected-error@-1 {{definition of 'A' must be imported from module 
'M' before it is required}} expected-error@-1 {{}}
        // expected-n...@impl.cppm:2 {{declaration here is not visible}}
        // expected-n...@impl.cppm:2 {{definition here is not reachable}} 
expected-n...@impl.cppm:2 {{}}
 }
@@ -41,8 +41,8 @@ void test() {
 export module B;
 import M;
 void test() {
-  A a; // expected-error {{declaration of 'A' must be imported from module 
'M:impl'}}
-       // expected-error@-1 {{definition of 'A' must be imported from module 
'M:impl'}} expected-error@-1 {{}}
+  A a; // expected-error {{declaration of 'A' must be imported from module 
'M'}}
+       // expected-error@-1 {{definition of 'A' must be imported from module 
'M'}} expected-error@-1 {{}}
        // expected-n...@impl.cppm:2 {{declaration here is not visible}}
        // expected-n...@impl.cppm:2 {{definition here is not reachable}} 
expected-n...@impl.cppm:2 {{}}
 }

diff  --git a/clang/test/CXX/module/module.reach/ex1.cpp 
b/clang/test/CXX/module/module.reach/ex1.cpp
index a1e38c4c88a2885..96d06f9a3e0f69a 100644
--- a/clang/test/CXX/module/module.reach/ex1.cpp
+++ b/clang/test/CXX/module/module.reach/ex1.cpp
@@ -37,10 +37,10 @@ export void f(B b = B());
 //--- X.cppm
 export module X;
 import M;
-B b3; // expected-error {{definition of 'B' must be imported from module 'M:B' 
before it is required}} expected-error {{}}
+B b3; // expected-error {{definition of 'B' must be imported from module 'M' 
before it is required}} expected-error {{}}
       // expected-note@* {{definition here is not reachable}} expected-note@* 
{{}}
 // FIXME: We should emit an error for unreachable definition of B.
 void g() { f(); }
-void g1() { f(B()); } // expected-error 1+{{definition of 'B' must be imported 
from module 'M:B' before it is required}}
+void g1() { f(B()); } // expected-error 1+{{definition of 'B' must be imported 
from module 'M' before it is required}}
                       // expected-note@* 1+{{definition here is not reachable}}
                       // expected-n...@m.cppm:5 {{passing argument to 
parameter 'b' here}}

diff  --git a/clang/test/CXX/module/module.reach/p2.cpp 
b/clang/test/CXX/module/module.reach/p2.cpp
index 6ccf6ee6d0566d3..9242e6f2457e8f1 100644
--- a/clang/test/CXX/module/module.reach/p2.cpp
+++ b/clang/test/CXX/module/module.reach/p2.cpp
@@ -17,6 +17,6 @@ export A f();
 //--- UseStrict.cpp
 import M;
 void test() {
-  auto a = f(); // expected-error {{definition of 'A' must be imported from 
module 'M:impl' before it is required}} expected-error{{}}
+  auto a = f(); // expected-error {{definition of 'A' must be imported from 
module 'M' before it is required}} expected-error{{}}
                 // expected-note@* {{definition here is not reachable}} 
expected-note@* {{}}
 }

diff  --git a/clang/test/Modules/export-language-linkage.cppm 
b/clang/test/Modules/export-language-linkage.cppm
index 420e4be0ce45b63..462b28d36cb44b5 100644
--- a/clang/test/Modules/export-language-linkage.cppm
+++ b/clang/test/Modules/export-language-linkage.cppm
@@ -37,7 +37,7 @@ int use() {
     f1();
     f2();
     f3();
-    unexported(); // expected-error {{missing '#include'; 'unexported' must be 
declared before it is used}}
+    unexported(); // expected-error {{declaration of 'unexported' must be 
imported from module 'a' before it is required}}
                    // expected-n...@a.cppm:15 {{declaration here is not 
visible}}
     return foo();
 }
@@ -58,6 +58,6 @@ int use() {
 }
 
 int use_of_nonexported() {
-    return h(); // expected-error {{missing '#include'; 'h' must be declared 
before it is used}}
+    return h(); // expected-error {{declaration of 'h' must be imported from 
module 'c' before it is required}}
                 // expected-n...@c.cppm:4 {{declaration here is not visible}}
 }


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to