This is an archive of the discontinued LLVM Phabricator instance.

[Sema]Select correct lexical context during template instantiate
ClosedPublic

Authored by HerrCai0907 on Apr 22 2023, 10:42 PM.

Details

Summary

This patch wants to fix inline friend decl like

template <class F1> int foo(F1 X);
template <int A1> struct A {
  template <class F1> friend int foo(F1 X) { return A1; }
};

template struct A<1>;
int a = foo(1.0);

Diff Detail

Event Timeline

HerrCai0907 created this revision.Apr 22 2023, 10:42 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 22 2023, 10:42 PM
HerrCai0907 requested review of this revision.Apr 22 2023, 10:42 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 22 2023, 10:42 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript

fix assert failed

clang/lib/Sema/SemaTemplateDeduction.cpp
3597

I was originally REALLY suspicious about this function call here (and the setup with the out parameter/2nd variable here). but it seems that the 'true' argument (which, needs a /*ParamName */ comment) is specifically designed for this situation.

3598

So in what case would the currently-instantiated definition NOT also be a friend? I would think this last condition should be able to be an assert instead.

3601

I THINK this should just be:
Owner = FD->getLexicalDeclContext() here.

HerrCai0907 added inline comments.Apr 24 2023, 4:04 PM
clang/lib/Sema/SemaTemplateDeduction.cpp
3598

Last condition cannot be an assert, define and declare in difference place is common case, what we need to identifier in here is inlined friend define.

3601

The old Owner is FunctionTemplate->getLexicalDeclContext(). So I think we should use same level owner.

add comment and more test

erichkeane added inline comments.Apr 25 2023, 6:09 AM
clang/lib/Sema/SemaTemplateDeduction.cpp
3598

Can you be more clear here? WHEN can a definition and declaration NOT have the same friend object kind? THAT is probably incorrect a bug.

3601

Its not a question of "SameLevel", its that it was the accessible one based on what was around. IN this case, we have a 'better' alternative, which is the FunctionDecl.

HerrCai0907 added inline comments.Apr 25 2023, 2:18 PM
clang/lib/Sema/SemaTemplateDeduction.cpp
3598

Sorry I cannot get the point.
Here I have 3 conditions:

  1. FD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None

FD(declaration) is not friend object.

  1. FD->isDefined(FDFriend, true)

get FDFriend(definition) from FD(declaration).

  1. FDFriend->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None)

FDFriend(definition) is friend object.

matching those 3 condition and then we can say FDFriend is a inline friend like

template <class F1> int foo(F1 X); // FD
template <int A1> struct A {
template <class F1> friend int foo(F1 X) { return A1; } // FDFriend
};

change LexicalDeclContext

erichkeane added inline comments.Apr 26 2023, 7:27 AM
clang/lib/Sema/SemaTemplateDeduction.cpp
3598

Ok, my question is: WHEN is #3 "false" but #1 and #2 are "true"? It should not be possible for #1 to be "true" but #3 to be "false", as far as I know.

tahonermann added inline comments.
clang/lib/Sema/SemaTemplateDeduction.cpp
3598

It looks like getFriendObjectKind() returns a declaration specific value such that, for the example given, it returns FOK_None for the first declaration and FOK_Declared for the friend definition. (I haven't tested that, but that is what my brief reading of the code suggests).

erichkeane accepted this revision.Apr 26 2023, 8:14 AM
erichkeane added inline comments.
clang/lib/Sema/SemaTemplateDeduction.cpp
3598

Ah, right! thanks for that Tom! Yeah, its just that the 1st declaration is NOT a friend, I had these reversed in my head so was very confused. OK, thanks!

This revision is now accepted and ready to land.Apr 26 2023, 8:14 AM
This revision was landed with ongoing or failed builds.Apr 26 2023, 3:30 PM
This revision was automatically updated to reflect the committed changes.