This is an archive of the discontinued LLVM Phabricator instance.

Check if MemberExpr arguments are type-dependent.
Needs ReviewPublic

Authored by mattd on Nov 28 2017, 9:26 AM.

Details

Summary

Fixes: PR28290

When checking an argument list, arguments from the templated class instance, were
returning 'is dependent' based on the 'this' pointer. In that case, arguments were
being marked dependent, and name lookup was delayed until template instantiation. This
had the side-effect of -fdelayed-template-parsing in certain cases
(attached test case), when that should not have been the case, especially
since that flag was never passed.

According to the standard the referenced member's type needs
to be checked:

[temp.dep.expr]p5:
A class member access expression (5.2.5) is type-dependent if the expression
refers to a member of the current instantiation and the type of the referenced
member is dependent, or the class member access expression refers to a member
of an unknown specialization.

This change decides if the argument belongs to a MemberExpr. If so, then the
type of the expression is checked if it is dependent or not.

Diff Detail

Event Timeline

mattd created this revision.Nov 28 2017, 9:26 AM

Hi, thanks for working on this!
Why don't we just set the TypeDependent bit to false when building the underlying MemberExpr here? Based on the section of the standard you quoted that node shouldn't be considered type-dependent, but it is by clang. I think this patch is just hiding that underlying problem by fishing out the real type-dependence after constructing the MemberExpr when really that information should be included in the MemberExpr to begin with.
Thanks,
Erik

mattd added a comment.Dec 2 2017, 10:00 PM

Thanks for the comments Eli! I agree, it makes sense to flag certain expressions to be type dependent at the earliest time of compilation. Clang already does this, as the Value/Type dependence is established upon Expr construction from MemberExpr construction.

As we have discussed, in the case of MemberExpr, Clang bases dependence on the 'this' pointer, which can be seen in the MemberExpr constructor. And from the attached test case, this is decision is not correct. From what we noted, member access expressions can base their dependence on the type of the member.

However, after trying to propagate this change sooner rather than later (in the MemberExpr ctor), I realized that I might have been changing language semantics. One thing, in particular, is how we handle address-of expressions. Clang predicates them, internally, on type-dependence. From that perspective, we will never try to bind a address-of expression within a template definition, if the address-of is for a member variable. The bind will only occur during template instantiation. Another case we have to be aware of are MemberExpr where the member is a CXXMethodExpr, which would be dependent given the implicit 'this' parameter; that's correct, but I don't want to break that either.

The part which seems to be throwing you off is "or the class member access expression refers to a member of an unknown specialization". A "member of an unknown specialization" is defined in [temp.dep.type] in the standard.