summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp218
1 files changed, 0 insertions, 218 deletions
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
deleted file mode 100644
index 7b724d2..0000000
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-//=== OSAtomicChecker.cpp - OSAtomic functions evaluator --------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This checker evaluates OSAtomic functions.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ClangSACheckers.h"
-#include "clang/StaticAnalyzer/Core/Checker.h"
-#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/Basic/Builtins.h"
-
-using namespace clang;
-using namespace ento;
-
-namespace {
-
-class OSAtomicChecker : public Checker<eval::InlineCall> {
-public:
- bool inlineCall(const CallExpr *CE, ExprEngine &Eng,
- ExplodedNode *Pred, ExplodedNodeSet &Dst) const;
-
-private:
- bool evalOSAtomicCompareAndSwap(const CallExpr *CE,
- ExprEngine &Eng,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst) const;
-};
-}
-
-static StringRef getCalleeName(ProgramStateRef State,
- const CallExpr *CE,
- const LocationContext *LCtx) {
- const Expr *Callee = CE->getCallee();
- SVal L = State->getSVal(Callee, LCtx);
- const FunctionDecl *funDecl = L.getAsFunctionDecl();
- if (!funDecl)
- return StringRef();
- IdentifierInfo *funI = funDecl->getIdentifier();
- if (!funI)
- return StringRef();
- return funI->getName();
-}
-
-bool OSAtomicChecker::inlineCall(const CallExpr *CE,
- ExprEngine &Eng,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst) const {
- StringRef FName = getCalleeName(Pred->getState(),
- CE, Pred->getLocationContext());
- if (FName.empty())
- return false;
-
- // Check for compare and swap.
- if (FName.startswith("OSAtomicCompareAndSwap") ||
- FName.startswith("objc_atomicCompareAndSwap"))
- return evalOSAtomicCompareAndSwap(CE, Eng, Pred, Dst);
-
- // FIXME: Other atomics.
- return false;
-}
-
-bool OSAtomicChecker::evalOSAtomicCompareAndSwap(const CallExpr *CE,
- ExprEngine &Eng,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst) const {
- // Not enough arguments to match OSAtomicCompareAndSwap?
- if (CE->getNumArgs() != 3)
- return false;
-
- ASTContext &Ctx = Eng.getContext();
- const Expr *oldValueExpr = CE->getArg(0);
- QualType oldValueType = Ctx.getCanonicalType(oldValueExpr->getType());
-
- const Expr *newValueExpr = CE->getArg(1);
- QualType newValueType = Ctx.getCanonicalType(newValueExpr->getType());
-
- // Do the types of 'oldValue' and 'newValue' match?
- if (oldValueType != newValueType)
- return false;
-
- const Expr *theValueExpr = CE->getArg(2);
- const PointerType *theValueType=theValueExpr->getType()->getAs<PointerType>();
-
- // theValueType not a pointer?
- if (!theValueType)
- return false;
-
- QualType theValueTypePointee =
- Ctx.getCanonicalType(theValueType->getPointeeType()).getUnqualifiedType();
-
- // The pointee must match newValueType and oldValueType.
- if (theValueTypePointee != newValueType)
- return false;
-
- static SimpleProgramPointTag OSAtomicLoadTag("OSAtomicChecker : Load");
- static SimpleProgramPointTag OSAtomicStoreTag("OSAtomicChecker : Store");
-
- // Load 'theValue'.
- ProgramStateRef state = Pred->getState();
- const LocationContext *LCtx = Pred->getLocationContext();
- ExplodedNodeSet Tmp;
- SVal location = state->getSVal(theValueExpr, LCtx);
- // Here we should use the value type of the region as the load type, because
- // we are simulating the semantics of the function, not the semantics of
- // passing argument. So the type of theValue expr is not we are loading.
- // But usually the type of the varregion is not the type we want either,
- // we still need to do a CastRetrievedVal in store manager. So actually this
- // LoadTy specifying can be omitted. But we put it here to emphasize the
- // semantics.
- QualType LoadTy;
- if (const TypedValueRegion *TR =
- dyn_cast_or_null<TypedValueRegion>(location.getAsRegion())) {
- LoadTy = TR->getValueType();
- }
- Eng.evalLoad(Tmp, CE, theValueExpr, Pred,
- state, location, &OSAtomicLoadTag, LoadTy);
-
- if (Tmp.empty()) {
- // If no nodes were generated, other checkers must have generated sinks.
- // We return an empty Dst.
- return true;
- }
-
- for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end();
- I != E; ++I) {
-
- ExplodedNode *N = *I;
- ProgramStateRef stateLoad = N->getState();
-
- // Use direct bindings from the environment since we are forcing a load
- // from a location that the Environment would typically not be used
- // to bind a value.
- SVal theValueVal_untested = stateLoad->getSVal(theValueExpr, LCtx, true);
-
- SVal oldValueVal_untested = stateLoad->getSVal(oldValueExpr, LCtx);
-
- // FIXME: Issue an error.
- if (theValueVal_untested.isUndef() || oldValueVal_untested.isUndef()) {
- return false;
- }
-
- DefinedOrUnknownSVal theValueVal =
- cast<DefinedOrUnknownSVal>(theValueVal_untested);
- DefinedOrUnknownSVal oldValueVal =
- cast<DefinedOrUnknownSVal>(oldValueVal_untested);
-
- SValBuilder &svalBuilder = Eng.getSValBuilder();
-
- // Perform the comparison.
- DefinedOrUnknownSVal Cmp =
- svalBuilder.evalEQ(stateLoad,theValueVal,oldValueVal);
-
- ProgramStateRef stateEqual = stateLoad->assume(Cmp, true);
-
- // Were they equal?
- if (stateEqual) {
- // Perform the store.
- ExplodedNodeSet TmpStore;
- SVal val = stateEqual->getSVal(newValueExpr, LCtx);
-
- // Handle implicit value casts.
- if (const TypedValueRegion *R =
- dyn_cast_or_null<TypedValueRegion>(location.getAsRegion())) {
- val = svalBuilder.evalCast(val,R->getValueType(), newValueExpr->getType());
- }
-
- Eng.evalStore(TmpStore, CE, theValueExpr, N,
- stateEqual, location, val, &OSAtomicStoreTag);
-
- if (TmpStore.empty()) {
- // If no nodes were generated, other checkers must have generated sinks.
- // We return an empty Dst.
- return true;
- }
-
- StmtNodeBuilder B(TmpStore, Dst, Eng.getBuilderContext());
- // Now bind the result of the comparison.
- for (ExplodedNodeSet::iterator I2 = TmpStore.begin(),
- E2 = TmpStore.end(); I2 != E2; ++I2) {
- ExplodedNode *predNew = *I2;
- ProgramStateRef stateNew = predNew->getState();
- // Check for 'void' return type if we have a bogus function prototype.
- SVal Res = UnknownVal();
- QualType T = CE->getType();
- if (!T->isVoidType())
- Res = Eng.getSValBuilder().makeTruthVal(true, T);
- B.generateNode(CE, predNew, stateNew->BindExpr(CE, LCtx, Res),
- false, this);
- }
- }
-
- // Were they not equal?
- if (ProgramStateRef stateNotEqual = stateLoad->assume(Cmp, false)) {
- // Check for 'void' return type if we have a bogus function prototype.
- SVal Res = UnknownVal();
- QualType T = CE->getType();
- if (!T->isVoidType())
- Res = Eng.getSValBuilder().makeTruthVal(false, CE->getType());
- StmtNodeBuilder B(N, Dst, Eng.getBuilderContext());
- B.generateNode(CE, N, stateNotEqual->BindExpr(CE, LCtx, Res),
- false, this);
- }
- }
-
- return true;
-}
-
-void ento::registerOSAtomicChecker(CheckerManager &mgr) {
- mgr.registerChecker<OSAtomicChecker>();
-}
OpenPOWER on IntegriCloud