This is an archive of the discontinued LLVM Phabricator instance.

[Sema] Fix an error-on-valid with friends and templates
ClosedPublic

Authored by erik.pilkington on Oct 9 2018, 3:08 PM.

Details

Summary

Clang used to error out on the attached testcase, due to multiple definitions of foo<int>. The problem is that multiple FunctionTemplateDecl::Common pointers are created for the two FunctionTemplateDeclarations foo in the redeclaration chain, each with their own copy of the instantiation of f<int>.

This patch fixes the problem by using the previous function template in a call to FuntionTemplateDecl::getInjectedTemplateArgs() (this was the call that caused the Common pointer to be allocated in the redeclaration). Most of this patch is just boilerplate to get the function template declaration down the stack to where it's needed.

Fixes rdar://44810129

Thanks for taking a look!
Erik

Diff Detail

Repository
rL LLVM

Event Timeline

erik.pilkington created this revision.Oct 9 2018, 3:08 PM
erik.pilkington added inline comments.Oct 9 2018, 3:10 PM
clang/lib/Sema/SemaDecl.cpp
10015 ↗(On Diff #168876)

The problem is here, MergeFunctionDecl() needs the injected template args, but...

10026 ↗(On Diff #168876)

... we don't link the two declarations until here!

The linking does actually happen in this test case, right? Can we just do something when linking them to unify their Common structures?

The linking does actually happen in this test case, right? Can we just do something when linking them to unify their Common structures?

Yep, that would work too I think. We can't properly merge in the general case, because we could have to decide between more than one identical instantiations of different template redecls, but in this case the only ordering problem is with the injected template arguments, which I believe we can merge (by just discarding the new arguments, if a previous redeclaration already has some). It would definitely be less intrusive, but its a more complicated invariant. Do you think that is a better solution? I could go either way.

The linking does actually happen in this test case, right? Can we just do something when linking them to unify their Common structures?

Yep, that would work too I think. We can't properly merge in the general case, because we could have to decide between more than one identical instantiations of different template redecls, but in this case the only ordering problem is with the injected template arguments, which I believe we can merge (by just discarding the new arguments, if a previous redeclaration already has some). It would definitely be less intrusive, but its a more complicated invariant. Do you think that is a better solution? I could go either way.

Well, we're really still in the middle of creating the new declaration, so I'm not too worried about the invariants. And yeah, we can safely discard the new arguments because IIUC this is just a cache.

Merge the common pointers rather than trying to use the previous one. Thanks!

rjmccall accepted this revision.Oct 10 2018, 8:32 AM

LGTM.

This revision is now accepted and ready to land.Oct 10 2018, 8:32 AM
This revision was automatically updated to reflect the committed changes.