Author: Chuanqi Xu Date: 2026-01-14T02:54:03Z New Revision: c560f1cf03aa06c0bdd00c5a9b558c16d882af6f
URL: https://github.com/llvm/llvm-project/commit/c560f1cf03aa06c0bdd00c5a9b558c16d882af6f DIFF: https://github.com/llvm/llvm-project/commit/c560f1cf03aa06c0bdd00c5a9b558c16d882af6f.diff LOG: [Serialization] Stop demote var definition as declaration (#172430) Close https://github.com/llvm/llvm-project/issues/172241 Close https://github.com/llvm/llvm-project/issues/64034 Close https://github.com/llvm/llvm-project/issues/149404 Close https://github.com/llvm/llvm-project/issues/174858 After this patch, we (the clang dev) no longer assumes there are at most one definition in a redeclaration chain. See https://discourse.llvm.org/t/rfc-clang-not-assuming-there-is-at-most-one-definition-in-a-redeclaration-chain/89360 for details. Added: clang/test/Modules/pr149404-02.cppm clang/test/Modules/pr172241.cppm Modified: clang/lib/Serialization/ASTReaderDecl.cpp Removed: ################################################################################ diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index f8e9caa3f5d1d..f0fb247f1afb9 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -3642,23 +3642,9 @@ template<> void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, Redeclarable<VarDecl> *D, Decl *Previous, Decl *Canon) { - auto *VD = static_cast<VarDecl *>(D); auto *PrevVD = cast<VarDecl>(Previous); D->RedeclLink.setPrevious(PrevVD); D->First = PrevVD->First; - - // We should keep at most one definition on the chain. - // FIXME: Cache the definition once we've found it. Building a chain with - // N definitions currently takes O(N^2) time here. - if (VD->isThisDeclarationADefinition() == VarDecl::Definition) { - for (VarDecl *CurD = PrevVD; CurD; CurD = CurD->getPreviousDecl()) { - if (CurD->isThisDeclarationADefinition() == VarDecl::Definition) { - Reader.mergeDefinitionVisibility(CurD, VD); - VD->demoteThisDefinitionToDeclaration(); - break; - } - } - } } static bool isUndeducedReturnType(QualType T) { diff --git a/clang/test/Modules/pr149404-02.cppm b/clang/test/Modules/pr149404-02.cppm new file mode 100644 index 0000000000000..291619ea05b8a --- /dev/null +++ b/clang/test/Modules/pr149404-02.cppm @@ -0,0 +1,104 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -std=c++20 -emit-module-interface -o %t/format.pcm %t/format.cppm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface -o %t/includes_in_gmf.pcm %t/includes_in_gmf.cppm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/test.cpp -verify -fsyntax-only + +// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface -o %t/format.pcm %t/format.cppm +// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface -o %t/includes_in_gmf.pcm %t/includes_in_gmf.cppm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/test.cpp -verify -fsyntax-only + +//--- format.h +#pragma once + +namespace test { + +template <class _Tp> +struct type_identity { + typedef _Tp type; +}; + +template <class _Tp> +using type_identity_t = typename type_identity<_Tp>::type; + + +template <class _Tp, class _CharT> +struct formatter +{ + formatter() = delete; +}; + +template <> +struct formatter<char, char> +{}; + +template <class _CharT, class... _Args> +struct basic_format_string { + static inline const int __handles_{ [] { + formatter<char, _CharT> f; + (void)f; + return 0; + }() }; + + consteval basic_format_string(const _CharT*) { + (void)__handles_; + } +}; + +template <class... _Args> +using wformat_string = basic_format_string<wchar_t, type_identity_t<_Args>...>; + +template <class... _Args> +using format_string = basic_format_string<char, type_identity_t<_Args>...>; + +template <class... _Args> +void format(format_string<_Args...> __fmt, _Args&&... __args) {} + +template <class... _Args> +void format(wformat_string<_Args...> __fmt, _Args&&... __args) {} + +} + +//--- format.cppm +module; +#include "format.h" +export module format; + +export namespace test { + using test::format; + using test::formatter; + using test::format_string; +} + +auto something() -> void +{ + auto a = 'a'; + test::format("{}", a); +} + +//--- includes_in_gmf.cppm +module; +#include "format.h" +export module includes_in_gmf; + +namespace test { + using test::format; + using test::formatter; + using test::format_string; +} + +//--- test.cpp +// expected-no-diagnostics +import format; +import includes_in_gmf; + +auto what() -> void +{ + auto a = 'a'; + test::format("{}", a); + + constexpr auto fs = "{}"; // test::format_string<char>{ "{}" }; // <- same result even passing exact param type + test::format(fs, 'r'); +} diff --git a/clang/test/Modules/pr172241.cppm b/clang/test/Modules/pr172241.cppm new file mode 100644 index 0000000000000..3eb885e8b2d9f --- /dev/null +++ b/clang/test/Modules/pr172241.cppm @@ -0,0 +1,47 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/m.cppm -emit-module-interface -o %t/m.pcm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/use.cpp -fmodule-file=m=%t/m.pcm -emit-llvm -o - | FileCheck %t/use.cpp +// +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/m.cppm -emit-reduced-module-interface -o %t/m.pcm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/use.cpp -fmodule-file=m=%t/m.pcm -emit-llvm -o - | FileCheck %t/use.cpp + +//--- header.h +#pragma once + +template <unsigned T> +class Templ { +public: + void lock() { __set_locked_bit(); } + +private: + static constexpr auto __set_locked_bit = [](){}; +}; + +class JT { +public: + ~JT() { + Templ<4> state; + state.lock(); + } +}; + +//--- m.cppm +module; +#include "header.h" +export module m; +export struct M { + JT jt; +}; +//--- use.cpp +#include "header.h" +import m; + +int main() { + M m; + return 0; +} + +// CHECK: @_ZN5TemplILj4EE16__set_locked_bitE = {{.*}}linkonce_odr _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
