vabridgers created this revision. vabridgers added reviewers: NoQ, steakhal, martong. Herald added subscribers: manas, ASDenysPetrov, dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware, xazax.hun. Herald added a project: All. vabridgers requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
clang: <root>/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp:727: void assertEqualBitWidths(clang::ento::ProgramStateRef, clang::ento::Loc, clang::ento::Loc): Assertion `RhsBitwidth == LhsBitwidth && "RhsLoc and LhsLoc bitwidth must be same!"' This change adjusts the bitwidth of the smaller operand for an evalBinOp as a result of a comparison operation. This can occur in the specific case represented by the test cases for a target with different pointer sizes. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D122513 Files: clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp clang/test/Analysis/addrspace-null.c Index: clang/test/Analysis/addrspace-null.c =================================================================== --- /dev/null +++ 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; +} Index: clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -792,8 +792,27 @@ // If both operands are constants, just perform the operation. if (Optional<loc::ConcreteInt> rInt = rhs.getAs<loc::ConcreteInt>()) { - SVal ResultVal = - lhs.castAs<loc::ConcreteInt>().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<loc::ConcreteInt>().getValue(); + llvm::APSInt RHSValue = rhs.castAs<loc::ConcreteInt>().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<NonLoc> Result = ResultVal.getAs<NonLoc>()) return evalCast(*Result, resultTy, QualType{});
Index: clang/test/Analysis/addrspace-null.c =================================================================== --- /dev/null +++ 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; +} Index: clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -792,8 +792,27 @@ // If both operands are constants, just perform the operation. if (Optional<loc::ConcreteInt> rInt = rhs.getAs<loc::ConcreteInt>()) { - SVal ResultVal = - lhs.castAs<loc::ConcreteInt>().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<loc::ConcreteInt>().getValue(); + llvm::APSInt RHSValue = rhs.castAs<loc::ConcreteInt>().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<NonLoc> Result = ResultVal.getAs<NonLoc>()) return evalCast(*Result, resultTy, QualType{});
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits