Added transfer function logic for sizeof(expr)/sizeof(type). This currently
doesn't support VLAs.
Reordered some cases in the switch statement of GRConstant::Visit() so
that they are ordered alphabetically based on AST node type.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47021 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Analysis/GRConstants.cpp b/Analysis/GRConstants.cpp
index 8b94aaa..90b055c 100644
--- a/Analysis/GRConstants.cpp
+++ b/Analysis/GRConstants.cpp
@@ -295,6 +295,10 @@
/// VisitLogicalExpr - Transfer function logic for '&&', '||'
void VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
+
+ /// VisitSizeOfAlignOfTypeExpr - Transfer function for sizeof(type).
+ void VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* S, NodeTy* Pred,
+ NodeSet& Dst);
};
} // end anonymous namespace
@@ -378,7 +382,8 @@
// Get the current block counter.
GRBlockCounter BC = builder.getBlockCounter();
- unsigned NumVisited = BC.getNumVisited(builder.getTargetBlock(true)->getBlockID());
+ unsigned BlockID = builder.getTargetBlock(true)->getBlockID();
+ unsigned NumVisited = BC.getNumVisited(BlockID);
if (isa<nonlval::ConcreteInt>(V) ||
BC.getNumVisited(builder.getTargetBlock(true)->getBlockID()) < 1) {
@@ -397,8 +402,8 @@
else
builder.markInfeasible(true);
- NumVisited = BC.getNumVisited(builder.getTargetBlock(true)->getBlockID());
-
+ BlockID = builder.getTargetBlock(false)->getBlockID();
+ NumVisited = BC.getNumVisited(BlockID);
if (isa<nonlval::ConcreteInt>(V) ||
BC.getNumVisited(builder.getTargetBlock(false)->getBlockID()) < 1) {
@@ -583,6 +588,28 @@
Nodify(Dst, S, Pred, SetValue(St, S, R));
}
+/// VisitSizeOfAlignOfTypeExpr - Transfer function for sizeof(type).
+void GRConstants::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* S,
+ NodeTy* Pred,
+ NodeSet& Dst) {
+
+ // 6.5.3.4 sizeof: "The result type is an integer."
+
+ QualType T = S->getArgumentType();
+
+ // FIXME: Add support for VLAs.
+ if (isa<VariableArrayType>(T.getTypePtr()))
+ return;
+
+ SourceLocation L = S->getExprLoc();
+ uint64_t size = getContext().getTypeSize(T, L) / 8;
+
+ Nodify(Dst, S, Pred,
+ SetValue(Pred->getState(), S,
+ NonLValue::GetValue(ValMgr, size, getContext().IntTy, L)));
+
+}
+
void GRConstants::VisitUnaryOperator(UnaryOperator* U,
GRConstants::NodeTy* Pred,
GRConstants::NodeSet& Dst) {
@@ -686,6 +713,25 @@
break;
}
+
+ case UnaryOperator::SizeOf: {
+ // 6.5.3.4 sizeof: "The result type is an integer."
+
+ QualType T = U->getSubExpr()->getType();
+
+ // FIXME: Add support for VLAs.
+ if (isa<VariableArrayType>(T.getTypePtr()))
+ return;
+
+ SourceLocation L = U->getExprLoc();
+ uint64_t size = getContext().getTypeSize(T, L) / 8;
+
+ Nodify(Dst, U, N1,
+ SetValue(St, U, NonLValue::GetValue(ValMgr, size,
+ getContext().IntTy, L)));
+
+ break;
+ }
case UnaryOperator::AddrOf: {
const LValue& L1 = GetLValue(St, U->getSubExpr());
@@ -885,14 +931,55 @@
Nodify(Dst, B, Pred, SetValue(St, B, GetValue(St, B->getRHS())));
break;
}
+
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+ break;
+ }
+
+ case Stmt::CastExprClass: {
+ CastExpr* C = cast<CastExpr>(S);
+ VisitCast(C, C->getSubExpr(), Pred, Dst);
+ break;
}
- // Fall-through.
+ case Stmt::ChooseExprClass: { // __builtin_choose_expr
+ ChooseExpr* C = cast<ChooseExpr>(S);
+ VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
+ break;
+ }
case Stmt::CompoundAssignOperatorClass:
VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
break;
+ case Stmt::ConditionalOperatorClass: { // '?' operator
+ ConditionalOperator* C = cast<ConditionalOperator>(S);
+ VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
+ break;
+ }
+
+ case Stmt::DeclRefExprClass:
+ VisitDeclRefExpr(cast<DeclRefExpr>(S), Pred, Dst);
+ break;
+
+ case Stmt::DeclStmtClass:
+ VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
+ break;
+
+ case Stmt::ImplicitCastExprClass: {
+ ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
+ VisitCast(C, C->getSubExpr(), Pred, Dst);
+ break;
+ }
+
+ case Stmt::ParenExprClass:
+ Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
+ break;
+
+ case Stmt::SizeOfAlignOfTypeExprClass:
+ VisitSizeOfAlignOfTypeExpr(cast<SizeOfAlignOfTypeExpr>(S), Pred, Dst);
+ break;
+
case Stmt::StmtExprClass: {
StmtExpr* SE = cast<StmtExpr>(S);
@@ -902,52 +989,17 @@
break;
}
- case Stmt::UnaryOperatorClass:
- VisitUnaryOperator(cast<UnaryOperator>(S), Pred, Dst);
- break;
-
- case Stmt::ParenExprClass:
- Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
- break;
-
- case Stmt::DeclRefExprClass:
- VisitDeclRefExpr(cast<DeclRefExpr>(S), Pred, Dst);
- break;
-
- case Stmt::ImplicitCastExprClass: {
- ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
- VisitCast(C, C->getSubExpr(), Pred, Dst);
- break;
- }
-
- case Stmt::CastExprClass: {
- CastExpr* C = cast<CastExpr>(S);
- VisitCast(C, C->getSubExpr(), Pred, Dst);
- break;
- }
-
- case Stmt::ConditionalOperatorClass: { // '?' operator
- ConditionalOperator* C = cast<ConditionalOperator>(S);
- VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
- break;
- }
-
- case Stmt::ChooseExprClass: { // __builtin_choose_expr
- ChooseExpr* C = cast<ChooseExpr>(S);
- VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
- break;
- }
-
- case Stmt::ReturnStmtClass:
+ case Stmt::ReturnStmtClass: {
if (Expr* R = cast<ReturnStmt>(S)->getRetValue())
Visit(R, Pred, Dst);
else
Dst.Add(Pred);
break;
+ }
- case Stmt::DeclStmtClass:
- VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
+ case Stmt::UnaryOperatorClass:
+ VisitUnaryOperator(cast<UnaryOperator>(S), Pred, Dst);
break;
default: