t.p.northover created this revision.
Herald added a subscriber: mcrosier.

For the simple casts in the test, we were crashing because the 
ZeroInitialization function created an LValue with an unexpected 
SubobjectDesignator: it was valid but didn't actually refer to a valid 
MostDerivedType.

Since PointerExprEvaluator actually creates an LValue based notionally on what 
you'd get if you dereferenced the pointer (I think), the MostDerivedType should 
be set by stripping the pointer from the type as in this patch.

The theoretically simpler solution of providing an invalid SubobjectDesignator 
(as happens for an int to pointer cast) is incorrect because nullptr has more 
possible uses in constexprs than other casts of integers.

Does my reasoning look sound? I've been all over that file before I finally 
thought I knew what was going on and I'm still not entirely confident.


https://reviews.llvm.org/D33568

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/test/SemaCXX/null-cast.cpp


Index: clang/test/SemaCXX/null-cast.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/null-cast.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct A {};
+struct B : virtual A {};
+
+void foo() {
+  (void)static_cast<A&>(*(B *)0); // expected-warning {{binding dereferenced 
null pointer to reference has undefined behavior}}
+}
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -5496,6 +5496,8 @@
   bool ZeroInitialization(const Expr *E) {
     auto Offset = Info.Ctx.getTargetNullPointerValue(E->getType());
     Result.set((Expr*)nullptr, 0, false, true, Offset);
+    Result.getLValueDesignator() =
+        SubobjectDesignator(E->getType()->getPointeeType());
     return true;
   }
 


Index: clang/test/SemaCXX/null-cast.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/null-cast.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct A {};
+struct B : virtual A {};
+
+void foo() {
+  (void)static_cast<A&>(*(B *)0); // expected-warning {{binding dereferenced null pointer to reference has undefined behavior}}
+}
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -5496,6 +5496,8 @@
   bool ZeroInitialization(const Expr *E) {
     auto Offset = Info.Ctx.getTargetNullPointerValue(E->getType());
     Result.set((Expr*)nullptr, 0, false, true, Offset);
+    Result.getLValueDesignator() =
+        SubobjectDesignator(E->getType()->getPointeeType());
     return true;
   }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to