Skip to content

Commit

Permalink
[Modules] Do not rewrite existing decls when deserializing class fields
Browse files Browse the repository at this point in the history
Classes can have implicit members that were added before fields were
deserialized. These members were previously silently removed from
`decls()` when fields were deserialized after them.

This was the root cause of a compilation error exposed in
bc95f27, added a test for it.

Reviewed By: ChuanqiXu

Differential Revision: https://reviews.llvm.org/D148515
  • Loading branch information
ilya-biryukov committed Apr 18, 2023
1 parent 2948316 commit ccf7191
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 2 deletions.
9 changes: 7 additions & 2 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4886,8 +4886,13 @@ void RecordDecl::LoadFieldsFromExternalStorage() const {
if (Decls.empty())
return;

std::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls,
/*FieldsAlreadyLoaded=*/false);
auto [ExternalFirst, ExternalLast] =
BuildDeclChain(Decls,
/*FieldsAlreadyLoaded=*/false);
ExternalLast->NextInContextAndBits.setPointer(FirstDecl);
FirstDecl = ExternalFirst;
if (!LastDecl)
LastDecl = ExternalLast;
}

bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const {
Expand Down
71 changes: 71 additions & 0 deletions clang/test/Modules/pr61065_2.cppm
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: split-file %s %t
//
// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm
// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-module-interface -o %t/b.pcm \
// RUN: -fprebuilt-module-path=%t
// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-module-interface -o %t/c.pcm \
// RUN: -fprebuilt-module-path=%t
// RUN: %clang_cc1 -std=c++20 %t/d.cppm -emit-module-interface -o %t/d.pcm \
// RUN: -fprebuilt-module-path=%t
// RUN: %clang_cc1 -std=c++20 %t/e.cpp -fsyntax-only -verify -fprebuilt-module-path=%t

//--- a.cppm
export module a;

struct WithCtor {
WithCtor();
};

export template <typename T>
struct Getter {
union {
WithCtor container;
};
};

//--- b.cppm
export module b;

import a;

export template <typename T>
class AnySpan {
public:
AnySpan();
AnySpan(Getter<T> getter)
: getter_(getter) {}

private:
Getter<T> getter_;
};

//--- c.cppm
export module c;
import b;

export inline void RegisterInt322(
AnySpan<const int> sibling_field_nums) {
sibling_field_nums = sibling_field_nums;
}

//--- d.cppm
// expected-no-diagnostics
export module d;
import c;
import b;

export inline void RegisterInt32(
AnySpan<const int> sibling_field_nums = {}) {
sibling_field_nums = sibling_field_nums;
}

//--- e.cpp
import d;
import b;

// expected-no-diagnostics
void foo(AnySpan<const int> s) {
s = AnySpan<const int>(s);
}

0 comments on commit ccf7191

Please sign in to comment.