This is an archive of the discontinued LLVM Phabricator instance.

[ExprConstant] Allow constexpr ctor to modify non static data members in body
ClosedPublic

Authored by erik.pilkington on Oct 2 2017, 4:41 PM.

Details

Summary

Previously, clang rejected the following (copied from PR19741):

struct A {
  int a = 0;
  constexpr A() { a = 1; }
};
constexpr bool f() {
  constexpr A a;
  static_assert(a.a == 1, "");
  return a.a == 1;
}
static_assert(f(), "");

Clang didn't like the assignment to a in A() because it doesn't know that A is being constructed and therefore considers the subobject A.a to be const. The fix in this patch (which @rsmith suggested in the PR) is just to keep track of the set of objects that are currently being constructed, and strip away the const whenever we encounter a subobject of an object under construction.

https://bugs.llvm.org/show_bug.cgi?id=19741

Thanks for taking a look!
Erik

Diff Detail

Repository
rL LLVM

Event Timeline

erik.pilkington created this revision.Oct 2 2017, 4:41 PM
rsmith added inline comments.Oct 2 2017, 5:03 PM
lib/AST/ExprConstant.cpp
576 ↗(On Diff #117445)

Please add a comment explaining what the two fields mean.

588 ↗(On Diff #117445)

Can the DidInsert == false case actually happen?

596 ↗(On Diff #117445)

Hmm, should we check the CallIndex is 0 in this case? I think we technically don't need to, but only because we happen to only evaluate the initializer of local variables before the enclosing function has its body attached.

Perhaps we could insert EvaluatingDecl into the EvaluatingConstructors list and simplify this check to just the DenseSet lookup?

erik.pilkington marked 2 inline comments as done.

Thanks for the feedback, in this new patch:

  • insert EvaluatingDecl into EvaluatingConstructors instead of checking it in isEvaluatingDecl()
  • Add a comment to the typedef
lib/AST/ExprConstant.cpp
588 ↗(On Diff #117445)

Yep, if you have the following:

struct Outer {
  struct Inner {
    constexpr Inner() {}
  };
  Inner i;
  constexpr Outer() {}
};
constexpr Outer o;

There are two ctor calls for the LValueBase constexpr Outer o; at call index 0.

rsmith accepted this revision.Oct 3 2017, 2:45 PM

LGTM, thank you!

lib/AST/ExprConstant.cpp
3127 ↗(On Diff #117529)

The first half of this FIXME is now fixed, and should be removed. (But the second half -- const subobjects remain mutable past the end of their period of construction -- is still an open problem.)

This revision is now accepted and ready to land.Oct 3 2017, 2:45 PM
This revision was automatically updated to reflect the committed changes.