From: Ted Kremenek Date: Thu, 21 Feb 2008 18:43:30 +0000 (+0000) Subject: Simplified and generalized transfer function logic for casts, allowing X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9ef1ec98a8fc17e7560e07641184bc4daee39b46;p=clang Simplified and generalized transfer function logic for casts, allowing the transfer function to be invoked without an Expr* for the Cast operation. Added implicit promotions to the transfer function logic for compound assignments. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47444 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Analysis/GRExprEngine.cpp b/Analysis/GRExprEngine.cpp index 1ca37615d8..51b0a597ee 100644 --- a/Analysis/GRExprEngine.cpp +++ b/Analysis/GRExprEngine.cpp @@ -477,7 +477,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ NodeTy* N = *I1; StateTy St = N->getState(); RVal V = GetRVal(St, Ex); - Nodify(Dst, CastE, N, SetRVal(St, CastE, EvalCast(ValMgr, V, CastE))); + Nodify(Dst, CastE, N, SetRVal(St, CastE, EvalCast(V, CastE->getType()))); } } @@ -520,14 +520,13 @@ void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, void GRExprEngine::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* Ex, NodeTy* Pred, NodeSet& Dst) { - - assert (Ex->isSizeOf() && "AlignOf(Expr) not yet implemented."); + + assert (Ex->isSizeOf() && "FIXME: AlignOf(Expr) not yet implemented."); // 6.5.3.4 sizeof: "The result type is an integer." QualType T = Ex->getArgumentType(); - - // FIXME: Implement alignof + // FIXME: Add support for VLAs. if (!T.getTypePtr()->isConstantSizeType()) @@ -942,7 +941,16 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, else ((int&) Op) -= BinaryOperator::MulAssign; - RVal Result = EvalBinOp(Op, V, RightV); + // Get the computation type. + QualType CTy = cast(B)->getComputationType(); + + // Perform promotions. + V = EvalCast(V, CTy); + RightV = EvalCast(V, CTy); + + // Evaluate operands and promote to result type. + RVal Result = EvalCast(EvalBinOp(Op, V, RightV), B->getType()); + St = SetRVal(SetRVal(St, B, Result), LeftLV, Result); } } diff --git a/Analysis/GRSimpleVals.cpp b/Analysis/GRSimpleVals.cpp index 675882f42e..ed0706be89 100644 --- a/Analysis/GRSimpleVals.cpp +++ b/Analysis/GRSimpleVals.cpp @@ -58,17 +58,16 @@ unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx, // Transfer function for Casts. //===----------------------------------------------------------------------===// -RVal GRSimpleVals::EvalCast(ValueManager& ValMgr, NonLVal X, Expr* CastExpr) { +RVal GRSimpleVals::EvalCast(ValueManager& ValMgr, NonLVal X, QualType T) { if (!isa(X)) return UnknownVal(); llvm::APSInt V = cast(X).getValue(); - QualType T = CastExpr->getType(); V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType()); - V.extOrTrunc(ValMgr.getContext().getTypeSize(T, CastExpr->getLocStart())); + V.extOrTrunc(ValMgr.getContext().getTypeSize(T, SourceLocation())); - if (CastExpr->getType()->isPointerType()) + if (T->isPointerType()) return lval::ConcreteInt(ValMgr.getValue(V)); else return nonlval::ConcreteInt(ValMgr.getValue(V)); @@ -76,20 +75,19 @@ RVal GRSimpleVals::EvalCast(ValueManager& ValMgr, NonLVal X, Expr* CastExpr) { // Casts. -RVal GRSimpleVals::EvalCast(ValueManager& ValMgr, LVal X, Expr* CastExpr) { +RVal GRSimpleVals::EvalCast(ValueManager& ValMgr, LVal X, QualType T) { - if (CastExpr->getType()->isPointerType()) + if (T->isPointerType()) return X; - assert (CastExpr->getType()->isIntegerType()); + assert (T->isIntegerType()); if (!isa(X)) return UnknownVal(); llvm::APSInt V = cast(X).getValue(); - QualType T = CastExpr->getType(); V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType()); - V.extOrTrunc(ValMgr.getContext().getTypeSize(T, CastExpr->getLocStart())); + V.extOrTrunc(ValMgr.getContext().getTypeSize(T, SourceLocation())); return nonlval::ConcreteInt(ValMgr.getValue(V)); } diff --git a/Analysis/GRSimpleVals.h b/Analysis/GRSimpleVals.h index 28286ec11f..870166e8f4 100644 --- a/Analysis/GRSimpleVals.h +++ b/Analysis/GRSimpleVals.h @@ -28,8 +28,8 @@ public: // Casts. - virtual RVal EvalCast(ValueManager& ValMgr, NonLVal V, Expr* CastExpr); - virtual RVal EvalCast(ValueManager& ValMgr, LVal V, Expr* CastExpr); + virtual RVal EvalCast(ValueManager& ValMgr, NonLVal V, QualType CastT); + virtual RVal EvalCast(ValueManager& ValMgr, LVal V, QualType CastT); // Unary Operators. diff --git a/Analysis/GRTransferFuncs.cpp b/Analysis/GRTransferFuncs.cpp deleted file mode 100644 index 29d6216b71..0000000000 --- a/Analysis/GRTransferFuncs.cpp +++ /dev/null @@ -1,41 +0,0 @@ -//== GRTransferFuncs.cpp - Path-Sens. Transfer Functions Interface -*- C++ -*--= -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This files defines GRTransferFuncs, which provides a base-class that -// defines an interface for transfer functions used by GRExprEngine. -// -//===----------------------------------------------------------------------===// - -#include "clang/Analysis/PathSensitive/GRTransferFuncs.h" - -using namespace clang; - -//===----------------------------------------------------------------------===// -// Transfer function for Casts. -//===----------------------------------------------------------------------===// - -RVal GRTransferFuncs::EvalCast(ValueManager& ValMgr, RVal X, Expr* CastExpr) { - - switch (X.getBaseKind()) { - - default: - assert(false && "Invalid RVal."); break; - - case RVal::LValKind: - return EvalCast(ValMgr, cast(X), CastExpr); - - case RVal::NonLValKind: - return EvalCast(ValMgr, cast(X), CastExpr); - - case RVal::UninitializedKind: - case RVal::UnknownKind: break; - } - - return X; -} diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index fbb0275dd4..f83f3d3e5c 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -341,8 +341,14 @@ public: void VisitDeref(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst); - RVal EvalCast(ValueManager& ValMgr, RVal X, Expr* CastExpr) { - return X.isValid() ? TF->EvalCast(ValMgr, X, CastExpr) : X; + RVal EvalCast(RVal X, QualType CastT) { + if (X.isUnknownOrUninit()) + return X; + + if (isa(X)) + return TF->EvalCast(ValMgr, cast(X), CastT); + else + return TF->EvalCast(ValMgr, cast(X), CastT); } RVal EvalMinus(UnaryOperator* U, RVal X) { diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index faa559ee58..2a8ec2b6f7 100644 --- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h @@ -26,9 +26,8 @@ public: // Casts. - RVal EvalCast(ValueManager& ValMgr, RVal V, Expr* CastExpr); - virtual RVal EvalCast(ValueManager& ValMgr, NonLVal V, Expr* CastExpr) =0; - virtual RVal EvalCast(ValueManager& ValMgr, LVal V, Expr* CastExpr) = 0; + virtual RVal EvalCast(ValueManager& ValMgr, NonLVal V, QualType CastT) =0; + virtual RVal EvalCast(ValueManager& ValMgr, LVal V, QualType CastT) = 0; // Unary Operators.