diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp | 134 |
1 files changed, 90 insertions, 44 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp index 65cea7a..d7c0a54 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp @@ -501,7 +501,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, = CondExpr->isTypeDependent() || CondExpr->isValueDependent(); unsigned CondWidth = HasDependentValue ? 0 : Context.getIntWidth(CondTypeBeforePromotion); - bool CondIsSigned = CondTypeBeforePromotion->isSignedIntegerType(); + bool CondIsSigned + = CondTypeBeforePromotion->isSignedIntegerOrEnumerationType(); // Accumulate all of the case values in a vector so that we can sort them // and detect duplicates. This vector contains the APInt for the case after @@ -723,7 +724,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // If switch has default case, then ignore it. if (!CaseListIsErroneous && !HasConstantCond && ET) { const EnumDecl *ED = ET->getDecl(); - typedef llvm::SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> EnumValsTy; + typedef llvm::SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> + EnumValsTy; EnumValsTy EnumVals; // Gather all enum values, set their type and sort them, @@ -1252,7 +1254,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, ExprResult BoundExpr; if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(UnqAT)) BoundExpr = Owned(IntegerLiteral::Create(Context, CAT->getSize(), - Context.IntTy, RangeLoc)); + Context.getPointerDiffType(), + RangeLoc)); else if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(UnqAT)) BoundExpr = VAT->getSizeExpr(); @@ -1455,7 +1458,10 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) { /// \param E The expression being returned from the function or block, or /// being thrown. /// -/// \param AllowFunctionParameter +/// \param AllowFunctionParameter Whether we allow function parameters to +/// be considered NRVO candidates. C++ prohibits this for NRVO itself, but +/// we re-use this logic to determine whether we should try to move as part of +/// a return or throw (which does allow function parameters). /// /// \returns The NRVO candidate variable, if the return statement may use the /// NRVO, or NULL if there is no such candidate. @@ -1525,12 +1531,11 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, // parameter of the selected constructor is not an rvalue reference // to the object's type (possibly cv-qualified), overload resolution // is performed again, considering the object as an lvalue. - if (Seq.getKind() != InitializationSequence::FailedSequence) { + if (Seq) { for (InitializationSequence::step_iterator Step = Seq.step_begin(), StepEnd = Seq.step_end(); Step != StepEnd; ++Step) { - if (Step->Kind - != InitializationSequence::SK_ConstructorInitialization) + if (Step->Kind != InitializationSequence::SK_ConstructorInitialization) continue; CXXConstructorDecl *Constructor @@ -1583,14 +1588,18 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (Result.isInvalid()) return StmtError(); RetValExp = Result.take(); - CurBlock->ReturnType = RetValExp->getType(); - if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) { - // We have to remove a 'const' added to copied-in variable which was - // part of the implementation spec. and not the actual qualifier for - // the variable. - if (CDRE->isConstQualAdded()) - CurBlock->ReturnType.removeLocalConst(); // FIXME: local??? - } + + if (!RetValExp->isTypeDependent()) { + CurBlock->ReturnType = RetValExp->getType(); + if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) { + // We have to remove a 'const' added to copied-in variable which was + // part of the implementation spec. and not the actual qualifier for + // the variable. + if (CDRE->isConstQualAdded()) + CurBlock->ReturnType.removeLocalConst(); // FIXME: local??? + } + } else + CurBlock->ReturnType = Context.DependentTy; } else CurBlock->ReturnType = Context.VoidTy; } @@ -1607,13 +1616,17 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // compatibility to worry about here. ReturnStmt *Result = 0; if (CurBlock->ReturnType->isVoidType()) { - if (RetValExp) { + if (RetValExp && !RetValExp->isTypeDependent() && + (!getLangOptions().CPlusPlus || !RetValExp->getType()->isVoidType())) { Diag(ReturnLoc, diag::err_return_block_has_expr); RetValExp = 0; } Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, 0); } else if (!RetValExp) { - return StmtError(Diag(ReturnLoc, diag::err_block_return_missing_expr)); + if (!CurBlock->ReturnType->isDependentType()) + return StmtError(Diag(ReturnLoc, diag::err_block_return_missing_expr)); + + Result = new (Context) ReturnStmt(ReturnLoc, 0, 0); } else { const VarDecl *NRVOCandidate = 0; @@ -1652,7 +1665,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // If we need to check for the named return value optimization, save the // return statement in our scope for later processing. - if (getLangOptions().CPlusPlus && FnRetType->isRecordType() && + if (getLangOptions().CPlusPlus && FnRetType->isRecordType() && !CurContext->isDependentContext()) FunctionScopes.back()->Returns.push_back(Result); @@ -1661,44 +1674,62 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { StmtResult Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { + // Check for unexpanded parameter packs. + if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp)) + return StmtError(); + if (getCurBlock()) return ActOnBlockReturnStmt(ReturnLoc, RetValExp); QualType FnRetType; + QualType DeclaredRetType; 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) << getCurFunctionOrMethodDecl()->getDeclName(); - } else if (ObjCMethodDecl *MD = getCurMethodDecl()) - FnRetType = MD->getResultType(); - else // If we don't have a function/method context, bail. + } else if (ObjCMethodDecl *MD = getCurMethodDecl()) { + DeclaredRetType = 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; + } + } else // If we don't have a function/method context, bail. return StmtError(); ReturnStmt *Result = 0; if (FnRetType->isVoidType()) { - if (RetValExp && !RetValExp->isTypeDependent()) { - // C99 6.8.6.4p1 (ext_ since GCC warns) - unsigned D = diag::ext_return_has_expr; - if (RetValExp->getType()->isVoidType()) - D = diag::ext_return_has_void_expr; - else { - ExprResult Result = Owned(RetValExp); - Result = IgnoredValueConversions(Result.take()); - if (Result.isInvalid()) - return StmtError(); - RetValExp = Result.take(); - RetValExp = ImpCastExprToType(RetValExp, Context.VoidTy, CK_ToVoid).take(); - } + if (RetValExp) { + if (!RetValExp->isTypeDependent()) { + // C99 6.8.6.4p1 (ext_ since GCC warns) + unsigned D = diag::ext_return_has_expr; + if (RetValExp->getType()->isVoidType()) + D = diag::ext_return_has_void_expr; + else { + ExprResult Result = Owned(RetValExp); + Result = IgnoredValueConversions(Result.take()); + if (Result.isInvalid()) + return StmtError(); + RetValExp = Result.take(); + RetValExp = ImpCastExprToType(RetValExp, + Context.VoidTy, CK_ToVoid).take(); + } - // return (some void expression); is legal in C++. - if (D != diag::ext_return_has_void_expr || - !getLangOptions().CPlusPlus) { - NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); - Diag(ReturnLoc, D) - << CurDecl->getDeclName() << isa<ObjCMethodDecl>(CurDecl) - << RetValExp->getSourceRange(); + // return (some void expression); is legal in C++. + if (D != diag::ext_return_has_void_expr || + !getLangOptions().CPlusPlus) { + NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); + Diag(ReturnLoc, D) + << CurDecl->getDeclName() << isa<ObjCMethodDecl>(CurDecl) + << RetValExp->getSourceRange(); + } } CheckImplicitConversions(RetValExp, ReturnLoc); @@ -1730,7 +1761,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false); InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc, FnRetType, - NRVOCandidate != 0); + NRVOCandidate != 0); ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate, FnRetType, RetValExp); if (Res.isInvalid()) { @@ -1744,6 +1775,17 @@ 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); } @@ -2015,7 +2057,9 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (InputDomain == AD_Int && OutputDomain == AD_Int && !isOperandMentioned(InputOpNo, Pieces) && InputExpr->isEvaluatable(Context)) { - InputExpr = ImpCastExprToType(InputExpr, OutTy, CK_IntegralCast).take(); + CastKind castKind = + (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast); + InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take(); Exprs[InputOpNo] = InputExpr; NS->setInputExpr(i, InputExpr); continue; @@ -2251,7 +2295,9 @@ Sema::ActOnSEHExceptBlock(SourceLocation Loc, assert(FilterExpr && Block); if(!FilterExpr->getType()->isIntegerType()) { - return StmtError(Diag(FilterExpr->getExprLoc(), diag::err_filter_expression_integral) << FilterExpr->getType()); + return StmtError(Diag(FilterExpr->getExprLoc(), + diag::err_filter_expression_integral) + << FilterExpr->getType()); } return Owned(SEHExceptStmt::Create(Context,Loc,FilterExpr,Block)); |