C++ PATCH for c++/91264 - detect modifying const objects in constexpr

Jason Merrill jason@redhat.com
Mon Aug 5 20:37:00 GMT 2019


On 7/31/19 3:26 PM, Marek Polacek wrote:
> One of the features of constexpr is that it doesn't allow UB; and such UB must
> be detected at compile-time.  So running your code in a context that requires
> a constant expression should ensure that the code in question is free of UB.
> In effect, constexpr can serve as a sanitizer.  E.g. this article describes in
> in more detail:
> <https://shafik.github.io/c++/undefined%20behavior/2019/05/11/explporing_undefined_behavior_using_constexpr.html>
> 
> [dcl.type.cv]p4 says "Any attempt to modify a const object during its lifetime
> results in undefined behavior." However, as the article above points out, we
> aren't detecting that case in constexpr evaluation.
> 
> This patch fixes that.  It's not that easy, though, because we have to keep in
> mind [class.ctor]p5:
> "A constructor can be invoked for a const, volatile or const volatile object.
> const and volatile semantics are not applied on an object under construction.
> They come into effect when the constructor for the most derived object ends."
> 
> I handled this by keeping a hash set which tracks objects under construction.
> I considered other options, such as going up call_stack, but that wouldn't
> work with trivial constructor/op=.  It was also interesting to find out that
> the definition of TREE_HAS_CONSTRUCTOR says "When appearing in a FIELD_DECL,
> it means that this field has been duly initialized in its constructor" though
> nowhere in the codebase do we set TREE_HAS_CONSTRUCTOR on a FIELD_DECL as far
> as I can see.  Unfortunately, using this bit proved useless for my needs here.

> Also, be mindful of mutable subobjects.
> 
> Does this approach look like an appropriate strategy for tracking objects'
> construction?

For scalar objects, we should be able to rely on INIT_EXPR vs. 
MODIFY_EXPR to distinguish between initialization and modification; for 
class objects, I wonder about setting a flag on the CONSTRUCTOR after 
initialization is complete to indicate that the value is now constant.

Jason



More information about the Gcc-patches mailing list