Perform Objective-C lifetime adjustments before comparing deduced lambda result types.

Objective-C ARC lifetime qualifiers are dropped when canonicalizing
function types. Perform the same adjustment before comparing the
deduced result types of lambdas. Fixes rdar://problem/22344904.

llvm-svn: 249065
This commit is contained in:
Douglas Gregor 2015-10-01 20:20:47 +00:00
parent 57e40deb8d
commit a602a153de
5 changed files with 46 additions and 11 deletions

View File

@ -968,6 +968,9 @@ public:
const FunctionType *adjustFunctionType(const FunctionType *Fn,
FunctionType::ExtInfo EInfo);
/// Adjust the given function result type.
CanQualType getCanonicalFunctionResultType(QualType ResultType) const;
/// \brief Change the result type of a function type once it is deduced.
void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType);

View File

@ -2990,6 +2990,21 @@ static bool isCanonicalResultType(QualType T) {
T.getObjCLifetime() == Qualifiers::OCL_ExplicitNone);
}
CanQualType
ASTContext::getCanonicalFunctionResultType(QualType ResultType) const {
CanQualType CanResultType = getCanonicalType(ResultType);
// Canonical result types do not have ARC lifetime qualifiers.
if (CanResultType.getQualifiers().hasObjCLifetime()) {
Qualifiers Qs = CanResultType.getQualifiers();
Qs.removeObjCLifetime();
return CanQualType::CreateUnsafe(
getQualifiedType(CanResultType.getUnqualifiedType(), Qs));
}
return CanResultType;
}
QualType
ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
const FunctionProtoType::ExtProtoInfo &EPI) const {
@ -3027,14 +3042,8 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
CanonicalEPI.HasTrailingReturn = false;
CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo();
// Result types do not have ARC lifetime qualifiers.
QualType CanResultTy = getCanonicalType(ResultTy);
if (ResultTy.getQualifiers().hasObjCLifetime()) {
Qualifiers Qs = CanResultTy.getQualifiers();
Qs.removeObjCLifetime();
CanResultTy = getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
}
// Adjust the canonical function result type.
CanQualType CanResultTy = getCanonicalFunctionResultType(ResultTy);
Canonical = getFunctionType(CanResultTy, CanonicalArgs, CanonicalEPI);
// Get the new insert position for the node we care about.

View File

@ -685,7 +685,8 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
QualType ReturnType =
(RetE ? RetE->getType() : Context.VoidTy).getUnqualifiedType();
if (Context.hasSameType(ReturnType, CSI.ReturnType))
if (Context.getCanonicalFunctionResultType(ReturnType) ==
Context.getCanonicalFunctionResultType(CSI.ReturnType))
continue;
// FIXME: This is a poor diagnostic for ReturnStmts without expressions.

View File

@ -3028,8 +3028,11 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
// the program is ill-formed.
if (AT->isDeduced() && !FD->isInvalidDecl()) {
AutoType *NewAT = Deduced->getContainedAutoType();
if (!FD->isDependentContext() &&
!Context.hasSameType(AT->getDeducedType(), NewAT->getDeducedType())) {
CanQualType OldDeducedType = Context.getCanonicalFunctionResultType(
AT->getDeducedType());
CanQualType NewDeducedType = Context.getCanonicalFunctionResultType(
NewAT->getDeducedType());
if (!FD->isDependentContext() && OldDeducedType != NewDeducedType) {
const LambdaScopeInfo *LambdaSI = getCurLambda();
if (LambdaSI && LambdaSI->HasImplicitReturnType) {
Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible)

View File

@ -0,0 +1,19 @@
// RUN: %clang_cc1 -std=c++1y -Wno-unused-value -fsyntax-only -verify -fobjc-arc %s
// expected-no-diagnostics
__attribute__((objc_root_class))
@interface NSString
@end
// rdar://problem/22344904
void testResultTypeDeduction(int i) {
auto x = [i] {
switch (i) {
case 0:
return @"foo";
default:
return @"bar";
}
};
}