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