diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-03-30 01:13:43 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-03-30 01:13:43 +0000 |
commit | 38ac243e300798e8cd9fe05888cd97beabfb94e6 (patch) | |
tree | bf8fa2eaf1262d1caaeb10671299790d1af4f6f1 /lib/Sema/SemaStmt.cpp | |
parent | 9ee20020255d0968fa0d8937b79e31406025a5c0 (diff) |
Make sure we perform the relevant implied conversions correctly for ObjC methods with related result types. PR12384.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153716 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 37 |
1 files changed, 19 insertions, 18 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 6db66a5eff..39e8a1a1b9 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1945,24 +1945,21 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp); QualType FnRetType; - QualType DeclaredRetType; + QualType RelatedRetType; if (const FunctionDecl *FD = getCurFunctionDecl()) { FnRetType = FD->getResultType(); - DeclaredRetType = FnRetType; if (FD->hasAttr<NoReturnAttr>() || FD->getType()->getAs<FunctionType>()->getNoReturnAttr()) Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) << FD->getDeclName(); } else if (ObjCMethodDecl *MD = getCurMethodDecl()) { - DeclaredRetType = MD->getResultType(); + FnRetType = MD->getResultType(); if (MD->hasRelatedResultType() && MD->getClassInterface()) { // In the implementation of a method with a related return type, the // type used to type-check the validity of return statements within the // method body is a pointer to the type of the class being implemented. - FnRetType = Context.getObjCInterfaceType(MD->getClassInterface()); - FnRetType = Context.getObjCObjectPointerType(FnRetType); - } else { - FnRetType = DeclaredRetType; + RelatedRetType = Context.getObjCInterfaceType(MD->getClassInterface()); + RelatedRetType = Context.getObjCObjectPointerType(RelatedRetType); } } else // If we don't have a function/method context, bail. return StmtError(); @@ -2045,6 +2042,21 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) { // we have a non-void function with an expression, continue checking + if (!RelatedRetType.isNull()) { + // If we have a related result type, perform an extra conversion here. + // FIXME: The diagnostics here don't really describe what is happening. + InitializedEntity Entity = + InitializedEntity::InitializeTemporary(RelatedRetType); + + ExprResult Res = PerformCopyInitialization(Entity, SourceLocation(), + RetValExp); + if (Res.isInvalid()) { + // FIXME: Cleanup temporaries here, anyway? + return StmtError(); + } + RetValExp = Res.takeAs<Expr>(); + } + // C99 6.8.6.4p3(136): The return statement is not an assignment. The // overlap restriction of subclause 6.5.16.1 does not apply to the case of // function return. @@ -2068,17 +2080,6 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (RetValExp) { - // If we type-checked an Objective-C method's return type based - // on a related return type, we may need to adjust the return - // type again. Do so now. - if (DeclaredRetType != FnRetType) { - ExprResult result = PerformImplicitConversion(RetValExp, - DeclaredRetType, - AA_Returning); - if (result.isInvalid()) return StmtError(); - RetValExp = result.take(); - } - CheckImplicitConversions(RetValExp, ReturnLoc); RetValExp = MaybeCreateExprWithCleanups(RetValExp); } |