Remove warning "suggest braces" for aggregate initialization of an empty class with an aggregate base class.
I recently ran into issues with aggregates and inheritance, I'm using it for creating a type-safe library where most of the types are build over "tagged" std::array. After bit of cleaning and enabling -Wall -Wextra -pedantic I noticed clang only in my pipeline gives me warning. After a bit of focusing on it I found it's not helpful, and contemplate disabling the warning all together. After a discussion with other library authors I found it's bothering more people and decided to fix it. Removes this warning: template<typename T, int N> struct StdArray { T contents[N]; }; template<typename T, int N> struct AggregateAndEmpty : StdArray<T,N> { }; AggregateAndEmpty<int, 3> p = {1, 2, 3}; // <-- warning here about omitted braces
This commit is contained in:
parent
5b15fe9334
commit
64c24f493e
@ -1007,21 +1007,33 @@ static bool isIdiomaticBraceElisionEntity(const InitializedEntity &Entity) {
|
|||||||
//
|
//
|
||||||
// (where std::array is an aggregate struct containing a single array field.
|
// (where std::array is an aggregate struct containing a single array field.
|
||||||
|
|
||||||
// FIXME: Should aggregate initialization of a struct with a single
|
if (!Entity.getParent())
|
||||||
// base class and no members also suppress the warning?
|
|
||||||
if (Entity.getKind() != InitializedEntity::EK_Member || !Entity.getParent())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto *ParentRD =
|
// Allows elide brace initialization for aggregates with empty base.
|
||||||
Entity.getParent()->getType()->castAs<RecordType>()->getDecl();
|
if (Entity.getKind() == InitializedEntity::EK_Base) {
|
||||||
if (CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(ParentRD))
|
auto *ParentRD =
|
||||||
if (CXXRD->getNumBases())
|
Entity.getParent()->getType()->castAs<RecordType>()->getDecl();
|
||||||
return false;
|
CXXRecordDecl *CXXRD = cast<CXXRecordDecl>(ParentRD);
|
||||||
|
return CXXRD->getNumBases() == 1 && CXXRD->field_empty();
|
||||||
|
}
|
||||||
|
|
||||||
auto FieldIt = ParentRD->field_begin();
|
// Allow brace elision if the only subobject is a field.
|
||||||
assert(FieldIt != ParentRD->field_end() &&
|
if (Entity.getKind() == InitializedEntity::EK_Member) {
|
||||||
"no fields but have initializer for member?");
|
auto *ParentRD =
|
||||||
return ++FieldIt == ParentRD->field_end();
|
Entity.getParent()->getType()->castAs<RecordType>()->getDecl();
|
||||||
|
if (CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(ParentRD)) {
|
||||||
|
if (CXXRD->getNumBases()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto FieldIt = ParentRD->field_begin();
|
||||||
|
assert(FieldIt != ParentRD->field_end() &&
|
||||||
|
"no fields but have initializer for member?");
|
||||||
|
return ++FieldIt == ParentRD->field_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether the range of the initializer \p ParentIList from element
|
/// Check whether the range of the initializer \p ParentIList from element
|
||||||
|
@ -172,11 +172,20 @@ namespace IdiomaticStdArrayInitDoesNotWarn {
|
|||||||
};
|
};
|
||||||
ArrayAndBaseClass<int, 3> z = {1, 2, 3}; // expected-warning {{suggest braces}}
|
ArrayAndBaseClass<int, 3> z = {1, 2, 3}; // expected-warning {{suggest braces}}
|
||||||
|
|
||||||
// It's not clear whether we should be warning in this case. If this
|
// This pattern is used for tagged aggregates and must not warn
|
||||||
// pattern becomes idiomatic, it would be reasonable to suppress the
|
|
||||||
// warning here too.
|
|
||||||
template<typename T, int N> struct JustABaseClass : StdArray<T, N> {};
|
template<typename T, int N> struct JustABaseClass : StdArray<T, N> {};
|
||||||
JustABaseClass<int, 3> w = {1, 2, 3}; // expected-warning {{suggest braces}}
|
JustABaseClass<int, 3> w = {1, 2, 3};
|
||||||
|
// but this should be also ok
|
||||||
|
JustABaseClass<int, 3> v = {{1, 2, 3}};
|
||||||
|
|
||||||
|
template <typename T, int N> struct OnionBaseClass : JustABaseClass<T, N> {};
|
||||||
|
OnionBaseClass<int, 3> u = {1, 2, 3};
|
||||||
|
OnionBaseClass<int, 3> t = {{{1, 2, 3}}};
|
||||||
|
|
||||||
|
struct EmptyBase {};
|
||||||
|
|
||||||
|
template <typename T, int N> struct AggregateAndEmpty : StdArray<T, N>, EmptyBase {};
|
||||||
|
AggregateAndEmpty<int, 3> p = {1, 2, 3}; // expected-warning {{suggest braces}}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
Loading…
x
Reference in New Issue
Block a user