aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaInit.cpp
diff options
context:
space:
mode:
authorHana Dusíková <hanicka@hanicka.net>2021-04-13 15:45:09 -0400
committerAaron Ballman <aaron@aaronballman.com>2021-04-13 15:45:09 -0400
commit64c24f493e5f4637ee193f10f469cdd2695b4ba6 (patch)
tree1f307b8a3e2babf3e60926bdc11a07158e4823eb /clang/lib/Sema/SemaInit.cpp
parent5b15fe9334b802b928f2f6cfedde31bb8cba72ee (diff)
downloadllvm-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.cpp36
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