Sema: Consider it an error to apply __builtin_offsetof to a member in a virtual base
authorDavid Majnemer <david.majnemer@gmail.com>
Tue, 15 Oct 2013 06:28:23 +0000 (06:28 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Tue, 15 Oct 2013 06:28:23 +0000 (06:28 +0000)
icc 13 and g++ 4.9 both reject this while we would crash.

Fixes PR17578.

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExpr.cpp
test/SemaCXX/offsetof.cpp

index 8f68278eeb3e0d898e0a9b371c9b792113b56585..1c4f0bc50a2eb6b8061cc4a692d5539888e28d4d 100644 (file)
@@ -4200,6 +4200,8 @@ def warn_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">,
 def warn_offsetof_non_standardlayout_type : ExtWarn<
   "offset of on non-standard-layout type %0">, InGroup<InvalidOffsetof>;
 def err_offsetof_bitfield : Error<"cannot compute offset of bit-field %0">;
+def err_offsetof_field_of_virtual_base : Error<
+  "invalid application of 'offsetof' to a field of a virtual base">;
 def warn_sub_ptr_zero_size_types : Warning<
   "subtraction of pointers to type %0 of zero size has undefined behavior">,
   InGroup<PointerArith>;
index 6bcc49ed6236b4d210d768d88e015bd2772e1ff4..04e01f6ccb7e1d7a8298290871e0b27a2d576465 100644 (file)
@@ -9996,9 +9996,15 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
 
     // If the member was found in a base class, introduce OffsetOfNodes for
     // the base class indirections.
-    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
-                       /*DetectVirtual=*/false);
+    CXXBasePaths Paths;
     if (IsDerivedFrom(CurrentType, Context.getTypeDeclType(Parent), Paths)) {
+      if (Paths.getDetectedVirtual()) {
+        Diag(OC.LocEnd, diag::err_offsetof_field_of_virtual_base)
+          << MemberDecl->getDeclName()
+          << SourceRange(BuiltinLoc, RParenLoc);
+        return ExprError();
+      }
+
       CXXBasePath &Path = Paths.front();
       for (CXXBasePath::iterator B = Path.begin(), BEnd = Path.end();
            B != BEnd; ++B)
index a5f5d347c282ca013e9f014ce44a013726f821c8..e6069ac9c0a0708077baace5a94bd8cbd58a62ef 100644 (file)
@@ -73,3 +73,13 @@ struct LtoRCheck {
 };
 int ltor = __builtin_offsetof(struct LtoRCheck, a[LtoRCheck().f]); // \
   expected-error {{reference to non-static member function must be called}}
+
+namespace PR17578 {
+struct Base {
+  int Field;
+};
+struct Derived : virtual Base {
+  void Fun() { (void)__builtin_offsetof(Derived, Field); } // expected-warning {{offset of on non-POD type}} \
+                                                              expected-error {{invalid application of 'offsetof' to a field of a virtual base}}
+};
+}