diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index f0fb247f1afb9..f8e9caa3f5d1d 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -3642,9 +3642,23 @@ template<> void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, Redeclarable *D, Decl *Previous, Decl *Canon) { + auto *VD = static_cast(D); auto *PrevVD = cast(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 deleted file mode 100644 index 291619ea05b8a..0000000000000 --- a/clang/test/Modules/pr149404-02.cppm +++ /dev/null @@ -1,104 +0,0 @@ -// 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 -struct type_identity { - typedef _Tp type; -}; - -template -using type_identity_t = typename type_identity<_Tp>::type; - - -template -struct formatter -{ - formatter() = delete; -}; - -template <> -struct formatter -{}; - -template -struct basic_format_string { - static inline const int __handles_{ [] { - formatter f; - (void)f; - return 0; - }() }; - - consteval basic_format_string(const _CharT*) { - (void)__handles_; - } -}; - -template -using wformat_string = basic_format_string...>; - -template -using format_string = basic_format_string...>; - -template -void format(format_string<_Args...> __fmt, _Args&&... __args) {} - -template -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{ "{}" }; // <- 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 deleted file mode 100644 index 3eb885e8b2d9f..0000000000000 --- a/clang/test/Modules/pr172241.cppm +++ /dev/null @@ -1,47 +0,0 @@ -// 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 -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