]> granicus.if.org Git - clang/commitdiff
Sema: Disallow derived classes with virtual bases from having flexible array members
authorDavid Majnemer <david.majnemer@gmail.com>
Sat, 2 Nov 2013 11:19:13 +0000 (11:19 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Sat, 2 Nov 2013 11:19:13 +0000 (11:19 +0000)
Flexible array members only work out if they are the last field of a
record, however virtual bases would give us many situations where the
flexible array member would overlap with the virtual base fields.

It is unlikely in the extreme that this behavior was intended by the
user so raise a diagnostic instead of accepting.  This is will not
reject conforming code because flexible array members are an extension
in C++ mode.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@193920 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
test/SemaCXX/flexible-array-test.cpp

index ae2d9c9e779df6dcd86f37ed6fd7c8928d11ec9f..86108be0b93661bab115a81b0db740e9bb9bab79 100644 (file)
@@ -3937,6 +3937,9 @@ def ext_variable_sized_type_in_struct : ExtWarn<
 
 def ext_c99_flexible_array_member : Extension<
   "flexible array members are a C99 feature">, InGroup<C99>;
+def err_flexible_array_virtual_base : Error<
+  "flexible array member %0 not allowed in "
+  "%select{struct|interface|union|class|enum}1 which has a virtual base class">;
 def err_flexible_array_empty_aggregate : Error<
   "flexible array member %0 not allowed in otherwise empty "
   "%select{struct|interface|union|class|enum}1 is not allowed">;
index 101f4ce8988a315f7237c6f70511882e9645bd1b..d9dd4507de6202eec33b0ca13031b38122e508b5 100644 (file)
@@ -11841,6 +11841,15 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
       if (DiagID)
         Diag(FD->getLocation(), DiagID) << FD->getDeclName()
                                         << Record->getTagKind();
+      // While the layout of types that contain virtual bases is not specified
+      // by the C++ standard, both the Itanium and Microsoft C++ ABIs place
+      // virtual bases after the derived members.  This would make a flexible
+      // array member declared at the end of an object not adjacent to the end
+      // of the type.
+      if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record))
+        if (RD->getNumVBases() != 0)
+          Diag(FD->getLocation(), diag::err_flexible_array_virtual_base)
+            << FD->getDeclName() << Record->getTagKind();
       if (!getLangOpts().C99)
         Diag(FD->getLocation(), diag::ext_c99_flexible_array_member)
           << FD->getDeclName() << Record->getTagKind();
index e6c3132801f805e9b35d261a488404558033e4c2..f287711eeb6a5de5442ea31475235019a9720db2 100644 (file)
@@ -66,4 +66,8 @@ struct Storage : StorageBase {
   int data[];
 };
 
+struct VirtStorage : virtual StorageBase {
+  int data[]; // expected-error {{flexible array member 'data' not allowed in struct which has a virtual base class}}
+};
+
 }