This is an archive of the discontinued LLVM Phabricator instance.

[clang] Avoid an assertion in APValue::hasArrayFiller()
AbandonedPublic

Authored by tbaeder on Jun 21 2022, 1:04 AM.

Details

Summary

When calling hasArrayFiller() on a APValue that's not an array, the two functions called inside hasArrayFiller() would both run into their isArray() assertions.

This triggered for me with the included test case in ExprConstant.cpp:

if (!Result.hasArrayFiller())
  return Success;

adding a !Result.isArray() || there would also work of course but I think the version in this patch is safer.

Diff Detail

Event Timeline

tbaeder created this revision.Jun 21 2022, 1:04 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 21 2022, 1:04 AM
tbaeder requested review of this revision.Jun 21 2022, 1:04 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 21 2022, 1:04 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
tbaeder updated this revision to Diff 438612.Jun 21 2022, 2:50 AM

Failing tests are just because the test file is not formatted it seems.

aaron.ballman added inline comments.Jun 24 2022, 5:03 AM
clang/include/clang/AST/APValue.h
511–512 ↗(On Diff #438612)

I think this makes the interface somewhat self-inconsistent. hasLValuePath() asserts on isLValue(), and getArraySize() was providing a similar assertion (on isArray()) when called from hasArrayFiller().

I take that to mean that the expectation for this interface is that the caller validates the APValue in the cases where it doesn't already know the answer.

shafik added a subscriber: shafik.Jun 27 2022, 2:09 PM

Are you sure it is failing on the line you indicated? After looking at the code, a little before that line we have:

Result = APValue(APValue::UninitArray(), NumEltsToInit, NumElts);

which should assure that we have an array at this point. Looking at the result of the code prior to this they evaluate the check for Result.isArray() and so we should be consistent.

If you apply e.g.

@@ -10739,6 +10779,7 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E,
                           << NumEltsToInit << ".\n");

   Result = APValue(APValue::UninitArray(), NumEltsToInit, NumElts);
+  llvm::errs() << "Result " << &Result << ": " << Result.isArray() << "\n";

   // If the array was previously zero-initialized, preserve the
   // zero-initialized values.
@@ -10764,6 +10805,7 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E,
     }
   }

+  llvm::errs() << "Result " << &Result << ": " << Result.isArray() << "\n";
   if (!Result.hasArrayFiller())
     return Success;

and run the test case, the first added line prints 1 and the second one 0. Result is being mutated when doing the in-place evaluation.

I take that to mean that the expectation for this interface is that the caller validates the APValue in the cases where it doesn't already know the answer.

Sure, that was the other option.

and run the test case, the first added line prints 1 and the second one 0. Result is being mutated when doing the in-place evaluation.

I did not catch that. That is unfortunate, I am wondering now if we need a Result.isArray() && before the EvaluateInPlace in that loop.

shafik added inline comments.Jun 29 2022, 1:24 PM
clang/include/clang/AST/APValue.h
511–512 ↗(On Diff #438612)

I agree with Aaron here, the correct place to fix this is in VisitInitListExpr and check Result.isArray().

tbaeder updated this revision to Diff 441344.Jun 30 2022, 4:10 AM

I added the isArray() check in both places now, but the first one is not necessary for the test case (at least).

aaron.ballman accepted this revision.Jun 30 2022, 5:42 AM

Basically LGTM -- can you also add a release note about the assertion fix?

clang/test/SemaCXX/constexpr-array-init.cpp
2

Can remove spurious newline

16

Same here.

Also, I'd appreciate a FIXME comment about what this is testing (it's not obvious from the context) and that this code is expected to compile without a diagnostic in the future (so it's a bit more obviously correct when we do fix that).

This revision is now accepted and ready to land.Jun 30 2022, 5:42 AM
tbaeder updated this revision to Diff 441379.Jun 30 2022, 6:29 AM
shafik accepted this revision.Jun 30 2022, 9:11 AM

LGTM after addressing all of Aaron's comments.

tbaeder marked 2 inline comments as done.Jul 1 2022, 2:49 AM

LGTM after addressing all of Aaron's comments.

I've already addressed them; did you miss the update or are you saying I haven't addressed them properly?

tbaeder abandoned this revision.Aug 4 2022, 2:53 AM

Abandoning as per the discussion in https://discourse.llvm.org/t/apvalue-lifetime-problem-when-evaluating-constant-expressions/64002/5. This patch just hides a problem.