hankadusikova updated this revision to Diff 337067.
hankadusikova marked 3 inline comments as done.
hankadusikova added a comment.

changes suggested by @rsmith


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100057/new/

https://reviews.llvm.org/D100057

Files:
  clang/lib/Sema/SemaInit.cpp
  clang/test/SemaCXX/aggregate-initialization.cpp


Index: clang/test/SemaCXX/aggregate-initialization.cpp
===================================================================
--- clang/test/SemaCXX/aggregate-initialization.cpp
+++ clang/test/SemaCXX/aggregate-initialization.cpp
@@ -172,11 +172,20 @@
   };
   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
-  // pattern becomes idiomatic, it would be reasonable to suppress the
-  // warning here too.
+  // This pattern is used for tagged aggregates and must not warn
   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
 
 #pragma clang diagnostic pop
Index: clang/lib/Sema/SemaInit.cpp
===================================================================
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -1007,21 +1007,33 @@
   //
   // (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


Index: clang/test/SemaCXX/aggregate-initialization.cpp
===================================================================
--- clang/test/SemaCXX/aggregate-initialization.cpp
+++ clang/test/SemaCXX/aggregate-initialization.cpp
@@ -172,11 +172,20 @@
   };
   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
-  // pattern becomes idiomatic, it would be reasonable to suppress the
-  // warning here too.
+  // This pattern is used for tagged aggregates and must not warn
   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
 
 #pragma clang diagnostic pop
Index: clang/lib/Sema/SemaInit.cpp
===================================================================
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -1007,21 +1007,33 @@
   //
   // (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
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D1000... Hana Dusíková via Phabricator via cfe-commits
    • [PATCH] ... Michael Schellenberger Costa via Phabricator via cfe-commits
    • [PATCH] ... Hana Dusíková via Phabricator via cfe-commits
    • [PATCH] ... Roman Lebedev via Phabricator via cfe-commits
    • [PATCH] ... Hana Dusíková via Phabricator via cfe-commits
    • [PATCH] ... JF Bastien via Phabricator via cfe-commits
    • [PATCH] ... Hana Dusíková via Phabricator via cfe-commits
    • [PATCH] ... Hana Dusíková via Phabricator via cfe-commits
    • [PATCH] ... Louis Dionne via Phabricator via cfe-commits
    • [PATCH] ... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] ... Hana Dusíková via Phabricator via cfe-commits
    • [PATCH] ... Aaron Ballman via Phabricator via cfe-commits
    • [PATCH] ... Aaron Ballman via Phabricator via cfe-commits

Reply via email to