diff options
author | Hana Dusíková <hanicka@hanicka.net> | 2021-04-13 15:45:09 -0400 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2021-04-13 15:45:09 -0400 |
commit | 64c24f493e5f4637ee193f10f469cdd2695b4ba6 (patch) | |
tree | 1f307b8a3e2babf3e60926bdc11a07158e4823eb /clang/lib/Sema/SemaInit.cpp | |
parent | 5b15fe9334b802b928f2f6cfedde31bb8cba72ee (diff) | |
download | llvm-64c24f493e5f4637ee193f10f469cdd2695b4ba6.zip llvm-64c24f493e5f4637ee193f10f469cdd2695b4ba6.tar.gz llvm-64c24f493e5f4637ee193f10f469cdd2695b4ba6.tar.bz2 |
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
Diffstat (limited to 'clang/lib/Sema/SemaInit.cpp')
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index ec7e472..c8e8c86 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -1007,21 +1007,33 @@ static bool isIdiomaticBraceElisionEntity(const InitializedEntity &Entity) { // // (where std::array is an aggregate struct containing a single array field. - // FIXME: Should aggregate initialization of a struct with a single - // base class and no members also suppress the warning? - if (Entity.getKind() != InitializedEntity::EK_Member || !Entity.getParent()) + if (!Entity.getParent()) return false; - auto *ParentRD = - Entity.getParent()->getType()->castAs<RecordType>()->getDecl(); - if (CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(ParentRD)) - if (CXXRD->getNumBases()) - return false; + // Allows elide brace initialization for aggregates with empty base. + if (Entity.getKind() == InitializedEntity::EK_Base) { + auto *ParentRD = + Entity.getParent()->getType()->castAs<RecordType>()->getDecl(); + CXXRecordDecl *CXXRD = cast<CXXRecordDecl>(ParentRD); + return CXXRD->getNumBases() == 1 && CXXRD->field_empty(); + } + + // Allow brace elision if the only subobject is a field. + if (Entity.getKind() == InitializedEntity::EK_Member) { + auto *ParentRD = + 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(); + } - 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 |