summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaInit.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-10-03 20:36:00 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-10-03 20:36:00 +0000
commit283e2076f6a6f23629475a25c64173843e72cf61 (patch)
treebd89ce68e591932aa9361e034111d3c9959879c9 /clang/lib/Sema/SemaInit.cpp
parent389b7cedc311c785d9060d83197b555d227b4d7d (diff)
downloadbcm5719-llvm-283e2076f6a6f23629475a25c64173843e72cf61.tar.gz
bcm5719-llvm-283e2076f6a6f23629475a25c64173843e72cf61.zip
Suppress -Wmissing-braces warning when aggregate-initializing a struct with a single field that is itself an aggregate.
In C++, such initialization of std::array<T, N> types is guaranteed to work by the standard, is completely idiomatic, and the "suggested" alternative from Clang was technically invalid. llvm-svn: 314838
Diffstat (limited to 'clang/lib/Sema/SemaInit.cpp')
-rw-r--r--clang/lib/Sema/SemaInit.cpp31
1 files changed, 30 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 341e7120fe8..dc7fe1d92b0 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -826,6 +826,34 @@ int InitListChecker::numStructUnionElements(QualType DeclType) {
return InitializableMembers - structDecl->hasFlexibleArrayMember();
}
+/// Determine whether Entity is an entity for which it is idiomatic to elide
+/// the braces in aggregate initialization.
+static bool isIdiomaticBraceElisionEntity(const InitializedEntity &Entity) {
+ // Recursive initialization of the one and only field within an aggregate
+ // class is considered idiomatic. This case arises in particular for
+ // initialization of std::array, where the C++ standard suggests the idiom of
+ //
+ // std::array<T, N> arr = {1, 2, 3};
+ //
+ // (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())
+ return false;
+
+ 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();
+}
+
/// Check whether the range of the initializer \p ParentIList from element
/// \p Index onwards can be used to initialize an object of type \p T. Update
/// \p Index to indicate how many elements of the list were consumed.
@@ -887,7 +915,8 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
// Complain about missing braces.
if ((T->isArrayType() || T->isRecordType()) &&
- !ParentIList->isIdiomaticZeroInitializer(SemaRef.getLangOpts())) {
+ !ParentIList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) &&
+ !isIdiomaticBraceElisionEntity(Entity)) {
SemaRef.Diag(StructuredSubobjectInitList->getLocStart(),
diag::warn_missing_braces)
<< StructuredSubobjectInitList->getSourceRange()
OpenPOWER on IntegriCloud