Author: Chuanqi Xu
Date: 2025-03-13T11:02:57+08:00
New Revision: 4d8070e9560269494654bd21a2b0c342f4bdae48

URL: 
https://github.com/llvm/llvm-project/commit/4d8070e9560269494654bd21a2b0c342f4bdae48
DIFF: 
https://github.com/llvm/llvm-project/commit/4d8070e9560269494654bd21a2b0c342f4bdae48.diff

LOG: [C++20] [Modules] Don't add decls from other units to undefinedButUsed set

It is still better to elide the declaration if possible. To overcome the
false positive undefinedButUsed diagnostic, it seems better to not add
declaration from other units to the set actually.

Added: 
    

Modified: 
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/lib/Serialization/ASTWriterDecl.cpp
    clang/test/Modules/external-but-not-type-external.cppm

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 9c67fbd40ac71..61e3cd4066a8d 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -3829,11 +3829,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, 
NamedDecl *&OldD, Scope *S,
 
   // If this redeclaration makes the function inline, we may need to add it to
   // UndefinedButUsed.
-  if (!Old->isInlined() && New->isInlined() &&
-      !New->hasAttr<GNUInlineAttr>() &&
-      !getLangOpts().GNUInline &&
-      Old->isUsed(false) &&
-      !Old->isDefined() && !New->isThisDeclarationADefinition())
+  if (!Old->isInlined() && New->isInlined() && !New->hasAttr<GNUInlineAttr>() 
&&
+      !getLangOpts().GNUInline && Old->isUsed(false) && !Old->isDefined() &&
+      !New->isThisDeclarationADefinition() && !Old->isInAnotherModuleUnit())
     UndefinedButUsed.insert(std::make_pair(Old->getCanonicalDecl(),
                                            SourceLocation()));
 
@@ -4700,7 +4698,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult 
&Previous) {
   // If this redeclaration makes the variable inline, we may need to add it to
   // UndefinedButUsed.
   if (!Old->isInline() && New->isInline() && Old->isUsed(false) &&
-      !Old->getDefinition() && !New->isThisDeclarationADefinition())
+      !Old->getDefinition() && !New->isThisDeclarationADefinition() &&
+      !Old->isInAnotherModuleUnit())
     UndefinedButUsed.insert(std::make_pair(Old->getCanonicalDecl(),
                                            SourceLocation()));
 

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index a36a2f563739e..7d4d3cc24e539 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -18355,7 +18355,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, 
FunctionDecl *Func,
   // If this is the first "real" use, act on that.
   if (OdrUse == OdrUseContext::Used && !Func->isUsed(/*CheckUsedAttr=*/false)) 
{
     // Keep track of used but undefined functions.
-    if (!Func->isDefined()) {
+    if (!Func->isDefined() && !Func->isInAnotherModuleUnit()) {
       if (mightHaveNonExternalLinkage(Func))
         UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
       else if (Func->getMostRecentDecl()->isInlined() &&

diff  --git a/clang/lib/Serialization/ASTWriterDecl.cpp 
b/clang/lib/Serialization/ASTWriterDecl.cpp
index d4551348b168b..0cb9c4db810d1 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -331,12 +331,6 @@ namespace clang {
 }
 
 bool clang::CanElideDeclDef(const Decl *D) {
-  bool isExternalWithNoLinkageType = false;
-  if (auto *VD = dyn_cast<ValueDecl>(D))
-    if (VD->hasExternalFormalLinkage() &&
-        !isExternalFormalLinkage(VD->getType()->getLinkage()))
-      isExternalWithNoLinkageType = true;
-
   if (auto *FD = dyn_cast<FunctionDecl>(D)) {
     if (FD->isInlined() || FD->isConstexpr())
       return false;
@@ -346,9 +340,6 @@ bool clang::CanElideDeclDef(const Decl *D) {
 
     if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
       return false;
-
-    if (isExternalWithNoLinkageType && !FD->isExternC())
-      return false;
   }
 
   if (auto *VD = dyn_cast<VarDecl>(D)) {
@@ -362,9 +353,6 @@ bool clang::CanElideDeclDef(const Decl *D) {
 
     if (VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
       return false;
-
-    if (isExternalWithNoLinkageType && !VD->isExternC())
-      return false;
   }
 
   return true;

diff  --git a/clang/test/Modules/external-but-not-type-external.cppm 
b/clang/test/Modules/external-but-not-type-external.cppm
index 37a0d29104c5d..349e20fdae1e8 100644
--- a/clang/test/Modules/external-but-not-type-external.cppm
+++ b/clang/test/Modules/external-but-not-type-external.cppm
@@ -2,8 +2,10 @@
 // RUN: split-file %s %t
 // RUN: cd %t
 //
-// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o 
%t/a.pcm
-// RUN: %clang_cc1 -std=c++20 %t/use.cc -fmodule-file=a=%t/a.pcm -fsyntax-only 
-verify
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm 
-emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/use.cc 
-fmodule-file=a=%t/a.pcm -fsyntax-only -verify
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/use.cc 
-fmodule-file=a=%t/a.pcm -emit-llvm -o - | \
+// RUN:     FileCheck %t/use.cc
 
 //--- a.cppm
 export module a;
@@ -25,3 +27,5 @@ void *use() {
     A a;
     return a.external_but_not_type_external(nullptr);
 }
+
+// CHECK-NOT: define 
{{.*}}@_ZNW1a1A30external_but_not_type_externalEPN12_GLOBAL__N_15LocalE


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

Reply via email to