[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
Aleksei Sidorin via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Sun Apr 8 09:50:11 PDT 2018
a.sidorin created this revision.
a.sidorin added reviewers: NoQ, dcoughlin, xazax.hun.
Herald added subscribers: cfe-commits, rnkovacs, szepet.
Herald added a reviewer: george.karpenkov.
Despite the fact that cast expressions return rvalues, GCC still handles such outputs as lvalues when compiling inline assembler. Such code causes assertion failure in ExprEngine::VisitGCCAsmStmt. In this commit, we treat such rvalue outputs in the way similar to how CGStmt does it.
Repository:
rC Clang
https://reviews.llvm.org/D45416
Files:
lib/StaticAnalyzer/Core/ExprEngine.cpp
test/Analysis/asm.c
Index: test/Analysis/asm.c
===================================================================
--- /dev/null
+++ test/Analysis/asm.c
@@ -0,0 +1,10 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker debug.ExprInspection -fheinous-gnu-extensions -w %s -verify
+
+int clang_analyzer_eval(int);
+
+int global;
+void testRValueOutput() {
+ global = 1;
+ __asm__("" : "=r"((int)global)); // don't crash on rvalue output operand
+ clang_analyzer_eval(global == 1); // expected-warning{{UNKNOWN}}
+}
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -3071,9 +3071,25 @@
// outputs.
ProgramStateRef state = Pred->getState();
+ const auto *LCtx = Pred->getLocationContext();
for (const Expr *O : A->outputs()) {
- SVal X = state->getSVal(O, Pred->getLocationContext());
+ // NOTE: GCC inline asm supports rvalue no-op-like casts as output
+ // arguments (-fheinous-gnu-extensions).
+ const Expr *LValueOutputE = O->IgnoreParenNoopCasts(getContext());
+ SVal X = state->getSVal(LValueOutputE, LCtx);
+ if (X.isUnknown()) {
+ // The value being casted to rvalue can be garbage-collected after
+ // the cast is modeled. Try to recover the memory region being casted
+ // if possible.
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(LValueOutputE)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+ const VarRegion *VR =
+ getSValBuilder().getRegionManager().getVarRegion(VD, LCtx);
+ X = loc::MemRegionVal(VR);
+ }
+ }
+ }
assert(!X.getAs<NonLoc>()); // Should be an Lval, or unknown, undef.
if (Optional<Loc> LV = X.getAs<Loc>())
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D45416.141551.patch
Type: text/x-patch
Size: 1803 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180408/440645cd/attachment.bin>
More information about the cfe-commits
mailing list