From: Ted Kremenek Date: Sat, 9 Jan 2010 22:58:54 +0000 (+0000) Subject: Fix overzealous assertion in GRExprEngine::VisitLValue(). A X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4a749b957f28292e8412b7c13b01ca4baeb78d24;p=clang 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 --- 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()) { const FunctionType *FT = PT->getPointeeType()->getAs(); T = FT->getResultType(); @@ -58,16 +57,35 @@ static bool CalleeReturnsReference(const CallExpr *CE) { else { const BlockPointerType *BT = T->getAs(); T = BT->getPointeeType()->getAs()->getResultType(); - } - return T->isReferenceType(); + } + return T; +} + +static bool CalleeReturnsReference(const CallExpr *CE) { + return (bool) GetCalleeReturnType(CE)->getAs(); } static bool ReceiverReturnsReference(const ObjCMessageExpr *ME) { const ObjCMethodDecl *MD = ME->getMethodDecl(); if (!MD) return false; - return MD->getResultType()->isReferenceType(); + return MD->getResultType()->getAs(); +} + +#ifndef NDEBUG +static bool ReceiverReturnsReferenceOrRecord(const ObjCMessageExpr *ME) { + const ObjCMethodDecl *MD = ME->getMethodDecl(); + if (!MD) + return false; + QualType T = MD->getResultType(); + return T->getAs() || T->getAs(); +} + +static bool CalleeReturnsReferenceOrRecord(const CallExpr *CE) { + QualType T = GetCalleeReturnType(CE); + return T->getAs() || T->getAs(); } +#endif //===----------------------------------------------------------------------===// // Batch auditor. DEPRECATED. @@ -825,7 +843,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred, case Stmt::CallExprClass: case Stmt::CXXOperatorCallExprClass: { CallExpr *C = cast(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(Ex); - assert(ReceiverReturnsReference(ME)); + assert(ReceiverReturnsReferenceOrRecord(ME)); VisitObjCMessageExpr(ME, Pred, Dst, true); return; } diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m index 06114c2ab0..df423efeae 100644 --- a/test/Analysis/misc-ps-region-store.m +++ b/test/Analysis/misc-ps-region-store.m @@ -684,3 +684,29 @@ void pr4358(struct pr4358 *pnt) { } pr4358_aux(uninit); // no-warning } + +//===----------------------------------------------------------------------===// +// +// Test handling fields of values returned from function calls or +// message expressions. +//===----------------------------------------------------------------------===// + +typedef struct testReturn_rdar_7526777 { + int x; + int y; +} testReturn_rdar_7526777; + +@interface TestReturnStruct_rdar_7526777 +- (testReturn_rdar_7526777) foo; +@end + +int test_return_struct(TestReturnStruct_rdar_7526777 *x) { + return [x foo].x; +} + +testReturn_rdar_7526777 test_return_struct_2_aux_rdar_7526777(); + +int test_return_struct_2_rdar_7526777() { + return test_return_struct_2_aux_rdar_7526777().x; +} +