diff --git a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp --- a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -792,8 +792,27 @@ // If both operands are constants, just perform the operation. if (Optional rInt = rhs.getAs()) { - SVal ResultVal = - lhs.castAs().evalBinOp(BasicVals, op, *rInt); + // Need a big enough type to compare both values. + // + // In the case of something like this for targets with different + // pointer sizes based on address space, need to find the largest + // bitwidth to use for the evalBinOp + // + // int fn1() { + // int val = 0; + // __attribute__((address_space(3))) int *dptr = val; + // return dptr == (void *)0; + // } + llvm::APSInt LHSValue = lhs.castAs().getValue(); + llvm::APSInt RHSValue = rhs.castAs().getValue(); + APSIntType OpType = std::max(APSIntType(LHSValue), APSIntType(RHSValue)); + + OpType.apply(LHSValue); + OpType.apply(RHSValue); + loc::ConcreteInt ciLHS = loc::ConcreteInt(LHSValue); + loc::ConcreteInt ciRHS = loc::ConcreteInt(RHSValue); + SVal ResultVal = ciLHS.evalBinOp(BasicVals, op, ciRHS); + if (Optional Result = ResultVal.getAs()) return evalCast(*Result, resultTy, QualType{}); diff --git a/clang/test/Analysis/addrspace-null.c b/clang/test/Analysis/addrspace-null.c new file mode 100644 --- /dev/null +++ b/clang/test/Analysis/addrspace-null.c @@ -0,0 +1,47 @@ +// RUN: %clang_analyze_cc1 -triple amdgcn-unknown-unknown \ +// RUN: -analyze -analyzer-checker=core -DAMDGCN_TRIPLE \ +// RUN: -analyze -analyzer-checker=debug.ExprInspection \ +// RUN: -Wno-implicit-int -Wno-int-conversion -verify %s +// +// RUN: %clang_analyze_cc1 -triple amdgcn-unknown-unknown \ +// RUN: -analyze -analyzer-checker=core -DDEFAULT_TRIPLE \ +// RUN: -analyze -analyzer-checker=debug.ExprInspection \ +// RUN: -Wno-implicit-int -Wno-int-conversion -verify %s + +// From https://llvm.org/docs/AMDGPUUsage.html#address-spaces, +// select address space 3 (local), since the pointer size is +// different than Generic. + +// expected-no-diagnostics + +#define DEVICE __attribute__((address_space(3))) + +#if defined(AMDGCN) +// this crashes +int fn1() { + int val = 0; + DEVICE int *dptr = val; + return dptr == (void *)0; +} + +// does not crash +int fn2() { + int val = 0; + DEVICE int *dptr = val; + return dptr == (DEVICE void *)0; +} + +// this crashes +int fn3() { + int val = 0; + int *dptr = val; + return dptr == (DEVICE void *)0; +} +#endif + +// does not crash +int fn4() { + int val = 0; + int *dptr = val; + return dptr == (void *)0; +}