Two minor, related fixes for template instantiation with blocks:

- 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>.

llvm-svn: 151372
This commit is contained in:
Douglas Gregor 2012-02-24 17:41:38 +00:00
parent dd5a59baed
commit 3a08c1cd3b
3 changed files with 23 additions and 5 deletions

View 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) {}

View 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

View 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>();
}