[cfe-commits] r66094 - in /cfe/trunk: lib/Analysis/CFRefCount.cpp test/Analysis/misc-ps-region-store.m

Ted Kremenek kremenek at apple.com
Wed Mar 4 14:56:43 PST 2009


Author: kremenek
Date: Wed Mar  4 16:56:43 2009
New Revision: 66094

URL: http://llvm.org/viewvc/llvm-project?rev=66094&view=rev
Log:
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.

Modified:
    cfe/trunk/lib/Analysis/CFRefCount.cpp
    cfe/trunk/test/Analysis/misc-ps-region-store.m

Modified: cfe/trunk/lib/Analysis/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFRefCount.cpp?rev=66094&r1=66093&r2=66094&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Wed Mar  4 16:56:43 2009
@@ -1650,28 +1650,81 @@
           R = dyn_cast<TypedRegion>(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<RefBindings>(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<RefBindings>(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<SVal>(loc::SymbolVal(NewSym))
-                                  : cast<SVal>(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<SVal>(loc::SymbolVal(NewSym))
+                                    : cast<SVal>(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<SVal>(loc::SymbolVal(NewSym))
+                                        : cast<SVal>(nonloc::SymbolVal(NewSym)));
+                }                
+              }
+            }
+            else {
+              // Just blast away other values.
+              state = state.BindLoc(*MR, UnknownVal());
+            }
           }
         }
         else

Modified: cfe/trunk/test/Analysis/misc-ps-region-store.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps-region-store.m?rev=66094&r1=66093&r2=66094&view=diff

==============================================================================
--- cfe/trunk/test/Analysis/misc-ps-region-store.m (original)
+++ cfe/trunk/test/Analysis/misc-ps-region-store.m Wed Mar  4 16:56:43 2009
@@ -19,3 +19,28 @@
       ).__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';
+}





More information about the cfe-commits mailing list