diff options
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; |