This is an archive of the discontinued LLVM Phabricator instance.

[analyzer] Do not assume that all pointers have the same bitwidth as void*
ClosedPublic

Authored by vabridgers on Jul 14 2021, 5:45 AM.

Details

Summary

This change addresses this assertion that occurs in a downstream
compiler with a custom target.

APInt.h:1151: bool llvm::APInt::operator==(const llvm::APInt &) const: Assertion `BitWidth == RHS.BitWidth && "Comparison requires equal bit widths"'

No covering test case is susbmitted with this change since this crash
cannot be reproduced using any upstream supported target. The test case
that exposes this issue is as simple as:

void test(int * p) {
  int * q = p-1;
  if (q) {}
  if (q) {} // crash
  (void)q;
}

The custom target that exposes this problem supports two address spaces,
16-bit chars, and a _Bool type that maps to 16-bits. There are no upstream
supported targets with similar attributes.

The assertion appears to be happening as a result of evaluating the
SymIntExpr (reg_$0<int * p>) != 0U in VisitSymIntExpr located in
SimpleSValBuilder.cpp. The LHS is evaluated to 32b and the RHS is
evaluated to 16b. This eventually leads to the assertion in APInt.h.

While this change addresses the crash and passes LITs, two follow-ups
are required:

  1. The remainder of getZeroWithPtrWidth() and getIntWithPtrWidth() should be cleaned up following this model to prevent future confusion.
  2. We're not sure why references are found along with the modified code path, that should not be the case. A more principled fix may be found after some further comprehension of why this is the case.

Acks: Thanks to @steakhal and @martong for the discussions leading to this
fix.

Diff Detail

Event Timeline

vabridgers created this revision.Jul 14 2021, 5:45 AM
vabridgers requested review of this revision.Jul 14 2021, 5:45 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 14 2021, 5:45 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript

update commit header

steakhal retitled this revision from [analyzer] Fix assertion in state split code path to [analyzer] Do not assume that all pointers have the same bitwidth as void*.Jul 14 2021, 7:36 AM
steakhal edited the summary of this revision. (Show Details)
steakhal added reviewers: NoQ, vsavchenko, ASDenysPetrov.
bjope added a subscriber: bjope.Jul 14 2021, 9:32 AM

I think you can create an upstream test case by looking at clang/test/Analysis/ptr.cl.
It uses amdgcn and address space 256, which seems to have a different pointer size compared to address space zero for that specific target.

So the test case (named with a .cl extension) would look like this (I don't think you really need to specify verde as target cpu):

// RUN: %clang_analyze_cc1 -triple amdgcn-unknown-unknown -target-cpu verde -analyze -analyzer-checker=core %s

void test(__attribute__((address_space(256))) int * p) {
  __attribute__((address_space(256))) int * q = p-1;
  if (q) {}
  if (q) {} // crash
  (void)q;
}
NoQ added a comment.Jul 14 2021, 9:53 AM

I think this is a plausible use case, previously I thought it's too much work but it seems reasonable last time I looked into it, so I'm glad to see it going on!

Can you add a comment explaining that the new code is necessary for architectures with varying pointer bit width? That's often unobvious.

clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
718

I guess something like this?

void foo(int &x) {
  int *p = &x; // 'p' is the same SVal as 'x'
  bool b = p;
}

I think we should return a concrete true in the reference case. We already know that such symbol is true-ish but returning a concrete true might be easier on the solver.

Thanks all for the updates and comments. I'll address promptly and resubmit. Best!

address comments, add test case suggested by @bjope

Thanks for the updates, comments and the reproducer. I've added those in this update. If possible, I'd like to get this change accepted to avoid the crash we currently see, and I'll immediately follow up with the FIXMEs. Otherwise, I'll iterate quickly on the FIXMEs. - Vince

clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
718

I think this comment is addressed by changing the comment, and deferring a subsequent follow up. I'd like to get this change submitted to at least avoid the crash if possible? Otherwise, if needed, I'll iterate quickly on trying to return a concrete 'true' for the reference case.

update test case

NoQ accepted this revision.Jul 15 2021, 8:36 PM

Looks great, thanks!

clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
718

Yes, it's absolutely fine to investigate this separately :)

This revision is now accepted and ready to land.Jul 15 2021, 8:36 PM