aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Analysis/AnalysisContext.h20
-rw-r--r--include/clang/Analysis/CFG.h18
-rw-r--r--include/clang/Checker/PathSensitive/AnalysisManager.h10
-rw-r--r--include/clang/Checker/PathSensitive/CheckerVisitor.def3
-rw-r--r--include/clang/Checker/PathSensitive/CheckerVisitor.h7
-rw-r--r--include/clang/Checker/PathSensitive/GRExprEngine.h51
-rw-r--r--lib/Analysis/AnalysisContext.cpp9
-rw-r--r--lib/Analysis/CFG.cpp131
-rw-r--r--lib/Analysis/PseudoConstantAnalysis.cpp7
-rw-r--r--lib/Analysis/ReachableCode.cpp6
-rw-r--r--lib/Checker/AggExprVisitor.cpp2
-rw-r--r--lib/Checker/BugReporterVisitors.cpp5
-rw-r--r--lib/Checker/DereferenceChecker.cpp5
-rw-r--r--lib/Checker/Environment.cpp3
-rw-r--r--lib/Checker/GRCXXExprEngine.cpp20
-rw-r--r--lib/Checker/GRCoreEngine.cpp2
-rw-r--r--lib/Checker/GRExprEngine.cpp571
-rw-r--r--test/Analysis/constant-folding.c1
-rw-r--r--test/Analysis/idempotent-operations.c1
-rw-r--r--test/Analysis/method-call.cpp1
-rw-r--r--test/Analysis/misc-ps-region-store.cpp1
-rw-r--r--test/Analysis/reference.cpp3
22 files changed, 257 insertions, 620 deletions
diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h
index a941f7fe57..35f394f957 100644
--- a/include/clang/Analysis/AnalysisContext.h
+++ b/include/clang/Analysis/AnalysisContext.h
@@ -16,6 +16,7 @@
#define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerUnion.h"
@@ -200,7 +201,7 @@ public:
class StackFrameContext : public LocationContext {
// The callsite where this stack frame is established. The int bit indicates
// whether the call expr should return an l-value when it has reference type.
- llvm::PointerIntPair<const Stmt *, 1> CallSite;
+ const Stmt *CallSite;
// The parent block of the callsite.
const CFGBlock *Block;
@@ -210,17 +211,21 @@ class StackFrameContext : public LocationContext {
friend class LocationContextManager;
StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
- const Stmt *s, bool asLValue, const CFGBlock *blk,
+ const Stmt *s, const CFGBlock *blk,
unsigned idx)
- : LocationContext(StackFrame, ctx, parent), CallSite(s, asLValue),
+ : LocationContext(StackFrame, ctx, parent), CallSite(s),
Block(blk), Index(idx) {}
public:
~StackFrameContext() {}
- const Stmt *getCallSite() const { return CallSite.getPointer(); }
+ const Stmt *getCallSite() const { return CallSite; }
- bool evalAsLValue() const { return CallSite.getInt(); }
+ bool evalAsLValue() const {
+ if (const Expr *CE = dyn_cast<Expr>(CallSite))
+ return CE->isLValue();
+ return false;
+ }
const CFGBlock *getCallSiteBlock() const { return Block; }
@@ -230,9 +235,8 @@ public:
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
const LocationContext *parent, const Stmt *s,
- bool asLValue, const CFGBlock *blk, unsigned idx) {
+ const CFGBlock *blk, unsigned idx) {
ProfileCommon(ID, StackFrame, ctx, parent, s);
- ID.AddBoolean(asLValue);
ID.AddPointer(blk);
ID.AddInteger(idx);
}
@@ -300,7 +304,7 @@ public:
const StackFrameContext *getStackFrame(AnalysisContext *ctx,
const LocationContext *parent,
- const Stmt *s, bool asLValue,
+ const Stmt *s,
const CFGBlock *blk, unsigned idx);
const ScopeContext *getScope(AnalysisContext *ctx,
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index fb239e8207..e02d03d274 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -47,7 +47,6 @@ public:
enum Kind {
// main kind
Statement,
- StatementAsLValue,
Initializer,
ImplicitDtor,
// dtor kind
@@ -94,18 +93,14 @@ public:
class CFGStmt : public CFGElement {
public:
CFGStmt() {}
- CFGStmt(Stmt *S, bool asLValue) : CFGElement(S, asLValue) {}
+ CFGStmt(Stmt *S) : CFGElement(S, 0) {}
Stmt *getStmt() const { return static_cast<Stmt *>(Data1.getPointer()); }
operator Stmt*() const { return getStmt(); }
- bool asLValue() const {
- return static_cast<Kind>(Data1.getInt()) == StatementAsLValue;
- }
-
static bool classof(const CFGElement *E) {
- return E->getKind() == Statement || E->getKind() == StatementAsLValue;
+ return E->getKind() == Statement;
}
};
@@ -492,12 +487,13 @@ public:
Succs.push_back(Block, C);
}
- void appendStmt(Stmt* Statement, BumpVectorContext &C, bool asLValue) {
- Elements.push_back(CFGStmt(Statement, asLValue), C);
+ void appendStmt(Stmt* statement, BumpVectorContext &C) {
+ Elements.push_back(CFGStmt(statement), C);
}
- void appendInitializer(CXXBaseOrMemberInitializer *I, BumpVectorContext& C) {
- Elements.push_back(CFGInitializer(I), C);
+ void appendInitializer(CXXBaseOrMemberInitializer *initializer,
+ BumpVectorContext& C) {
+ Elements.push_back(CFGInitializer(initializer), C);
}
void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C) {
diff --git a/include/clang/Checker/PathSensitive/AnalysisManager.h b/include/clang/Checker/PathSensitive/AnalysisManager.h
index ce33269da0..473772b82e 100644
--- a/include/clang/Checker/PathSensitive/AnalysisManager.h
+++ b/include/clang/Checker/PathSensitive/AnalysisManager.h
@@ -178,23 +178,23 @@ public:
const StackFrameContext *getStackFrame(AnalysisContext *Ctx,
LocationContext const *Parent,
- const Stmt *S, bool asLValue,
+ const Stmt *S,
const CFGBlock *Blk, unsigned Idx) {
- return LocCtxMgr.getStackFrame(Ctx, Parent, S, asLValue, Blk, Idx);
+ return LocCtxMgr.getStackFrame(Ctx, Parent, S, Blk, Idx);
}
// Get the top level stack frame.
const StackFrameContext *getStackFrame(Decl const *D,
idx::TranslationUnit *TU) {
- return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0, 0);
+ return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0);
}
// Get a stack frame with parent.
StackFrameContext const *getStackFrame(const Decl *D,
LocationContext const *Parent,
- const Stmt *S, bool asLValue,
+ const Stmt *S,
const CFGBlock *Blk, unsigned Idx) {
- return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S, asLValue,
+ return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S,
Blk,Idx);
}
};
diff --git a/include/clang/Checker/PathSensitive/CheckerVisitor.def b/include/clang/Checker/PathSensitive/CheckerVisitor.def
index 4f9c48c2fe..3ee8071985 100644
--- a/include/clang/Checker/PathSensitive/CheckerVisitor.def
+++ b/include/clang/Checker/PathSensitive/CheckerVisitor.def
@@ -22,9 +22,12 @@
PREVISIT(ArraySubscriptExpr, Stmt)
PREVISIT(BinaryOperator, Stmt)
PREVISIT(CallExpr, GenericCall)
+PREVISIT(CStyleCastExpr, CastExpr)
+PREVISIT(CXXFunctionalCastExpr, CastExpr)
PREVISIT(CXXOperatorCallExpr, GenericCall)
PREVISIT(CXXMemberCallExpr, GenericCall)
PREVISIT(DeclStmt, Stmt)
+PREVISIT(ImplicitCastExpr, CastExpr)
PREVISIT(ObjCAtSynchronizedStmt, Stmt)
PREVISIT(ObjCMessageExpr, Stmt)
PREVISIT(ReturnStmt, Stmt)
diff --git a/include/clang/Checker/PathSensitive/CheckerVisitor.h b/include/clang/Checker/PathSensitive/CheckerVisitor.h
index 6d45bd3546..241d9e39ad 100644
--- a/include/clang/Checker/PathSensitive/CheckerVisitor.h
+++ b/include/clang/Checker/PathSensitive/CheckerVisitor.h
@@ -40,13 +40,6 @@ public:
default:
assert(false && "Unsupport statement.");
return;
-
- case Stmt::ImplicitCastExprClass:
- case Stmt::CStyleCastExprClass:
- static_cast<ImplClass*>(this)->PreVisitCastExpr(C,
- static_cast<const CastExpr*>(S));
- break;
-
case Stmt::CompoundAssignOperatorClass:
static_cast<ImplClass*>(this)->PreVisitBinaryOperator(C,
static_cast<const BinaryOperator*>(S));
diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h
index 2a0298f963..0b44c32ec3 100644
--- a/include/clang/Checker/PathSensitive/GRExprEngine.h
+++ b/include/clang/Checker/PathSensitive/GRExprEngine.h
@@ -297,14 +297,10 @@ public:
/// other functions that handle specific kinds of statements.
void Visit(const Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst);
- /// VisitLValue - evaluate the lvalue of the expression. For example, if Ex is
- /// a DeclRefExpr, it evaluates to the MemRegionVal which represents its
- /// storage location. Note that not all kinds of expressions has lvalue.
- void VisitLValue(const Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst);
-
/// VisitArraySubscriptExpr - Transfer function for array accesses.
- void VisitArraySubscriptExpr(const ArraySubscriptExpr* Ex, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ void VisitLvalArraySubscriptExpr(const ArraySubscriptExpr* Ex,
+ ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
/// VisitAsmStmt - Transfer function logic for inline asm.
void VisitAsmStmt(const AsmStmt* A, ExplodedNode* Pred, ExplodedNodeSet& Dst);
@@ -325,35 +321,26 @@ public:
/// VisitBinaryOperator - Transfer function logic for binary operators.
void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ ExplodedNodeSet& Dst);
/// VisitCall - Transfer function for function calls.
void VisitCall(const CallExpr* CE, ExplodedNode* Pred,
CallExpr::const_arg_iterator AI,
CallExpr::const_arg_iterator AE,
- ExplodedNodeSet& Dst, bool asLValue);
+ ExplodedNodeSet& Dst);
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred,
- ExplodedNodeSet &Dst, bool asLValue);
+ ExplodedNodeSet &Dst);
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
void VisitCompoundLiteralExpr(const CompoundLiteralExpr* CL,
- ExplodedNode* Pred, ExplodedNodeSet& Dst,
- bool asLValue);
-
- /// VisitDeclRefExpr - Transfer function logic for DeclRefExprs.
- void VisitDeclRefExpr(const DeclRefExpr* DR, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ ExplodedNode* Pred, ExplodedNodeSet& Dst);
- /// VisitBlockDeclRefExpr - Transfer function logic for BlockDeclRefExprs.
- void VisitBlockDeclRefExpr(const BlockDeclRefExpr* DR, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
-
+ /// Transfer function logic for DeclRefExprs and BlockDeclRefExprs.
void VisitCommonDeclRefExpr(const Expr* DR, const NamedDecl *D,
- ExplodedNode* Pred, ExplodedNodeSet& Dst,
- bool asLValue);
+ ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitDeclStmt - Transfer function logic for DeclStmts.
void VisitDeclStmt(const DeclStmt* DS, ExplodedNode* Pred,
@@ -377,15 +364,15 @@ public:
/// VisitMemberExpr - Transfer function for member expressions.
void VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ ExplodedNodeSet& Dst);
/// Transfer function logic for ObjCAtSynchronizedStmts.
void VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
- /// VisitObjCIvarRefExpr - Transfer function logic for ObjCIvarRefExprs.
- void VisitObjCIvarRefExpr(const ObjCIvarRefExpr* DR, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ /// Transfer function logic for computing the lvalue of an Objective-C ivar.
+ void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr* DR, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
/// VisitObjCForCollectionStmt - Transfer function logic for
/// ObjCForCollectionStmt.
@@ -398,7 +385,7 @@ public:
/// VisitObjCMessageExpr - Transfer function for ObjC message expressions.
void VisitObjCMessageExpr(const ObjCMessageExpr* ME, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ ExplodedNodeSet& Dst);
/// VisitReturnStmt - Transfer function logic for return statements.
void VisitReturnStmt(const ReturnStmt* R, ExplodedNode* Pred,
@@ -414,20 +401,18 @@ public:
/// VisitUnaryOperator - Transfer function logic for unary operators.
void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ ExplodedNodeSet& Dst);
void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
ExplodedNodeSet & Dst);
void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr,
- ExplodedNode *Pred, ExplodedNodeSet &Dst,
- bool asLValue) {
- VisitCXXConstructExpr(expr, 0, Pred, Dst, asLValue);
+ ExplodedNode *Pred, ExplodedNodeSet &Dst) {
+ VisitCXXConstructExpr(expr, 0, Pred, Dst);
}
void VisitCXXConstructExpr(const CXXConstructExpr *E, const MemRegion *Dest,
- ExplodedNode *Pred, ExplodedNodeSet &Dst,
- bool asLValue);
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
void VisitCXXDestructor(const CXXDestructorDecl *DD,
const MemRegion *Dest, const Stmt *S,
diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp
index 5307074dce..4305507c9c 100644
--- a/lib/Analysis/AnalysisContext.cpp
+++ b/lib/Analysis/AnalysisContext.cpp
@@ -152,8 +152,7 @@ void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
}
void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getAnalysisContext(), getParent(), CallSite.getPointer(),
- CallSite.getInt(), Block, Index);
+ Profile(ID, getAnalysisContext(), getParent(), CallSite, Block, Index);
}
void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) {
@@ -189,15 +188,15 @@ LocationContextManager::getLocationContext(AnalysisContext *ctx,
const StackFrameContext*
LocationContextManager::getStackFrame(AnalysisContext *ctx,
const LocationContext *parent,
- const Stmt *s, bool asLValue,
+ const Stmt *s,
const CFGBlock *blk, unsigned idx) {
llvm::FoldingSetNodeID ID;
- StackFrameContext::Profile(ID, ctx, parent, s, asLValue, blk, idx);
+ StackFrameContext::Profile(ID, ctx, parent, s, blk, idx);
void *InsertPos;
StackFrameContext *L =
cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
if (!L) {
- L = new StackFrameContext(ctx, parent, s, asLValue, blk, idx);
+ L = new StackFrameContext(ctx, parent, s, blk, idx);
Contexts.InsertNode(L, InsertPos);
}
return L;
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 35d93867c1..0f32614d2b 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -32,7 +32,6 @@ static SourceLocation GetEndLoc(Decl* D) {
if (VarDecl* VD = dyn_cast<VarDecl>(D))
if (Expr* Ex = VD->getInit())
return Ex->getSourceRange().getEnd();
-
return D->getLocation();
}
@@ -49,22 +48,13 @@ static SourceLocation GetEndLoc(Decl* D) {
/// the builder has an option not to add a subexpression as a
/// block-level expression.
///
-/// The lvalue bit captures whether or not a subexpression needs to
-/// be processed as an lvalue. That information needs to be recorded
-/// in the CFG for block-level expressions so that analyses do the
-/// right thing when traversing the CFG (since such subexpressions
-/// will be seen before their parent expression is processed).
class AddStmtChoice {
public:
- enum Kind { NotAlwaysAdd = 0,
- AlwaysAdd = 1,
- AsLValueNotAlwaysAdd = 2,
- AsLValueAlwaysAdd = 3 };
+ enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {}
bool alwaysAdd() const { return kind & AlwaysAdd; }
- bool asLValue() const { return kind >= AsLValueNotAlwaysAdd; }
/// Return a copy of this object, except with the 'always-add' bit
/// set as specified.
@@ -73,13 +63,6 @@ public:
Kind(kind & ~AlwaysAdd));
}
- /// Return a copy of this object, except with the 'as-lvalue' bit
- /// set as specified.
- AddStmtChoice withAsLValue(bool asLVal) const {
- return AddStmtChoice(asLVal ? Kind(kind | AsLValueNotAlwaysAdd) :
- Kind(kind & ~AsLValueNotAlwaysAdd));
- }
-
private:
Kind kind;
};
@@ -372,9 +355,9 @@ private:
void addLocalScopeAndDtors(Stmt* S);
// Interface to CFGBlock - adding CFGElements.
- void AppendStmt(CFGBlock *B, Stmt *S,
+ void appendStmt(CFGBlock *B, Stmt *S,
AddStmtChoice asc = AddStmtChoice::AlwaysAdd) {
- B->appendStmt(S, cfg->getBumpVectorContext(), asc.asLValue());
+ B->appendStmt(S, cfg->getBumpVectorContext());
}
void appendInitializer(CFGBlock *B, CXXBaseOrMemberInitializer *I) {
B->appendInitializer(I, cfg->getBumpVectorContext());
@@ -568,12 +551,12 @@ CFGBlock *CFGBuilder::addInitializer(CXXBaseOrMemberInitializer *I) {
appendInitializer(Block, I);
if (Init) {
- AddStmtChoice asc = AddStmtChoice().withAsLValue(IsReference);
- if (HasTemporaries)
+ if (HasTemporaries) {
// For expression with temporaries go directly to subexpression to omit
// generating destructors for the second time.
- return Visit(cast<ExprWithCleanups>(Init)->getSubExpr(), asc);
- return Visit(Init, asc);
+ return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
+ }
+ return Visit(Init);
}
return Block;
@@ -825,16 +808,6 @@ tryAgain:
case Stmt::ContinueStmtClass:
return VisitContinueStmt(cast<ContinueStmt>(S));
-
- case Stmt::CStyleCastExprClass: {
- CastExpr *castExpr = cast<CastExpr>(S);
- if (castExpr->getCastKind() == CK_LValueToRValue) {
- // temporary workaround
- S = castExpr->getSubExpr();
- goto tryAgain;
- }
- return VisitStmt(S, asc);
- }
case Stmt::CXXCatchStmtClass:
return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
@@ -881,15 +854,8 @@ tryAgain:
case Stmt::IfStmtClass:
return VisitIfStmt(cast<IfStmt>(S));
- case Stmt::ImplicitCastExprClass: {
- ImplicitCastExpr *castExpr = cast<ImplicitCastExpr>(S);
- if (castExpr->getCastKind() == CK_LValueToRValue) {
- // temporary workaround
- S = castExpr->getSubExpr();
- goto tryAgain;
- }
- return VisitImplicitCastExpr(castExpr, asc);
- }
+ case Stmt::ImplicitCastExprClass:
+ return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
case Stmt::IndirectGotoStmtClass:
return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
@@ -945,7 +911,7 @@ tryAgain:
CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
if (asc.alwaysAdd()) {
autoCreateBlock();
- AppendStmt(Block, S, asc);
+ appendStmt(Block, S, asc);
}
return VisitChildren(S);
@@ -967,28 +933,27 @@ CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
if (asc.alwaysAdd()) {
autoCreateBlock();
- AppendStmt(Block, A, asc);
+ appendStmt(Block, A, asc);
}
return Block;
}
CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U,
- AddStmtChoice asc) {
+ AddStmtChoice asc) {
if (asc.alwaysAdd()) {
autoCreateBlock();
- AppendStmt(Block, U, asc);
+ appendStmt(Block, U, asc);
}
- bool asLVal = U->isIncrementDecrementOp();
- return Visit(U->getSubExpr(), AddStmtChoice().withAsLValue(asLVal));
+ return Visit(U->getSubExpr(), AddStmtChoice());
}
CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
AddStmtChoice asc) {
if (B->isLogicalOp()) { // && or ||
CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
- AppendStmt(ConfluenceBlock, B, asc);
+ appendStmt(ConfluenceBlock, B, asc);
if (badCFG)
return 0;
@@ -1033,7 +998,7 @@ CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
if (B->getOpcode() == BO_Comma) { // ,
autoCreateBlock();
- AppendStmt(Block, B, asc);
+ appendStmt(Block, B, asc);
addStmt(B->getRHS());
return addStmt(B->getLHS());
}
@@ -1041,16 +1006,15 @@ CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
if (B->isAssignmentOp()) {
if (asc.alwaysAdd()) {
autoCreateBlock();
- AppendStmt(Block, B, asc);
+ appendStmt(Block, B, asc);
}
-
- Visit(B->getLHS(), AddStmtChoice::AsLValueNotAlwaysAdd);
+ Visit(B->getLHS());
return Visit(B->getRHS());
}
if (asc.alwaysAdd()) {
autoCreateBlock();
- AppendStmt(Block, B, asc);
+ appendStmt(Block, B, asc);
}
CFGBlock *RBlock = Visit(B->getRHS());
@@ -1064,7 +1028,7 @@ CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) {
if (asc.alwaysAdd()) {
autoCreateBlock();
- AppendStmt(Block, E, asc);
+ appendStmt(Block, E, asc);
}
return Block;
}
@@ -1142,7 +1106,7 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
}
Block = createBlock(!NoReturn);
- AppendStmt(Block, C, asc);
+ appendStmt(Block, C, asc);
if (NoReturn) {
// Wire this to the exit block directly.
@@ -1162,7 +1126,7 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,
AddStmtChoice asc) {
CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
- AppendStmt(ConfluenceBlock, C, asc);
+ appendStmt(ConfluenceBlock, C, asc);
if (badCFG)
return 0;
@@ -1212,7 +1176,7 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C,
// Create the confluence block that will "merge" the results of the ternary
// expression.
CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
- AppendStmt(ConfluenceBlock, C, asc);
+ appendStmt(ConfluenceBlock, C, asc);
if (badCFG)
return 0;
@@ -1310,7 +1274,7 @@ CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt* DS) {
if (!VD) {
autoCreateBlock();
- AppendStmt(Block, DS);
+ appendStmt(Block, DS);
return Block;
}
@@ -1332,16 +1296,15 @@ CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt* DS) {
}
autoCreateBlock();
- AppendStmt(Block, DS);
+ appendStmt(Block, DS);
if (Init) {
- AddStmtChoice asc = AddStmtChoice().withAsLValue(IsReference);
if (HasTemporaries)
// For expression with temporaries go directly to subexpression to omit
// generating destructors for the second time.
- Visit(cast<ExprWithCleanups>(Init)->getSubExpr(), asc);
+ Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
else
- Visit(Init, asc);
+ Visit(Init);
}
// If the type of VD is a VLA, then we must process its size expressions.
@@ -1459,7 +1422,7 @@ CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) {
if (VarDecl *VD = I->getConditionVariable()) {
if (Expr *Init = VD->getInit()) {
autoCreateBlock();
- AppendStmt(Block, I, AddStmtChoice::AlwaysAdd);
+ appendStmt(Block, I, AddStmtChoice::AlwaysAdd);
addStmt(Init);
}
}
@@ -1594,7 +1557,7 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) {
if (VarDecl *VD = F->getConditionVariable()) {
if (Expr *Init = VD->getInit()) {
autoCreateBlock();
- AppendStmt(Block, F, AddStmtChoice::AlwaysAdd);
+ appendStmt(Block, F, AddStmtChoice::AlwaysAdd);
EntryConditionBlock = addStmt(Init);
assert(Block == EntryConditionBlock);
}
@@ -1694,10 +1657,9 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) {
CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) {
if (asc.alwaysAdd()) {
autoCreateBlock();
- AppendStmt(Block, M, asc);
+ appendStmt(Block, M, asc);
}
- return Visit(M->getBase(),
- AddStmtChoice().withAsLValue(!M->isArrow()));
+ return Visit(M->getBase());
}
CFGBlock* CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
@@ -1753,7 +1715,7 @@ CFGBlock* CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
// The last statement in the block should be the ObjCForCollectionStmt, which
// performs the actual binding to 'element' and determines if there are any
// more items in the collection.
- AppendStmt(ExitConditionBlock, S);
+ appendStmt(ExitConditionBlock, S);
Block = ExitConditionBlock;
// Walk the 'element' expression to see if there are any side-effects. We
@@ -1820,7 +1782,7 @@ CFGBlock* CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt* S) {
// Add the @synchronized to the CFG.
autoCreateBlock();
- AppendStmt(Block, S, AddStmtChoice::AlwaysAdd);
+ appendStmt(Block, S, AddStmtChoice::AlwaysAdd);
// Inline the sync expression.
return addStmt(S->getSynchExpr());
@@ -1878,7 +1840,7 @@ CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) {
if (VarDecl *VD = W->getConditionVariable()) {
if (Expr *Init = VD->getInit()) {
autoCreateBlock();
- AppendStmt(Block, W, AddStmtChoice::AlwaysAdd);
+ appendStmt(Block, W, AddStmtChoice::AlwaysAdd);
EntryConditionBlock = addStmt(Init);
assert(Block == EntryConditionBlock);
}
@@ -2130,7 +2092,7 @@ CFGBlock *CFGBuilder::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E,
if (asc.alwaysAdd()) {
autoCreateBlock();
- AppendStmt(Block, E);
+ appendStmt(Block, E);
}
// VLA types have expressions that must be evaluated.
@@ -2148,7 +2110,7 @@ CFGBlock *CFGBuilder::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E,
CFGBlock* CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) {
if (asc.alwaysAdd()) {
autoCreateBlock();
- AppendStmt(Block, SE);
+ appendStmt(Block, SE);
}
return VisitCompoundStmt(SE->getSubStmt());
}
@@ -2226,7 +2188,7 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) {
if (VarDecl *VD = Terminator->getConditionVariable()) {
if (Expr *Init = VD->getInit()) {
autoCreateBlock();
- AppendStmt(Block, Terminator, AddStmtChoice::AlwaysAdd);
+ appendStmt(Block, Terminator, AddStmtChoice::AlwaysAdd);
addStmt(Init);
}
}
@@ -2429,7 +2391,7 @@ CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
AddStmtChoice asc) {
if (asc.alwaysAdd()) {
autoCreateBlock();
- AppendStmt(Block, E, asc);
+ appendStmt(Block, E, asc);
// We do not want to propagate the AlwaysAdd property.
asc = asc.withAlwaysAdd(false);
@@ -2441,7 +2403,7 @@ CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C,
AddStmtChoice asc) {
autoCreateBlock();
if (!C->isElidable())
- AppendStmt(Block, C, asc.withAlwaysAdd(true));
+ appendStmt(Block, C, asc.withAlwaysAdd(true));
return VisitChildren(C);
}
@@ -2450,7 +2412,7 @@ CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
AddStmtChoice asc) {
if (asc.alwaysAdd()) {
autoCreateBlock();
- AppendStmt(Block, E, asc);
+ appendStmt(Block, E, asc);
// We do not want to propagate the AlwaysAdd property.
asc = asc.withAlwaysAdd(false);
}
@@ -2460,14 +2422,14 @@ CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
AddStmtChoice asc) {
autoCreateBlock();
- AppendStmt(Block, C, asc.withAlwaysAdd(true));
+ appendStmt(Block, C, asc.withAlwaysAdd(true));
return VisitChildren(C);
}
CFGBlock *CFGBuilder::VisitCXXMemberCallExpr(CXXMemberCallExpr *C,
AddStmtChoice asc) {
autoCreateBlock();
- AppendStmt(Block, C, asc.withAlwaysAdd(true));
+ appendStmt(Block, C, asc.withAlwaysAdd(true));
return VisitChildren(C);
}
@@ -2475,11 +2437,9 @@ CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,
AddStmtChoice asc) {
if (asc.alwaysAdd()) {
autoCreateBlock();
- AppendStmt(Block, E, asc);
- // We do not want to propagate the AlwaysAdd property.
- asc = asc.withAlwaysAdd(false);
+ appendStmt(Block, E, asc);
}
- return Visit(E->getSubExpr(), asc);
+ return Visit(E->getSubExpr(), AddStmtChoice());
}
CFGBlock* CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt* I) {
@@ -3082,9 +3042,6 @@ static void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
OS << " (BindTemporary)";
}
- if (CS.asLValue())
- OS << " (asLValue)";
-
// Expressions need a newline.
if (isa<Expr>(S))
OS << '\n';
diff --git a/lib/Analysis/PseudoConstantAnalysis.cpp b/lib/Analysis/PseudoConstantAnalysis.cpp
index ff43fc252a..25b04fc2e8 100644
--- a/lib/Analysis/PseudoConstantAnalysis.cpp
+++ b/lib/Analysis/PseudoConstantAnalysis.cpp
@@ -86,6 +86,9 @@ void PseudoConstantAnalysis::RunAnalysis() {
const Stmt* Head = WorkList.front();
WorkList.pop_front();
+ if (const Expr *Ex = dyn_cast<Expr>(Head))
+ Head = Ex->IgnoreParenCasts();
+
switch (Head->getStmtClass()) {
// Case 1: Assignment operators modifying VarDecls
case Stmt::BinaryOperatorClass: {
@@ -225,8 +228,8 @@ void PseudoConstantAnalysis::RunAnalysis() {
continue;
}
- default:
- break;