[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
rsmith added inline comments. Comment at: test/Analysis/asm.cpp:9 + ref = 1; + __asm__("" : "=r"((int)global)); // don't crash on rvalue output operand + clang_analyzer_eval(global == 1); // expected-warning{{UNKNOWN}} Ugh, do we really need to support this nonsense? :( If so, it'd seem reasonable to me to do the cleanup when building the AST rather than in the CFG builder (that is, convert the LValueToRValue cast here to a NoOp lvalue cast node, since that matches its actual semantics). Repository: rC Clang https://reviews.llvm.org/D45416 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
NoQ accepted this revision. NoQ added a subscriber: rsmith. NoQ added a comment. Woohoo LGTM. Heads up to @rsmith because we're about to break the CFG again, and also yay we've found another use case for rewriting AST in our CFG. Repository: rC Clang https://reviews.llvm.org/D45416 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
a.sidorin updated this revision to Diff 143959. a.sidorin added a comment. Add a test for CFG dump; replace static_cast with an initialization. No test failures on check-all were observed. Repository: rC Clang https://reviews.llvm.org/D45416 Files: include/clang/Analysis/CFG.h lib/Analysis/CFG.cpp lib/StaticAnalyzer/Core/ExprEngine.cpp test/Analysis/asm.cpp test/Analysis/cfg.cpp Index: test/Analysis/cfg.cpp === --- test/Analysis/cfg.cpp +++ test/Analysis/cfg.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -analyzer-config cfg-temporary-dtors=true -std=c++11 -analyzer-config cfg-rich-constructors=false %s > %t 2>&1 +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -fheinous-gnu-extensions -analyzer-config cfg-temporary-dtors=true -std=c++11 -analyzer-config cfg-rich-constructors=false %s > %t 2>&1 // RUN: FileCheck --input-file=%t -check-prefixes=CHECK,WARNINGS %s -// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -analyzer-config cfg-temporary-dtors=true -std=c++11 -analyzer-config cfg-rich-constructors=true %s > %t 2>&1 +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -fheinous-gnu-extensions -analyzer-config cfg-temporary-dtors=true -std=c++11 -analyzer-config cfg-rich-constructors=true %s > %t 2>&1 // RUN: FileCheck --input-file=%t -check-prefixes=CHECK,ANALYZER %s // This file tests how we construct two different flavors of the Clang CFG - @@ -84,6 +84,23 @@ static_assert(1, "abc"); } + +// CHECK-LABEL: void checkGCCAsmRValueOutput() +// CHECK: [B2 (ENTRY)] +// CHECK-NEXT: Succs (1): B1 +// CHECK: [B1] +// CHECK-NEXT: 1: int arg +// CHECK-NEXT: 2: arg +// CHECK-NEXT: 3: asm ("" : "=r" ([B1.2])); +// CHECK-NEXT: 4: arg +// CHECK-NEXT: 5: asm ("" : "=r" ([B1.4])); +void checkGCCAsmRValueOutput() { + int arg; + __asm__("" : "=r"((int)arg)); // rvalue output operand + __asm__("" : "=r"(arg)); // lvalue output operand +} + + // CHECK-LABEL: void F(EmptyE e) // CHECK: ENTRY // CHECK-NEXT: Succs (1): B1 Index: test/Analysis/asm.cpp === --- /dev/null +++ test/Analysis/asm.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker debug.ExprInspection -fheinous-gnu-extensions -w %s -verify + +int clang_analyzer_eval(int); + +int global; +void testRValueOutput() { + int = global; + ref = 1; + __asm__("" : "=r"((int)global)); // don't crash on rvalue output operand + clang_analyzer_eval(global == 1); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(ref == 1);// expected-warning{{UNKNOWN}} +} Index: lib/StaticAnalyzer/Core/ExprEngine.cpp === --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -3058,13 +3058,14 @@ // outputs. ProgramStateRef state = Pred->getState(); + const auto *LCtx = Pred->getLocationContext(); for (const Expr *O : A->outputs()) { -SVal X = state->getSVal(O, Pred->getLocationContext()); +SVal X = state->getSVal(O, LCtx); assert(!X.getAs()); // Should be an Lval, or unknown, undef. if (Optional LV = X.getAs()) - state = state->bindLoc(*LV, UnknownVal(), Pred->getLocationContext()); + state = state->bindLoc(*LV, UnknownVal(), LCtx); } Bldr.generateNode(A, Pred, state); Index: lib/Analysis/CFG.cpp === --- lib/Analysis/CFG.cpp +++ lib/Analysis/CFG.cpp @@ -548,6 +548,7 @@ CFGBlock *VisitDoStmt(DoStmt *D); CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E, AddStmtChoice asc); CFGBlock *VisitForStmt(ForStmt *F); + CFGBlock *VisitGCCAsmStmt(GCCAsmStmt *GCCAsmS, AddStmtChoice asc); CFGBlock *VisitGotoStmt(GotoStmt *G); CFGBlock *VisitIfStmt(IfStmt *I); CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc); @@ -587,6 +588,16 @@ CFGBlock *VisitChildren(Stmt *S); CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc); + GCCAsmStmt *getOrCreateGCCAsmStmtWithoutGnuExtensions(GCCAsmStmt *GCCAsmS); + + template void *allocateMemForStmt() { +// Get the alignment of the new Stmt, padding out to >=8 bytes. +unsigned Align = std::max(alignof(StmtTy), size_t{8}); +// Allocate a new Stmt using the BumpPtrAllocator. It will get +// automatically freed with the CFG. +return cfg->getAllocator().Allocate(sizeof(StmtTy), Align); + } + void maybeAddScopeBeginForVarDecl(CFGBlock *B, const VarDecl *VD, const Stmt *S) { if (ScopePos && (VD == ScopePos.getFirstVarInScope())) @@ -2039,6 +2050,9 @@ case Stmt::ForStmtClass: return VisitForStmt(cast(S)); +case Stmt::GCCAsmStmtClass: + return
[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
NoQ added a comment. (also we'll need CFG dump tests) Repository: rC Clang https://reviews.llvm.org/D45416 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
NoQ added a comment. (i'd much rather do the latter) Repository: rC Clang https://reviews.llvm.org/D45416 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
NoQ accepted this revision. NoQ added a comment. Wow, you actually did that. Ok, now we can decide if we want this to be analyzer-only (with a `CFG::BuildOptions` flag) or get someone else to have a look at that as a global CFG change (i.e. it may potentially affect compiler warnings). Or at least make sure to run all clang tests :) Repository: rC Clang https://reviews.llvm.org/D45416 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
a.sidorin updated this revision to Diff 142226. a.sidorin added a comment. Rewrite the GCCAsmStmt in the CFG. Repository: rC Clang https://reviews.llvm.org/D45416 Files: include/clang/Analysis/CFG.h lib/Analysis/CFG.cpp lib/StaticAnalyzer/Core/ExprEngine.cpp test/Analysis/asm.cpp Index: test/Analysis/asm.cpp === --- /dev/null +++ test/Analysis/asm.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker debug.ExprInspection -fheinous-gnu-extensions -w %s -verify + +int clang_analyzer_eval(int); + +int global; +void testRValueOutput() { + int = global; + ref = 1; + __asm__("" : "=r"((int)global)); // don't crash on rvalue output operand + clang_analyzer_eval(global == 1); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(ref == 1);// expected-warning{{UNKNOWN}} +} Index: lib/StaticAnalyzer/Core/ExprEngine.cpp === --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -3071,13 +3071,14 @@ // outputs. ProgramStateRef state = Pred->getState(); + const auto *LCtx = Pred->getLocationContext(); for (const Expr *O : A->outputs()) { -SVal X = state->getSVal(O, Pred->getLocationContext()); +SVal X = state->getSVal(O, LCtx); assert(!X.getAs()); // Should be an Lval, or unknown, undef. if (Optional LV = X.getAs()) - state = state->bindLoc(*LV, UnknownVal(), Pred->getLocationContext()); + state = state->bindLoc(*LV, UnknownVal(), LCtx); } Bldr.generateNode(A, Pred, state); Index: lib/Analysis/CFG.cpp === --- lib/Analysis/CFG.cpp +++ lib/Analysis/CFG.cpp @@ -548,6 +548,7 @@ CFGBlock *VisitDoStmt(DoStmt *D); CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E, AddStmtChoice asc); CFGBlock *VisitForStmt(ForStmt *F); + CFGBlock *VisitGCCAsmStmt(GCCAsmStmt *GCCAsmS, AddStmtChoice asc); CFGBlock *VisitGotoStmt(GotoStmt *G); CFGBlock *VisitIfStmt(IfStmt *I); CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc); @@ -587,6 +588,16 @@ CFGBlock *VisitChildren(Stmt *S); CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc); + GCCAsmStmt *getOrCreateGCCAsmStmtWithoutGnuExtensions(GCCAsmStmt *GCCAsmS); + + template void *allocateMemForStmt() { +// Get the alignment of the new Stmt, padding out to >=8 bytes. +unsigned Align = std::max(alignof(StmtTy), static_cast(8)); +// Allocate a new Stmt using the BumpPtrAllocator. It will get +// automatically freed with the CFG. +return cfg->getAllocator().Allocate(sizeof(StmtTy), Align); + } + void maybeAddScopeBeginForVarDecl(CFGBlock *B, const VarDecl *VD, const Stmt *S) { if (ScopePos && (VD == ScopePos.getFirstVarInScope())) @@ -2039,6 +2050,9 @@ case Stmt::ForStmtClass: return VisitForStmt(cast(S)); +case Stmt::GCCAsmStmtClass: + return VisitGCCAsmStmt(cast(S), asc); + case Stmt::GotoStmtClass: return VisitGotoStmt(cast(S)); @@ -2571,14 +2585,9 @@ for (DeclStmt::reverse_decl_iterator I = DS->decl_rbegin(), E = DS->decl_rend(); I != E; ++I) { -// Get the alignment of the new DeclStmt, padding out to >=8 bytes. -unsigned A = alignof(DeclStmt) < 8 ? 8 : alignof(DeclStmt); - -// Allocate the DeclStmt using the BumpPtrAllocator. It will get -// automatically freed with the CFG. DeclGroupRef DG(*I); Decl *D = *I; -void *Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A); +void *Mem = allocateMemForStmt(); DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D)); cfg->addSyntheticDeclStmt(DSNew, DS); @@ -3009,7 +3018,58 @@ } return LastBlock; } - + +GCCAsmStmt * +CFGBuilder::getOrCreateGCCAsmStmtWithoutGnuExtensions(GCCAsmStmt *S) { + // GCC asm syntax allows using no-op-like casts as outputs. While GCC treats + // them as lvalues, clang builds an LValueToRValue cast. + // We are going to re-create the GCCAsmStmt if this happens. + if (std::find_if(S->begin_outputs(), S->end_outputs(), [this](const Expr *E) { +return E != E->IgnoreParenNoopCasts(*Context); + }) == S->end_outputs()) +return S; + + SmallVector Names; + for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) +Names.push_back(S->getOutputIdentifier(I)); + + for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) +Names.push_back(S->getInputIdentifier(I)); + + SmallVector Clobbers; + for (unsigned I = 0, E = S->getNumClobbers(); I != E; I++) +Clobbers.push_back(S->getClobberStringLiteral(I)); + + SmallVector Constraints; + for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) +Constraints.push_back(S->getOutputConstraintLiteral(I)); + + for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) +
[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
NoQ added a comment. I mean, like, if we try to work with the existing AST then we're stuck with a prvalue expression that represents an lvalue and will be assigned a `Loc` value, which is pretty weird anyway. Getting rid of the ParentMap in favor of providing enough context (eg. in the CFG or in checker callbacks) whenever we might want to use it sounds like a much saner solution. There might be other "unknown unknowns" about rewriting the AST, but our current problem looks as safe as we'll ever get. Repository: rC Clang https://reviews.llvm.org/D45416 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
NoQ added a comment. In https://reviews.llvm.org/D45416#1062901, @a.sidorin wrote: > > The ultimate solution would probably be to add a fake cloned asm statement > > to the CFG (instead of the real asm statement) that would point to the > > correct output child-expression(s) that are untouched themselves but simply > > have their noop casts removed. > > I have some concerns about this solution. It will result in difference > between AST nodes and nodes that user will receive during analysis and I'm > not sure that it is good. What is even worse here is that a lot of AST stuff > won't work properly - ParentMap, for example. Yep. But i'd rather avoid using the `ParentMap`. Also we already do this for `DeclStmt`s that declare more than one `VarDecl` (split them up into single-decl statements), and the practical effect of such simplification is barely noticeable even though `DeclStmt`s are so much more common. >> Or we could try > > Looks like something is missed here :) Whoops sry nvm. And and and mmm you didn't include the diff context :p In https://reviews.llvm.org/D45416#1063366, @a.sidorin wrote: > Maybe we should just remove the condition and leave a FIXME? The fix is already there and it's valid and it makes things better overall, why not keep it around. We still need a FIXME though. Repository: rC Clang https://reviews.llvm.org/D45416 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
a.sidorin added a comment. Maybe we should just remove the condition and leave a FIXME? Repository: rC Clang https://reviews.llvm.org/D45416 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
a.sidorin added a comment. > The ultimate solution would probably be to add a fake cloned asm statement to > the CFG (instead of the real asm statement) that would point to the correct > output child-expression(s) that are untouched themselves but simply have > their noop casts removed. I have some concerns about this solution. It will result in difference between AST nodes and nodes that user will receive during analysis and I'm not sure that it is good. What is even worse here is that a lot of AST stuff won't work properly - ParentMap, for example. > Or we could try Looks like something is missed here :) Repository: rC Clang https://reviews.llvm.org/D45416 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
NoQ accepted this revision. NoQ added a comment. Thanks! Eww. Weird AST. I wonder how this should work: // RUN: %clang_analyze_cc1 -analyzer-checker debug.ExprInspection -fheinous-gnu-extensions -w %s -verify int clang_analyzer_eval(int); int global; void testRValueOutput() { int = global; ref = 1; __asm__("" : "=r"((int)ref)); clang_analyzer_eval(ref == 1); // currently says UNKNOWN clang_analyzer_eval(global == 1); // currently says TRUE } The ultimate solution would probably be to add a fake cloned asm statement to the CFG (instead of the real asm statement) that would point to the correct output child-expression(s) that are untouched themselves but simply have their noop casts removed. Or we could try Repository: rC Clang https://reviews.llvm.org/D45416 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
george.karpenkov accepted this revision. george.karpenkov added a comment. This revision is now accepted and ready to land. Right, sorry. LGTM, but maybe Artem has something to add as well. I don't have any suggestions, and trying to modifying lifetimes of expressions in environment for the sake of a GCC extensions seems suboptimal as well. Repository: rC Clang https://reviews.llvm.org/D45416 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
a.sidorin added inline comments. Comment at: lib/StaticAnalyzer/Core/ExprEngine.cpp:3082 +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 george.karpenkov wrote: > From my understanding, the code inside the if-block is not tested below > It is tested: without this code, "TRUE" will be printed. The reason is that the lvalue of 'global' is removed from Environment after the cast happens so `X` becomes Unknown. But the way of retrieving the value is definitely not the best so if you have any suggestions on improvement - they are welcome. Repository: rC Clang https://reviews.llvm.org/D45416 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
george.karpenkov requested changes to this revision. george.karpenkov added inline comments. This revision now requires changes to proceed. Comment at: lib/StaticAnalyzer/Core/ExprEngine.cpp:3082 +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 From my understanding, the code inside the if-block is not tested below Repository: rC Clang https://reviews.llvm.org/D45416 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D45416: [analyzer] ExprEngine: model GCC inline asm rvalue cast outputs
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(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}} +} 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()) ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits