xazax.hun updated this revision to Diff 34507.
xazax.hun added a comment.

- Updated to latest trunk.
- Separated the set/getDynamicTypeInfo APIs out from ProgramState

Note that it is not advised to put the implementations of 
set/getDynamicTypeInfo into a checker, because in that case there is a circular 
dependency during linking. The checkers use the symbols that are implemented in 
the clangStaticAnalyzerCore module and this way clangStaticAnalyzerCore would 
use symbols from that are implemented in the checkers as well.


http://reviews.llvm.org/D12767

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
  include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
  lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
  lib/StaticAnalyzer/Core/CMakeLists.txt
  lib/StaticAnalyzer/Core/CallEvent.cpp
  lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
  lib/StaticAnalyzer/Core/ProgramState.cpp

Index: lib/StaticAnalyzer/Core/ProgramState.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ProgramState.cpp
+++ lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -14,6 +14,7 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
 #include "clang/Analysis/CFG.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h"
@@ -752,36 +753,3 @@
   return Tainted;
 }
 
-/// The GDM component containing the dynamic type info. This is a map from a
-/// symbol to its most likely type.
-REGISTER_TRAIT_WITH_PROGRAMSTATE(DynamicTypeMap,
-                                 CLANG_ENTO_PROGRAMSTATE_MAP(const MemRegion *,
-                                                             DynamicTypeInfo))
-
-DynamicTypeInfo ProgramState::getDynamicTypeInfo(const MemRegion *Reg) const {
-  Reg = Reg->StripCasts();
-
-  // Look up the dynamic type in the GDM.
-  const DynamicTypeInfo *GDMType = get<DynamicTypeMap>(Reg);
-  if (GDMType)
-    return *GDMType;
-
-  // Otherwise, fall back to what we know about the region.
-  if (const TypedRegion *TR = dyn_cast<TypedRegion>(Reg))
-    return DynamicTypeInfo(TR->getLocationType(), /*CanBeSubclass=*/false);
-
-  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Reg)) {
-    SymbolRef Sym = SR->getSymbol();
-    return DynamicTypeInfo(Sym->getType());
-  }
-
-  return DynamicTypeInfo();
-}
-
-ProgramStateRef ProgramState::setDynamicTypeInfo(const MemRegion *Reg,
-                                                 DynamicTypeInfo NewTy) const {
-  Reg = Reg->StripCasts();
-  ProgramStateRef NewState = set<DynamicTypeMap>(Reg, NewTy);
-  assert(NewState);
-  return NewState;
-}
Index: lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
===================================================================
--- /dev/null
+++ lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
@@ -0,0 +1,51 @@
+//==- DynamicTypeMap.cpp - Dynamic Type Info related APIs ----------*- C++ -*-//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines APIs that are related to track and query dynamic type
+//  information. This information can be used to devirtualize calls during the
+//  symbolic exection or do type checking.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
+
+namespace clang {
+namespace ento {
+
+DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State,
+                                   const MemRegion *Reg) {
+  Reg = Reg->StripCasts();
+
+  // Look up the dynamic type in the GDM.
+  const DynamicTypeInfo *GDMType = State->get<DynamicTypeMap>(Reg);
+  if (GDMType)
+    return *GDMType;
+
+  // Otherwise, fall back to what we know about the region.
+  if (const TypedRegion *TR = dyn_cast<TypedRegion>(Reg))
+    return DynamicTypeInfo(TR->getLocationType(), /*CanBeSubclass=*/false);
+
+  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Reg)) {
+    SymbolRef Sym = SR->getSymbol();
+    return DynamicTypeInfo(Sym->getType());
+  }
+
+  return DynamicTypeInfo();
+}
+
+ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg,
+                                   DynamicTypeInfo NewTy) {
+  Reg = Reg->StripCasts();
+  ProgramStateRef NewState = State->set<DynamicTypeMap>(Reg, NewTy);
+  assert(NewState);
+  return NewState;
+}
+
+} // namespace ento
+} // namespace clang
Index: lib/StaticAnalyzer/Core/CallEvent.cpp
===================================================================
--- lib/StaticAnalyzer/Core/CallEvent.cpp
+++ lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/ParentMap.h"
 #include "clang/Analysis/ProgramPoint.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/raw_ostream.h"
@@ -435,7 +436,7 @@
     return RuntimeDefinition();
 
   // Do we know anything about the type of 'this'?
-  DynamicTypeInfo DynType = getState()->getDynamicTypeInfo(R);
+  DynamicTypeInfo DynType = getDynamicTypeInfo(getState(), R);
   if (!DynType.isValid())
     return RuntimeDefinition();
 
@@ -800,7 +801,7 @@
       if (!Receiver)
         return RuntimeDefinition();
 
-      DynamicTypeInfo DTI = getState()->getDynamicTypeInfo(Receiver);
+      DynamicTypeInfo DTI = getDynamicTypeInfo(getState(), Receiver);
       QualType DynType = DTI.getType();
       CanBeSubClassed = DTI.canBeASubClass();
       ReceiverT = dyn_cast<ObjCObjectPointerType>(DynType);
Index: lib/StaticAnalyzer/Core/CMakeLists.txt
===================================================================
--- lib/StaticAnalyzer/Core/CMakeLists.txt
+++ lib/StaticAnalyzer/Core/CMakeLists.txt
@@ -17,6 +17,7 @@
   CommonBugCategories.cpp
   ConstraintManager.cpp
   CoreEngine.cpp
+  DynamicTypeMap.cpp
   Environment.cpp
   ExplodedGraph.cpp
   ExprEngine.cpp
Index: lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
+++ lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
@@ -17,6 +17,7 @@
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
 
@@ -27,6 +28,7 @@
 class DynamicTypePropagation:
     public Checker< check::PreCall,
                     check::PostCall,
+                    check::DeadSymbols,
                     check::PostStmt<ImplicitCastExpr>,
                     check::PostStmt<CXXNewExpr> > {
   const ObjCObjectType *getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE,
@@ -40,9 +42,23 @@
   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
   void checkPostStmt(const ImplicitCastExpr *CastE, CheckerContext &C) const;
   void checkPostStmt(const CXXNewExpr *NewE, CheckerContext &C) const;
+  void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
 };
 }
 
+void DynamicTypePropagation::checkDeadSymbols(SymbolReaper &SR,
+                                              CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+  DynamicTypeMapImpl TypeMap = State->get<DynamicTypeMap>();
+  for (DynamicTypeMapImpl::iterator I = TypeMap.begin(), E = TypeMap.end();
+       I != E; ++I) {
+    if (!SR.isLiveRegion(I->first)) {
+      State = State->remove<DynamicTypeMap>(I->first);
+    }
+  }
+  C.addTransition(State);
+}
+
 static void recordFixedType(const MemRegion *Region, const CXXMethodDecl *MD,
                             CheckerContext &C) {
   assert(Region);
@@ -52,7 +68,7 @@
   QualType Ty = Ctx.getPointerType(Ctx.getRecordType(MD->getParent()));
 
   ProgramStateRef State = C.getState();
-  State = State->setDynamicTypeInfo(Region, Ty, /*CanBeSubclass=*/false);
+  State = setDynamicTypeInfo(State, Region, Ty, /*CanBeSubclass=*/false);
   C.addTransition(State);
   return;
 }
@@ -131,17 +147,17 @@
           return;
         QualType DynResTy =
                  C.getASTContext().getObjCObjectPointerType(QualType(ObjTy, 0));
-        C.addTransition(State->setDynamicTypeInfo(RetReg, DynResTy, false));
+        C.addTransition(setDynamicTypeInfo(State, RetReg, DynResTy, false));
         break;
       }
       case OMF_init: {
         // Assume, the result of the init method has the same dynamic type as
         // the receiver and propagate the dynamic type info.
         const MemRegion *RecReg = Msg->getReceiverSVal().getAsRegion();
         if (!RecReg)
           return;
-        DynamicTypeInfo RecDynType = State->getDynamicTypeInfo(RecReg);
-        C.addTransition(State->setDynamicTypeInfo(RetReg, RecDynType));
+        DynamicTypeInfo RecDynType = getDynamicTypeInfo(State, RecReg);
+        C.addTransition(setDynamicTypeInfo(State, RetReg, RecDynType));
         break;
       }
       }
@@ -186,7 +202,7 @@
   case CK_BitCast:
     // Only handle ObjCObjects for now.
     if (const Type *NewTy = getBetterObjCType(CastE, C))
-      C.addTransition(C.getState()->setDynamicTypeInfo(ToR, QualType(NewTy,0)));
+      C.addTransition(setDynamicTypeInfo(C.getState(), ToR, QualType(NewTy,0)));
     break;
   }
   return;
@@ -202,8 +218,8 @@
   if (!MR)
     return;
 
-  C.addTransition(C.getState()->setDynamicTypeInfo(MR, NewE->getType(),
-                                                   /*CanBeSubclass=*/false));
+  C.addTransition(setDynamicTypeInfo(C.getState(), MR, NewE->getType(),
+                                     /*CanBeSubclass=*/false));
 }
 
 const ObjCObjectType *
@@ -254,7 +270,7 @@
       CastE->getType()->getAs<ObjCObjectPointerType>();
   if (!NewTy)
     return nullptr;
-  QualType OldDTy = C.getState()->getDynamicTypeInfo(ToR).getType();
+  QualType OldDTy = getDynamicTypeInfo(C.getState(), ToR).getType();
   if (OldDTy.isNull()) {
     return NewTy;
   }
@@ -279,3 +295,4 @@
 void ento::registerDynamicTypePropagation(CheckerManager &mgr) {
   mgr.registerChecker<DynamicTypePropagation>();
 }
+
Index: include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -337,20 +337,6 @@
   bool isTainted(SymbolRef Sym, TaintTagType Kind = TaintTagGeneric) const;
   bool isTainted(const MemRegion *Reg, TaintTagType Kind=TaintTagGeneric) const;
 
-  /// \brief Get dynamic type information for a region.
-  DynamicTypeInfo getDynamicTypeInfo(const MemRegion *Reg) const;
-
-  /// \brief Set dynamic type information of the region; return the new state.
-  ProgramStateRef setDynamicTypeInfo(const MemRegion *Reg,
-                                     DynamicTypeInfo NewTy) const;
-
-  /// \brief Set dynamic type information of the region; return the new state.
-  ProgramStateRef setDynamicTypeInfo(const MemRegion *Reg,
-                                     QualType NewTy,
-                                     bool CanBeSubClassed = true) const {
-    return setDynamicTypeInfo(Reg, DynamicTypeInfo(NewTy, CanBeSubClassed));
-  }
-
   //==---------------------------------------------------------------------==//
   // Accessing the Generic Data Map (GDM).
   //==---------------------------------------------------------------------==//
Index: include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
===================================================================
--- /dev/null
+++ include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
@@ -0,0 +1,57 @@
+//== DynamicTypeMap.h - Dynamic type map ----------------------- -*- C++ -*--=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file provides APIs for tracking dynamic type information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "llvm/ADT/ImmutableMap.h"
+
+namespace clang {
+namespace ento {
+
+/// The GDM component containing the dynamic type info. This is a map from a
+/// symbol to its most likely type.
+struct DynamicTypeMap {};
+typedef llvm::ImmutableMap<const MemRegion *, DynamicTypeInfo>
+    DynamicTypeMapImpl;
+template <>
+struct ProgramStateTrait<DynamicTypeMap>
+    : public ProgramStatePartialTrait<DynamicTypeMapImpl> {
+  static void *GDMIndex() {
+    static int index = 0;
+    return &index;
+  }
+};
+
+/// \brief Get dynamic type information for a region.
+DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State,
+                                   const MemRegion *Reg);
+
+/// \brief Set dynamic type information of the region; return the new state.
+ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg,
+                                   DynamicTypeInfo NewTy);
+
+/// \brief Set dynamic type information of the region; return the new state.
+inline ProgramStateRef setDynamicTypeInfo(ProgramStateRef State,
+                                          const MemRegion *Reg, QualType NewTy,
+                                          bool CanBeSubClassed = true) {
+  return setDynamicTypeInfo(State, Reg,
+                            DynamicTypeInfo(NewTy, CanBeSubClassed));
+}
+
+} // ento
+} // clang
+
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to