r184006 - Unify return type checking for functions and ObjC methods. Move all the
Eli Friedman
eli.friedman at gmail.com
Fri Jun 14 14:14:10 PDT 2013
Author: efriedma
Date: Fri Jun 14 16:14:10 2013
New Revision: 184006
URL: http://llvm.org/viewvc/llvm-project?rev=184006&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclObjC.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaLambda.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm
cfe/trunk/test/CodeGenObjC/blocks.m
cfe/trunk/test/FixIt/fixit-static-object-decl.m
cfe/trunk/test/SemaObjC/method-bad-param.m
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=184006&r1=184005&r2=184006&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jun 14 16:14:10 2013
@@ -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<
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=184006&r1=184005&r2=184006&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Jun 14 16:14:10 2013
@@ -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
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=184006&r1=184005&r2=184006&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Jun 14 16:14:10 2013
@@ -5896,23 +5896,6 @@ Sema::ActOnFunctionDeclarator(Scope *S,
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;
Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=184006&r1=184005&r2=184006&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Fri Jun 14 16:14:10 2013
@@ -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);
}
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=184006&r1=184005&r2=184006&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Jun 14 16:14:10 2013
@@ -9887,13 +9887,6 @@ void Sema::ActOnBlockArguments(SourceLoc
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:
// ^ * { ... }
Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=184006&r1=184005&r2=184006&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Fri Jun 14 16:14:10 2013
@@ -194,9 +194,6 @@ LambdaScopeInfo *Sema::enterLambdaScope(
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 {
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=184006&r1=184005&r2=184006&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Fri Jun 14 16:14:10 2013
@@ -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(QualTy
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 *GetFullTypeForDec
}
}
+ // 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()) &&
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=184006&r1=184005&r2=184006&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Fri Jun 14 16:14:10 2013
@@ -8986,15 +8986,6 @@ TreeTransform<Derived>::TransformBlockEx
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());
Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm?rev=184006&r1=184005&r2=184006&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm Fri Jun 14 16:14:10 2013
@@ -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'?}}
}
Modified: cfe/trunk/test/CodeGenObjC/blocks.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/blocks.m?rev=184006&r1=184005&r2=184006&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/blocks.m (original)
+++ cfe/trunk/test/CodeGenObjC/blocks.m Fri Jun 14 16:14:10 2013
@@ -7,7 +7,7 @@ struct S {
@interface T
- - (int)foo: (T (^)(T*)) x;
+ - (int)foo: (T* (^)(T*)) x;
@end
void foo(T *P) {
Modified: cfe/trunk/test/FixIt/fixit-static-object-decl.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-static-object-decl.m?rev=184006&r1=184005&r2=184006&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/fixit-static-object-decl.m (original)
+++ cfe/trunk/test/FixIt/fixit-static-object-decl.m Fri Jun 14 16:14:10 2013
@@ -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];
}
Modified: cfe/trunk/test/SemaObjC/method-bad-param.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/method-bad-param.m?rev=184006&r1=184005&r2=184006&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/method-bad-param.m (original)
+++ cfe/trunk/test/SemaObjC/method-bad-param.m Fri Jun 14 16:14:10 2013
@@ -42,3 +42,7 @@ enum bogus; // expected-note {{forward d
}
@end
+ at interface arrayfun
+- (int[6])arrayRet; // expected-error {{function cannot return array type 'int [6]'}}
+- (int())funcRet; // expected-error {{function cannot return function type 'int ()'}}
+ at end
More information about the cfe-commits
mailing list