Skip to content

Commit

Permalink
[analyzer][solver] Handle UnarySymExpr in SMTConv
Browse files Browse the repository at this point in the history
Dependent patch adds UnarySymExpr, now I'd like to handle that for SMT
conversions like refutation.

Differential Revision: https://reviews.llvm.org/D125547
  • Loading branch information
Gabor Marton committed May 26, 2022
1 parent 88abc50 commit cd5783d
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 0 deletions.
22 changes: 22 additions & 0 deletions clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h
Expand Up @@ -446,6 +446,28 @@ class SMTConv {
return getCastExpr(Solver, Ctx, Exp, FromTy, Sym->getType());
}

if (const UnarySymExpr *USE = dyn_cast<UnarySymExpr>(Sym)) {
if (RetTy)
*RetTy = Sym->getType();

QualType OperandTy;
llvm::SMTExprRef OperandExp =
getSymExpr(Solver, Ctx, USE->getOperand(), &OperandTy, hasComparison);
llvm::SMTExprRef UnaryExp =
fromUnOp(Solver, USE->getOpcode(), OperandExp);

// Currently, without the `support-symbolic-integer-casts=true` option,
// we do not emit `SymbolCast`s for implicit casts.
// One such implicit cast is missing if the operand of the unary operator
// has a different type than the unary itself.
if (Ctx.getTypeSize(OperandTy) != Ctx.getTypeSize(Sym->getType())) {
if (hasComparison)
*hasComparison = false;
return getCastExpr(Solver, Ctx, UnaryExp, OperandTy, Sym->getType());
}
return UnaryExp;
}

if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
llvm::SMTExprRef Exp =
getSymBinExpr(Solver, Ctx, BSE, hasComparison, RetTy);
Expand Down
33 changes: 33 additions & 0 deletions clang/test/Analysis/unary-sym-expr-z3-refutation.c
@@ -0,0 +1,33 @@
// RUN: %clang_analyze_cc1 %s \
// RUN: -analyzer-checker=core,debug.ExprInspection \
// RUN: -analyzer-config eagerly-assume=true \
// RUN: -verify

// RUN: %clang_analyze_cc1 %s \
// RUN: -analyzer-checker=core,debug.ExprInspection \
// RUN: -analyzer-config eagerly-assume=true \
// RUN: -analyzer-config support-symbolic-integer-casts=true \
// RUN: -verify

// RUN: %clang_analyze_cc1 %s \
// RUN: -analyzer-checker=core,debug.ExprInspection \
// RUN: -analyzer-config eagerly-assume=true \
// RUN: -analyzer-config crosscheck-with-z3=true \
// RUN: -verify

// RUN: %clang_analyze_cc1 %s \
// RUN: -analyzer-checker=core,debug.ExprInspection \
// RUN: -analyzer-config eagerly-assume=true \
// RUN: -analyzer-config crosscheck-with-z3=true \
// RUN: -analyzer-config support-symbolic-integer-casts=true \
// RUN: -verify

// REQUIRES: z3

void k(long L) {
int g = L;
int h = g + 1;
int j;
j += -h < 0; // should not crash
// expected-warning@-1{{garbage}}
}
14 changes: 14 additions & 0 deletions clang/test/Analysis/z3-crosscheck.c
Expand Up @@ -14,6 +14,20 @@ int foo(int x)
return 0;
}

int unary(int x, long l)
{
int *z = 0;
int y = l;
if ((x & 1) && ((x & 1) ^ 1))
if (-y)
#ifdef NO_CROSSCHECK
return *z; // expected-warning {{Dereference of null pointer (loaded from variable 'z')}}
#else
return *z; // no-warning
#endif
return 0;
}

void g(int d);

void f(int *a, int *b) {
Expand Down

0 comments on commit cd5783d

Please sign in to comment.