diff options
author | Mikhail R. Gadelha <mikhail.ramalho@gmail.com> | 2018-07-26 11:17:13 +0000 |
---|---|---|
committer | Mikhail R. Gadelha <mikhail.ramalho@gmail.com> | 2018-07-26 11:17:13 +0000 |
commit | 127093129aa049f05594c80f7f4ae09187bb94a8 (patch) | |
tree | a14a1ca19898b2bd4522b0a86809c88e2468fb27 /clang/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp | |
parent | 4a612d4bf290346ec018a74fd245c8e30ff93de7 (diff) | |
download | bcm5719-llvm-127093129aa049f05594c80f7f4ae09187bb94a8.tar.gz bcm5719-llvm-127093129aa049f05594c80f7f4ae09187bb94a8.zip |
[analyzer] Fixed method to get APSInt model
Summary:
This patch replaces the current method of getting an `APSInt` from Z3's model by calling generic API method `getBitvector` instead of `Z3_get_numeral_uint64`.
By calling `getBitvector`, there's no need to handle bitvectors with bit width == 128 separately.
And, as a bonus, clang now compiles correctly with Z3 4.7.1.
Reviewers: NoQ, george.karpenkov
Reviewed By: george.karpenkov
Subscribers: xazax.hun, szepet, a.sidorin
Differential Revision: https://reviews.llvm.org/D49818
llvm-svn: 338020
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp | 41 |
1 files changed, 18 insertions, 23 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp index 4613ae76141..7379ded49c8 100644 --- a/clang/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp @@ -734,10 +734,11 @@ public: toZ3Sort(*Sort).Sort))); } - const llvm::APSInt getBitvector(const SMTExprRef &Exp) override { - // FIXME: this returns a string and the bitWidth is overridden - return llvm::APSInt( - Z3_get_numeral_string(Context.Context, toZ3Expr(*Exp).AST)); + llvm::APSInt getBitvector(const SMTExprRef &Exp, unsigned BitWidth, + bool isUnsigned) override { + return llvm::APSInt(llvm::APInt( + BitWidth, Z3_get_numeral_string(Context.Context, toZ3Expr(*Exp).AST), + 10)); } bool getBoolean(const SMTExprRef &Exp) override { @@ -814,26 +815,20 @@ public: return false; } - uint64_t Value[2]; - // Force cast because Z3 defines __uint64 to be a unsigned long long - // type, which isn't compatible with a unsigned long type, even if they - // are the same size. - Z3_get_numeral_uint64(Context.Context, toZ3Expr(*AST).AST, - reinterpret_cast<__uint64 *>(&Value[0])); - if (Sort->getBitvectorSortSize() <= 64) { - Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value[0]), - Int.isUnsigned()); - } else if (Sort->getBitvectorSortSize() == 128) { - SMTExprRef ASTHigh = mkBVExtract(127, 64, AST); - Z3_get_numeral_uint64(Context.Context, toZ3Expr(*AST).AST, - reinterpret_cast<__uint64 *>(&Value[1])); - Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value), - Int.isUnsigned()); - } else { - assert(false && "Bitwidth not supported!"); - return false; + // FIXME: This function is also used to retrieve floating-point values, + // which can be 16, 32, 64 or 128 bits long. Bitvectors can be anything + // between 1 and 64 bits long, which is the reason we have this weird + // guard. In the future, we need proper calls in the backend to retrieve + // floating-points and its special values (NaN, +/-infinity, +/-zero), + // then we can drop this weird condition. + if (Sort->getBitvectorSortSize() <= 64 || + Sort->getBitvectorSortSize() == 128) { + Int = getBitvector(AST, Int.getBitWidth(), Int.isUnsigned()); + return true; } - return true; + + assert(false && "Bitwidth not supported!"); + return false; } if (Sort->isBooleanSort()) { |