Skip to content

Commit 40ac423

Browse files
committed
Add more descriptive messages for
indirect base class inheritance
1 parent 6f787e1 commit 40ac423

File tree

4 files changed

+33
-3
lines changed

4 files changed

+33
-3
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,6 +1794,7 @@ def note_unsatisfied_trait_reason
17941794
"%MultipleDataBase{has multiple base classes with data members}|"
17951795
"%VirtualFunction{has virtual functions}|"
17961796
"%NonStdLayoutMember{has a non-standard-layout member %1 of type %2}|"
1797+
"%IndirectBaseWithFields{has an indirect base %1 with data members}|"
17971798
"%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|"
17981799
"%UserProvidedCtr{has a user provided %select{copy|move}1 "
17991800
"constructor}|"

clang/lib/Sema/SemaTypeTraits.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2407,6 +2407,37 @@ static void DiagnoseNonStandardLayoutReason(Sema &SemaRef, SourceLocation Loc,
24072407
<< Field->getType() << Field->getSourceRange();
24082408
}
24092409
}
2410+
2411+
// if this class and an indirect base
2412+
// both have non-static data members, grab the first such base.
2413+
if (D->hasDirectFields()) {
2414+
SmallVector<const CXXRecordDecl *, 4> Records;
2415+
2416+
// Recursive lambda to collect all bases that declare fields
2417+
std::function<void(const CXXRecordDecl *)> collect =
2418+
[&](const CXXRecordDecl *R) {
2419+
for (const CXXBaseSpecifier &B : R->bases()) {
2420+
const auto *BR = B.getType()->getAsCXXRecordDecl();
2421+
if (!BR || !BR->hasDefinition())
2422+
continue;
2423+
if (BR->hasDirectFields())
2424+
Records.push_back(BR);
2425+
// Recurse into the base class.
2426+
collect(BR);
2427+
}
2428+
};
2429+
2430+
// Collect all bases that declare fields.
2431+
collect(D);
2432+
2433+
// If more than one record has fields, then the layout is non-standard.
2434+
if (!Records.empty()) {
2435+
const CXXRecordDecl *Indirect = Records.front();
2436+
SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
2437+
<< diag::TraitNotSatisfiedReason::IndirectBaseWithFields << Indirect
2438+
<< Indirect->getSourceRange();
2439+
}
2440+
}
24102441
}
24112442

24122443
static void DiagnoseNonStandardLayoutReason(Sema &SemaRef, SourceLocation Loc,

clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,6 @@ namespace test_namespace {
217217
}
218218

219219

220-
221220
namespace concepts {
222221
template <typename T>
223222
requires std::is_trivially_relocatable<T>::value void f(); // #cand1
@@ -288,5 +287,3 @@ static_assert(std::is_replaceable_v<int&>);
288287
// expected-error@-1 {{static assertion failed due to requirement 'std::is_replaceable_v<int &>'}} \
289288
// expected-note@-1 {{'int &' is not replaceable}} \
290289
// expected-note@-1 {{because it is a reference type}}
291-
292-

clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,7 @@ struct BaseC: BaseB { int c; }; // #sl-BaseC
621621
static_assert(__is_standard_layout(BaseC));
622622
// expected-error@-1 {{static assertion failed due to requirement '__is_standard_layout(standard_layout_tests::BaseC)'}} \
623623
// expected-note@-1 {{'BaseC' is not standard-layout}} \
624+
// expected-note@-1 {{because it has an indirect base 'BaseA' with data members}} \
624625
// expected-note@#sl-BaseC {{'BaseC' defined here}} \
625626
626627
// Multiple direct base classes with no data members --> standard layout

0 commit comments

Comments
 (0)