diff options
author | Ted Kremenek <kremenek@apple.com> | 2010-01-09 22:58:54 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2010-01-09 22:58:54 +0000 |
commit | 4a749b957f28292e8412b7c13b01ca4baeb78d24 (patch) | |
tree | 35ee658987034b7a00a6da843f868f31f6d2efde /lib | |
parent | 124fca533d9fef2e3f6359283909bd342b5f5f26 (diff) |
Fix overzealous assertion in GRExprEngine::VisitLValue(). A
CallExpr/ObjCMessageExpr can be visited in an "lvalue" context if it
returns a struct temporary. Currently the analyzer doesn't reason
about struct temporary returned by function calls, but we shouldn't
crash here either.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93081 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index ed3dc8abac..b9a0ddc623 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -47,10 +47,9 @@ static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) { } -static bool CalleeReturnsReference(const CallExpr *CE) { +static QualType GetCalleeReturnType(const CallExpr *CE) { const Expr *Callee = CE->getCallee(); QualType T = Callee->getType(); - if (const PointerType *PT = T->getAs<PointerType>()) { const FunctionType *FT = PT->getPointeeType()->getAs<FunctionType>(); T = FT->getResultType(); @@ -58,16 +57,35 @@ static bool CalleeReturnsReference(const CallExpr *CE) { else { const BlockPointerType *BT = T->getAs<BlockPointerType>(); T = BT->getPointeeType()->getAs<FunctionType>()->getResultType(); - } - return T->isReferenceType(); + } + return T; +} + +static bool CalleeReturnsReference(const CallExpr *CE) { + return (bool) GetCalleeReturnType(CE)->getAs<ReferenceType>(); } static bool ReceiverReturnsReference(const ObjCMessageExpr *ME) { const ObjCMethodDecl *MD = ME->getMethodDecl(); if (!MD) return false; - return MD->getResultType()->isReferenceType(); + return MD->getResultType()->getAs<ReferenceType>(); +} + +#ifndef NDEBUG +static bool ReceiverReturnsReferenceOrRecord(const ObjCMessageExpr *ME) { + const ObjCMethodDecl *MD = ME->getMethodDecl(); + if (!MD) + return false; + QualType T = MD->getResultType(); + return T->getAs<RecordType>() || T->getAs<ReferenceType>(); +} + +static bool CalleeReturnsReferenceOrRecord(const CallExpr *CE) { + QualType T = GetCalleeReturnType(CE); + return T->getAs<ReferenceType>() || T->getAs<RecordType>(); } +#endif //===----------------------------------------------------------------------===// // Batch auditor. DEPRECATED. @@ -825,7 +843,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred, case Stmt::CallExprClass: case Stmt::CXXOperatorCallExprClass: { CallExpr *C = cast<CallExpr>(Ex); - assert(CalleeReturnsReference(C)); + assert(CalleeReturnsReferenceOrRecord(C)); VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst, true); break; } @@ -856,7 +874,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred, case Stmt::ObjCMessageExprClass: { ObjCMessageExpr *ME = cast<ObjCMessageExpr>(Ex); - assert(ReceiverReturnsReference(ME)); + assert(ReceiverReturnsReferenceOrRecord(ME)); VisitObjCMessageExpr(ME, Pred, Dst, true); return; } |