forked from OSchip/llvm-project
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
This commit is contained in:
parent
ab2436ee83
commit
31a5bcc24e
|
@ -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<
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
// ^ * { ... }
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()) &&
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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'?}}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ struct S {
|
|||
|
||||
|
||||
@interface T
|
||||
- (int)foo: (T (^)(T*)) x;
|
||||
- (int)foo: (T* (^)(T*)) x;
|
||||
@end
|
||||
|
||||
void foo(T *P) {
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue