]> granicus.if.org Git - clang/commitdiff
Two minor, related fixes for template instantiation with blocks:
authorDouglas Gregor <dgregor@apple.com>
Fri, 24 Feb 2012 17:41:38 +0000 (17:41 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 24 Feb 2012 17:41:38 +0000 (17:41 +0000)
  - Make sure that the block expression is instantiation-dependent if the
    block is in a dependent context
  - Make sure that the C++ 'this' expression gets captured even if we
  don't rebuild the AST node during template instantiation. This would
  also have manifested as a bug for lambdas.

Fixes <rdar://problem/10832617>.

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

include/clang/AST/Expr.h
lib/Sema/TreeTransform.h
test/CodeGenCXX/blocks.cpp

index b9c3220c0b85a6f3cb4f5dacadc4a1404ea291e9..741b47e560d1b2a1f778945131c256e58730a852 100644 (file)
@@ -4220,9 +4220,8 @@ protected:
 public:
   BlockExpr(BlockDecl *BD, QualType ty)
     : Expr(BlockExprClass, ty, VK_RValue, OK_Ordinary,
-           ty->isDependentType(), false,
-           // FIXME: Check for instantiate-dependence in the statement?
-           ty->isInstantiationDependentType(),
+           ty->isDependentType(), ty->isDependentType(),
+           ty->isInstantiationDependentType() || BD->isDependentContext(),
            false),
       TheBlock(BD) {}
 
index f0b5f4e2419fa2cdae8c136bf67521e757513546..11f03fc133accc26b5e50b79e63aa506ea93fa3c 100644 (file)
@@ -7038,9 +7038,12 @@ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
     T = getSema().Context.getPointerType(
       getSema().Context.getRecordType(cast<CXXRecordDecl>(DC)));
 
-  if (!getDerived().AlwaysRebuild() && T == E->getType())
+  if (!getDerived().AlwaysRebuild() && T == E->getType()) {
+    // Make sure that we capture 'this'.
+    getSema().CheckCXXThisCapture(E->getLocStart());
     return SemaRef.Owned(E);
-
+  }
+  
   return getDerived().RebuildCXXThisExpr(E->getLocStart(), T, E->isImplicit());
 }
 
@@ -8539,6 +8542,7 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
                                                  oldCapture));
       assert(blockScope->CaptureMap.count(newCapture));
     }
+    assert(oldBlock->capturesCXXThis() == blockScope->isCXXThisCaptured());
   }
 #endif
 
index 3d7fcfddbe275161ba6b32a353d374cde92898b4..eb544787da7e2f87813d6b6aa6c5844a5af76be7 100644 (file)
@@ -211,3 +211,18 @@ namespace test7 {
     return ^{ return *p; }();
   }
 }
+
+namespace test8 {
+  // <rdar://problem/10832617>: failure to capture this after skipping rebuild
+  // of the 'this' pointer.
+  struct X {
+    int x;
+
+    template<typename T>
+    int foo() {
+      return ^ { return x; }();
+    }
+  };
+
+  template int X::foo<int>();
+}