]> granicus.if.org Git - clang/commitdiff
When inferring the result type of a block based on a return statement
authorDouglas Gregor <dgregor@apple.com>
Sun, 5 Jun 2011 05:04:23 +0000 (05:04 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sun, 5 Jun 2011 05:04:23 +0000 (05:04 +0000)
with a type-dependent expression, infer the placeholder type
'Context.DependentTy' to indicate that this is just a
placeholder. Fixes PR9982 / <rdar://problem/9486685>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132657 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CodeGenModule.cpp
lib/Sema/SemaStmt.cpp
test/CodeGenObjCXX/block-in-template-inst.mm

index de11a29f67b7024837adfe346964b2e4bb8bcf5a..bea70ea38f314beefc5830bb7d5de27be40e7ba2 100644 (file)
@@ -2082,6 +2082,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
   case Decl::FunctionTemplate:
   case Decl::TypeAliasTemplate:
   case Decl::NamespaceAlias:
+  case Decl::Block:
     break;
   case Decl::CXXConstructor:
     // Skip function templates
index ec0e74f0a7d80c4ef09e57aee9c88a0b5edd301b..1ecb4196b9d5cb4355825ce600c9c2b36180163d 100644 (file)
@@ -1589,14 +1589,18 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
       if (Result.isInvalid())
         return StmtError();
       RetValExp = Result.take();
-      CurBlock->ReturnType = RetValExp->getType();
-      if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) {
-        // We have to remove a 'const' added to copied-in variable which was
-        // part of the implementation spec. and not the actual qualifier for
-        // the variable.
-        if (CDRE->isConstQualAdded())
-          CurBlock->ReturnType.removeLocalConst(); // FIXME: local???
-      }
+
+      if (!RetValExp->isTypeDependent()) {
+        CurBlock->ReturnType = RetValExp->getType();
+        if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) {
+          // We have to remove a 'const' added to copied-in variable which was
+          // part of the implementation spec. and not the actual qualifier for
+          // the variable.
+          if (CDRE->isConstQualAdded())
+            CurBlock->ReturnType.removeLocalConst(); // FIXME: local???
+        }
+      } else
+        CurBlock->ReturnType = Context.DependentTy;
     } else
       CurBlock->ReturnType = Context.VoidTy;
   }
@@ -1658,7 +1662,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
 
   // If we need to check for the named return value optimization, save the
   // return statement in our scope for later processing.
-  if (getLangOptions().CPlusPlus && FnRetType->isRecordType() &&
+  if (getLangOptions().CPlusPlus && FnRetType->isRecordType() && 
       !CurContext->isDependentContext())
     FunctionScopes.back()->Returns.push_back(Result);
 
index 862488ddb7e2ebc190df954b90d50aa47c3c9c42..72042fc03330065223d57f401b4eaac1a11ca660 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm-only -fblocks -o - -triple x86_64-apple-darwin10 %s
+// RUN: %clang_cc1 -emit-llvm-only -std=c++0x -fblocks -o - -triple x86_64-apple-darwin10 %s
 // rdar://9362021
 
 @class DYFuture;
@@ -32,3 +32,40 @@ void FUNC()
     ResourceManager<AnalyzerBaseObjectTypes> *rm;
     ^(void) { rm->XXX(); }();
 }
+
+namespace PR9982 {
+  template<typename T> struct Curry;
+
+  template<typename R, typename Arg0, typename Arg1, typename Arg2>
+    struct Curry<R (^)(Arg0, Arg1, Arg2)>
+    {
+      typedef R (^FType)(Arg0, Arg1, Arg2);
+    
+    Curry(FType _f) : f(_f) {}
+      ~Curry() {;}
+    
+      R (^(^operator()(Arg0 a))(Arg1))(Arg2) 
+      { 
+        auto block = ^(Arg1 b) {
+          auto inner_block = ^(Arg2 c) {
+            return f(a, b, c);
+          };
+          return inner_block; 
+        };
+        return block;
+      }
+    
+    private:
+      FType f;
+    };
+
+  auto add = ^(int a, int b, int c)
+    {
+      return a + b + c;
+    };
+
+  void curry() {
+    Curry<__decltype(add)> c = Curry<__decltype(add)>(add);
+    auto t = c(1)(10)(100);
+  }
+}