diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2013-06-14 21:14:10 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2013-06-14 21:14:10 +0000 |
commit | 31a5bcc24ea1145de4c9470f6b803f4decf27c87 (patch) | |
tree | 900b98e9734fe2e7137413a45c43f0901a612e89 /clang | |
parent | ab2436ee832df6728941b7af247b2f6a20ec0285 (diff) | |
download | bcm5719-llvm-31a5bcc24ea1145de4c9470f6b803f4decf27c87.tar.gz bcm5719-llvm-31a5bcc24ea1145de4c9470f6b803f4decf27c87.zip |
Unify return type checking for functions and ObjC methods. Move all the
random checks for ObjC object return types to SemaType.cpp.
Fixes issue with ObjC method type checking reported on cfe-dev.
llvm-svn: 184006
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 55 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 9 | ||||
-rw-r--r-- | clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm | 2 | ||||
-rw-r--r-- | clang/test/CodeGenObjC/blocks.m | 2 | ||||
-rw-r--r-- | clang/test/FixIt/fixit-static-object-decl.m | 12 | ||||
-rw-r--r-- | clang/test/SemaObjC/method-bad-param.m | 4 |
12 files changed, 70 insertions, 62 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d014a9dcb38..7891f12323e 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4926,8 +4926,6 @@ let CategoryName = "Lambda Issue" in { "lambda expression in default argument cannot capture any entity">; def err_lambda_incomplete_result : Error< "incomplete result type %0 in lambda expression">; - def err_lambda_objc_object_result : Error< - "non-pointer Objective-C class type %0 in lambda expression result">; def err_noreturn_lambda_has_return_expr : Error< "lambda declared 'noreturn' should not return">; def warn_maybe_falloff_nonvoid_lambda : Warning< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 117a519fb63..9a91bc46d7b 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1003,6 +1003,8 @@ public: QualType BuildExtVectorType(QualType T, Expr *ArraySize, SourceLocation AttrLoc); + bool CheckFunctionReturnType(QualType T, SourceLocation Loc); + /// \brief Build a function type. /// /// This routine checks the function type according to C++ rules and diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e43a318804d..f0d9fe8baae 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5896,23 +5896,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, diag::err_invalid_thread) << DeclSpec::getSpecifierName(TSCS); - // Do not allow returning a objc interface by-value. - if (R->getAs<FunctionType>()->getResultType()->isObjCObjectType()) { - Diag(D.getIdentifierLoc(), - diag::err_object_cannot_be_passed_returned_by_value) << 0 - << R->getAs<FunctionType>()->getResultType() - << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*"); - - QualType T = R->getAs<FunctionType>()->getResultType(); - T = Context.getObjCObjectPointerType(T); - if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(R)) { - FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - R = Context.getFunctionType(T, FPT->getArgTypes(), EPI); - } - else if (isa<FunctionNoProtoType>(R)) - R = Context.getFunctionNoProtoType(T); - } - bool isFriend = false; FunctionTemplateDecl *FunctionTemplate = 0; bool isExplicitSpecialization = false; diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 21d66d04976..07282935c8a 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -3009,14 +3009,9 @@ Decl *Sema::ActOnMethodDeclaration( if (ReturnType) { resultDeclType = GetTypeFromParser(ReturnType, &ResultTInfo); - // Methods cannot return interface types. All ObjC objects are - // passed by reference. - if (resultDeclType->isObjCObjectType()) { - Diag(MethodLoc, diag::err_object_cannot_be_passed_returned_by_value) - << 0 << resultDeclType; + if (CheckFunctionReturnType(resultDeclType, MethodLoc)) return 0; - } - + HasRelatedResultType = (resultDeclType == Context.getObjCInstanceType()); } else { // get the type for "id". resultDeclType = Context.getObjCIdType(); @@ -3099,14 +3094,8 @@ Decl *Sema::ActOnMethodDeclaration( else // Perform the default array/function conversions (C99 6.7.5.3p[7,8]). ArgType = Context.getAdjustedParameterType(ArgType); - if (ArgType->isObjCObjectType()) { - Diag(Param->getLocation(), - diag::err_object_cannot_be_passed_returned_by_value) - << 1 << ArgType; - Param->setInvalidDecl(); - } + Param->setDeclContext(ObjCMethod); - Params.push_back(Param); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index a6473a1c5c4..edeb731b83d 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -9887,13 +9887,6 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, CurBlock->TheDecl->setIsVariadic(isVariadic); - // Don't allow returning a objc interface by value. - if (RetTy->isObjCObjectType()) { - Diag(ParamInfo.getLocStart(), - diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; - return; - } - // Context.DependentTy is used as a placeholder for a missing block // return type. TODO: what should we do with declarators like: // ^ * { ... } diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index d8e90e5cb58..32cc176119d 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -194,9 +194,6 @@ LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator, if (RequireCompleteType(CallOperator->getLocStart(), LSI->ReturnType, diag::err_lambda_incomplete_result)) { // Do nothing. - } else if (LSI->ReturnType->isObjCObjectOrInterfaceType()) { - Diag(CallOperator->getLocStart(), diag::err_lambda_objc_object_result) - << LSI->ReturnType; } } } else { diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 99beabeda9b..279a6e34823 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -33,6 +33,8 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" +#include "TypeLocBuilder.h" + using namespace clang; /// isOmittedBlockReturnType - Return true if this declarator is missing a @@ -1654,24 +1656,38 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc); } -QualType Sema::BuildFunctionType(QualType T, - llvm::MutableArrayRef<QualType> ParamTypes, - SourceLocation Loc, DeclarationName Entity, - const FunctionProtoType::ExtProtoInfo &EPI) { +bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) { if (T->isArrayType() || T->isFunctionType()) { Diag(Loc, diag::err_func_returning_array_function) << T->isFunctionType() << T; - return QualType(); + return true; } // Functions cannot return half FP. if (T->isHalfType()) { Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 1 << FixItHint::CreateInsertion(Loc, "*"); - return QualType(); + return true; + } + + // Methods cannot return interface types. All ObjC objects are + // passed by reference. + if (T->isObjCObjectType()) { + Diag(Loc, diag::err_object_cannot_be_passed_returned_by_value) << 0 << T; + return 0; } + return false; +} + +QualType Sema::BuildFunctionType(QualType T, + llvm::MutableArrayRef<QualType> ParamTypes, + SourceLocation Loc, DeclarationName Entity, + const FunctionProtoType::ExtProtoInfo &EPI) { bool Invalid = false; + + Invalid |= CheckFunctionReturnType(T, Loc); + for (unsigned Idx = 0, Cnt = ParamTypes.size(); Idx < Cnt; ++Idx) { // FIXME: Loc is too inprecise here, should use proper locations for args. QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]); @@ -2682,6 +2698,33 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } } + // Methods cannot return interface types. All ObjC objects are + // passed by reference. + if (T->isObjCObjectType()) { + SourceLocation DiagLoc, FixitLoc; + if (TInfo) { + DiagLoc = TInfo->getTypeLoc().getLocStart(); + FixitLoc = S.PP.getLocForEndOfToken(TInfo->getTypeLoc().getLocEnd()); + } else { + DiagLoc = D.getDeclSpec().getTypeSpecTypeLoc(); + FixitLoc = S.PP.getLocForEndOfToken(D.getDeclSpec().getLocEnd()); + } + S.Diag(DiagLoc, diag::err_object_cannot_be_passed_returned_by_value) + << 0 << T + << FixItHint::CreateInsertion(FixitLoc, "*"); + + T = Context.getObjCObjectPointerType(T); + if (TInfo) { + TypeLocBuilder TLB; + TLB.pushFullCopy(TInfo->getTypeLoc()); + ObjCObjectPointerTypeLoc TLoc = TLB.push<ObjCObjectPointerTypeLoc>(T); + TLoc.setStarLoc(FixitLoc); + TInfo = TLB.getTypeSourceInfo(Context, T); + } + + D.setInvalidType(true); + } + // cv-qualifiers on return types are pointless except when the type is a // class type in C++. if ((T.getCVRQualifiers() || T->isAtomicType()) && diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index da1e41c2afb..1fd206bbc20 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -8986,15 +8986,6 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { QualType exprResultType = getDerived().TransformType(exprFunctionType->getResultType()); - // Don't allow returning a objc interface by value. - if (exprResultType->isObjCObjectType()) { - getSema().Diag(E->getCaretLocation(), - diag::err_object_cannot_be_passed_returned_by_value) - << 0 << exprResultType; - getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/0); - return ExprError(); - } - QualType functionType = getDerived().RebuildFunctionProtoType(exprResultType, paramTypes, exprFunctionType->getExtProtoInfo()); diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm index 0126e23a74a..92c62904d57 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm @@ -4,5 +4,5 @@ @end void test_result_type() { - auto l1 = [] () -> A { }; // expected-error{{non-pointer Objective-C class type 'A' in lambda expression result}} + auto l1 = [] () -> A { }; // expected-error{{interface type 'A' cannot be returned by value; did you forget * in 'A'?}} } diff --git a/clang/test/CodeGenObjC/blocks.m b/clang/test/CodeGenObjC/blocks.m index 3718ad590a5..d872e17051b 100644 --- a/clang/test/CodeGenObjC/blocks.m +++ b/clang/test/CodeGenObjC/blocks.m @@ -7,7 +7,7 @@ struct S { @interface T - - (int)foo: (T (^)(T*)) x; + - (int)foo: (T* (^)(T*)) x; @end void foo(T *P) { diff --git a/clang/test/FixIt/fixit-static-object-decl.m b/clang/test/FixIt/fixit-static-object-decl.m index e13900fa786..5f4feada490 100644 --- a/clang/test/FixIt/fixit-static-object-decl.m +++ b/clang/test/FixIt/fixit-static-object-decl.m @@ -5,8 +5,8 @@ // Objective-C++ recovery // RUN: cp %s %t -// RUN: not %clang_cc1 -fixit -x objective-c++ %t -// RUN: %clang_cc1 -fsyntax-only -Werror -x objective-c++ %t +// RUN: not %clang_cc1 -fixit -x objective-c++ %t -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -Werror -x objective-c++ %t -std=c++11 // rdar://9603056 @interface S @end @@ -24,6 +24,14 @@ NSArray func() { return P; } +NSArray (func2)() { return 0; } + +#ifdef __cplusplus +void test_result_type() { + auto l1 = [] () -> NSArray { return 0; }; +} +#endif + int main() { NSArray pluginNames = [NSArray arrayWithObjects]; } diff --git a/clang/test/SemaObjC/method-bad-param.m b/clang/test/SemaObjC/method-bad-param.m index d44b53614aa..30aba7b9d0d 100644 --- a/clang/test/SemaObjC/method-bad-param.m +++ b/clang/test/SemaObjC/method-bad-param.m @@ -42,3 +42,7 @@ enum bogus; // expected-note {{forward declaration of 'enum bogus'}} } @end +@interface arrayfun +- (int[6])arrayRet; // expected-error {{function cannot return array type 'int [6]'}} +- (int())funcRet; // expected-error {{function cannot return function type 'int ()'}} +@end |