This is an archive of the discontinued LLVM Phabricator instance.

[Sema] Fix a crash when a BlockExpr appears in a default-member-initializer of a class template
ClosedPublic

Authored by erik.pilkington on Jul 23 2018, 11:43 AM.

Details

Summary

Previously, clang would crash here:

template <class T> struct S {
  int (^p)() = ^{ return 0; };
};
S<int> x;

The problem was that InstantiateClass() was iterating over all the decls(), which included the BlockDecl. The template instantiator doesn't know how to instantiate BlockDecls though, it knows about BlockExprs. This is typically fine because BlockExprs must be the parent of the BlockDecl. To accommodate this, delay instantiating the BlockDecl until we're instantiating the default-member-initializer.

Thanks for taking a look!
Erik

Diff Detail

Repository
rC Clang

Event Timeline

(Forgot to add rdar://41200624)

I honestly don't know why the BlockDecl is in the members list in the first place; that seems wrong, for the same reason that we wouldn't (I assume?) consider a lambda's implicit record to be a member.

I honestly don't know why the BlockDecl is in the members list in the first place; that seems wrong, for the same reason that we wouldn't (I assume?) consider a lambda's implicit record to be a member.

Looks like we do actually treat a lambda's implicit record as a member. This loop is only iterating over decls that are in the pattern decl's context, and I think it makes sense that the BlockDecl is there, right?

rjmccall accepted this revision.Jul 23 2018, 2:53 PM

It makes sense that the BlockDecl's parent DC is the class, although I think it would be even better if we took a page from Swift and make a special DC for initializer expressions. I don't think it makes sense for it to be listed in the DC's list of declarations.

Regardless, it's not something you have to fix. Patch LGTM.

This revision is now accepted and ready to land.Jul 23 2018, 2:53 PM
This revision was automatically updated to reflect the committed changes.