From d104a09d30ec35cb67931051d5d0c1ff2ee2d697 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Wed, 4 Mar 2009 22:56:43 +0000 Subject: [PATCH] Add prototype support for invalidating fields for structures passed-by-reference to unknown functions. Most of this logic should be eventually moved to RegionStore and be made lazy. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66094 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/CFRefCount.cpp | 89 ++++++++++++++++++++++------ test/Analysis/misc-ps-region-store.m | 25 ++++++++ 2 files changed, 96 insertions(+), 18 deletions(-) diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 5e1857168d..7e6507cbe5 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -1650,28 +1650,81 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, R = dyn_cast(ATR->getSuperRegion()); } - if (R && R->isBoundable(Ctx)) { + if (R) { // Is the invalidated variable something that we were tracking? SymbolRef Sym = state.GetSValAsScalarOrLoc(R).getAsLocSymbol(); - if (Sym.isValid()) - state = state.remove(Sym); - // Set the value of the variable to be a conjured symbol. - unsigned Count = Builder.getCurrentBlockCount(); - QualType T = R->getRValueType(Ctx); + // Remove any existing reference-count binding. + if (Sym.isValid()) state = state.remove(Sym); - // FIXME: handle structs. - if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) { - SymbolRef NewSym = - Eng.getSymbolManager().getConjuredSymbol(*I, T, Count); - - state = state.BindLoc(Loc::MakeVal(R), - Loc::IsLocType(T) - ? cast(loc::SymbolVal(NewSym)) - : cast(nonloc::SymbolVal(NewSym))); - } - else { - state = state.BindLoc(*MR, UnknownVal()); + if (R->isBoundable(Ctx)) { + // Set the value of the variable to be a conjured symbol. + unsigned Count = Builder.getCurrentBlockCount(); + QualType T = R->getRValueType(Ctx); + + if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) { + SymbolRef NewSym = + Eng.getSymbolManager().getConjuredSymbol(*I, T, Count); + + state = state.BindLoc(Loc::MakeVal(R), + Loc::IsLocType(T) + ? cast(loc::SymbolVal(NewSym)) + : cast(nonloc::SymbolVal(NewSym))); + } + else if (const RecordType *RT = T->getAsStructureType()) { + // Handle structs in a not so awesome way. Here we just + // eagerly bind new symbols to the fields. In reality we + // should have the store manager handle this. The idea is just + // to prototype some basic functionality here. All of this logic + // should one day soon just go away. + const RecordDecl *RD = RT->getDecl()->getDefinition(Ctx); + + // No record definition. There is nothing we can do. + if (!RD) + continue; + + MemRegionManager &MRMgr = state.getManager().getRegionManager(); + + // Iterate through the fields and construct new symbols. + for (RecordDecl::field_iterator FI=RD->field_begin(), + FE=RD->field_end(); FI!=FE; ++FI) { + + // For now just handle scalar fields. + FieldDecl *FD = *FI; + QualType FT = FD->getType(); + + if (Loc::IsLocType(FT) || + (FT->isIntegerType() && FT->isScalarType())) { + + // Tag the symbol with the field decl so that we generate + // a unique symbol. + SymbolRef NewSym = + Eng.getSymbolManager().getConjuredSymbol(*I, FT, Count, FD); + + // Create a region. + // FIXME: How do we handle 'typedefs' in TypeViewRegions? + // e.g.: + // typedef struct *s foo; + // + // ((foo) x)->f vs. x->f + // + // The cast will add a ViewTypeRegion. Probably RegionStore + // needs to reason about typedefs explicitly when binding + // fields and elements. + // + const FieldRegion* FR = MRMgr.getFieldRegion(FD, R); + + state = state.BindLoc(Loc::MakeVal(FR), + Loc::IsLocType(FT) + ? cast(loc::SymbolVal(NewSym)) + : cast(nonloc::SymbolVal(NewSym))); + } + } + } + else { + // Just blast away other values. + state = state.BindLoc(*MR, UnknownVal()); + } } } else diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m index a7409ec5dc..4759848b9a 100644 --- a/test/Analysis/misc-ps-region-store.m +++ b/test/Analysis/misc-ps-region-store.m @@ -19,3 +19,28 @@ void checkaccess_union() { ).__i))) & 0xff00) >> 8) == 1) ret = 1; } + + +// Check our handling of fields being invalidated by function calls. +struct test2_struct { int x; int y; char* s; }; +void test2_helper(struct test2_struct* p); + +char test2() { + struct test2_struct s; + test2_help(&s); + char *p = 0; + + if (s.x > 1) { + if (s.s != 0) { + p = "hello"; + } + } + + if (s.x > 1) { + if (s.s != 0) { + return *p; + } + } + + return 'a'; +} -- 2.50.1