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(LValueOutputE)) { + if (const auto *VD = dyn_cast(DRE->getDecl())) { + const VarRegion *VR = + getSValBuilder().getRegionManager().getVarRegion(VD, LCtx); + X = loc::MemRegionVal(VR); + } + } + } assert(!X.getAs()); // Should be an Lval, or unknown, undef. if (Optional LV = X.getAs()) 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}} +}