[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