From: Douglas Gregor Date: Thu, 1 Oct 2015 20:20:47 +0000 (+0000) Subject: Perform Objective-C lifetime adjustments before comparing deduced lambda result types. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1eef93ff1d6bd164478e3565110f04b87c85b6f8;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@249065 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 8b31876ddd..5b8240925d 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -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); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 85add92792..47d0107a66 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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 ArgArray, const FunctionProtoType::ExtProtoInfo &EPI) const { @@ -3027,14 +3042,8 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef 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. diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 952272e37f..a8f109df28 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -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. diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 8ca3f5693e..e876fa921e 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -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) diff --git a/test/SemaObjCXX/cxx1y-lambda.mm b/test/SemaObjCXX/cxx1y-lambda.mm new file mode 100644 index 0000000000..25445cc68c --- /dev/null +++ b/test/SemaObjCXX/cxx1y-lambda.mm @@ -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"; + } + }; +}