--- /dev/null
+//== 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
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).
//==---------------------------------------------------------------------==//
#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"
class DynamicTypePropagation:
public Checker< check::PreCall,
check::PostCall,
+ check::DeadSymbols,
check::PostStmt<ImplicitCastExpr>,
check::PostStmt<CXXNewExpr> > {
const ObjCObjectType *getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE,
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);
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;
}
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: {
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;
}
}
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;
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 *
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;
}
void ento::registerDynamicTypePropagation(CheckerManager &mgr) {
mgr.registerChecker<DynamicTypePropagation>();
}
+
CommonBugCategories.cpp
ConstraintManager.cpp
CoreEngine.cpp
+ DynamicTypeMap.cpp
Environment.cpp
ExplodedGraph.cpp
ExprEngine.cpp
#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"
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();
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);
--- /dev/null
+//==- 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 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
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;
-}