[PATCH] D42776: [Sema] Fix an assertion failure in constant expression evaluation of calls to functions with default arguments

Richard Smith - zygoloid via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 22 13:27:32 PST 2018


rsmith added a comment.

Thank you, this looks like a great direction.

As noted, there are a bunch of other cases that we should cover with this approach. I'm really happy about the number of related bugs we get to fix with this change.



================
Comment at: lib/AST/ExprConstant.cpp:3186-3187
   // object under construction.
-  if (Info.isEvaluatingConstructor(LVal.getLValueBase(), LVal.CallIndex)) {
+  if (Info.isEvaluatingConstructor(LVal.getLValueBase(),
+                                   LVal.getLValueCallIndex())) {
     BaseType = Info.Ctx.getCanonicalType(BaseType);
----------------
This should take the version into account.


================
Comment at: lib/AST/ExprConstant.cpp:5236
     if (Frame) {
-      Result.set(VD, Frame->Index);
+      Result.set({VD, Frame->Index});
       return true;
----------------
Hmm. We should be versioning local variables as well. Currently we'll accept invalid code such as:

```
constexpr int f() {
  int *p = nullptr;
  for (int k = 0; k != 2; ++k) {
    int local_var = 0;
    if (k == 0)
      p = &local_var;
    else
      return *p;
  }
}
static_assert(f() == 0);
```


================
Comment at: lib/AST/ExprConstant.cpp:5275-5278
+    unsigned Version = Info.CurrentCall->getMTEVersion();
     Value = &Info.CurrentCall->
-        createTemporary(E, E->getStorageDuration() == SD_Automatic);
-    Result.set(E, Info.CurrentCall->Index);
+        createTemporary(E, E->getStorageDuration() == SD_Automatic, Version);
+    Result.set({E, Info.CurrentCall->Index, Version});
----------------
Can you combine these, so we have a single function to create a temporary and produce both an `LValue` denoting it and an `APValue*` to hold its evaluated value?


================
Comment at: lib/AST/ExprConstant.cpp:5772
     } else {
-      Result.set(SubExpr, Info.CurrentCall->Index);
+      Result.set({SubExpr, Info.CurrentCall->Index});
       if (!EvaluateInPlace(Info.CurrentCall->createTemporary(SubExpr, false),
----------------
This should create a versioned temporary object.


================
Comment at: lib/AST/ExprConstant.cpp:6540
   bool VisitConstructExpr(const Expr *E) {
-    Result.set(E, Info.CurrentCall->Index);
+    Result.set({E, Info.CurrentCall->Index});
     return EvaluateInPlace(Info.CurrentCall->createTemporary(E, false),
----------------
This should create a versioned temporary object.


================
Comment at: lib/AST/ExprConstant.cpp:8031
+         (A.getLValueCallIndex() == B.getLValueCallIndex() &&
+          A.getLValueVersion() == B.getLValueVersion());
 }
----------------
You already checked this above. It'd make sense to check the call index and version in the same place here, but we should only need one check for each :)


================
Comment at: lib/AST/ExprConstant.cpp:9974-9997
+    LV.set({E, Info.CurrentCall->Index});
     APValue &Value = Info.CurrentCall->createTemporary(E, false);
     if (!EvaluateArray(E, LV, Value, Info))
       return false;
     Result = Value;
   } else if (T->isRecordType()) {
     LValue LV;
----------------
These temporaries should all be versioned.


https://reviews.llvm.org/D42776





More information about the cfe-commits mailing list