diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 31 |
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() |