]> granicus.if.org Git - clang/commitdiff
Perform Objective-C lifetime adjustments before comparing deduced lambda result types.
authorDouglas Gregor <dgregor@apple.com>
Thu, 1 Oct 2015 20:20:47 +0000 (20:20 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 1 Oct 2015 20:20:47 +0000 (20:20 +0000)
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

include/clang/AST/ASTContext.h
lib/AST/ASTContext.cpp
lib/Sema/SemaLambda.cpp
lib/Sema/SemaStmt.cpp
test/SemaObjCXX/cxx1y-lambda.mm [new file with mode: 0644]

index 8b31876dddac484ee90a6bc21214bec0752ba131..5b8240925d8e4df4dfa771efc1c26930e45c4ed9 100644 (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);
 
index 85add927925b552ad40bb73ecfd87f9a31fa7ff7..47d0107a66de8ffa3571139e4553c57415de848b 100644 (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.
index 952272e37f3f34e28eeb3574c4eb4714274d7b94..a8f109df2842b176a2795c5db0e56e1928eced7f 100644 (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.
index 8ca3f5693e2465b65f4d6181b8382334ddb22650..e876fa921e147257b8a945453662a981d660dd90 100644 (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)
diff --git a/test/SemaObjCXX/cxx1y-lambda.mm b/test/SemaObjCXX/cxx1y-lambda.mm
new file mode 100644 (file)
index 0000000..25445cc
--- /dev/null
@@ -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";
+    }
+  };
+}