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