This is an archive of the discontinued LLVM Phabricator instance.

Warn if friend function depends on template parameters.
Needs ReviewPublic

Authored by sepavloff on Jan 26 2016, 6:55 AM.
This revision needs review, but there are no reviewers specified.

Details

Reviewers
None
Summary

Declaration of friend function may depend on template parameters,
however it does not become a template function:

template<typename T> class C1 {
  friend void func(T x);
};

It may be not obvious for user, so compiler could emit a warning in
such case. This patch implements appropriate warning, similar to GCC
warning -Wnon-template-friend. The warning is not issued if translation
unit contains a function declaration in appropriate namespace that
can redeclare the friend function in some class instantiation.
For the example above it could be a declaration:

void func(int x);

This change fixes PR23342.

Event Timeline

sepavloff updated this revision to Diff 45988.Jan 26 2016, 6:55 AM
sepavloff retitled this revision from to Warn if friend function depends on template parameters..
sepavloff updated this object.
sepavloff added a subscriber: cfe-commits.

Any feedback?

Thanks,
--Serge

Could someone provide a feedback?

Thanks,
--Serge

Ping.

Thanks,
--Serge

sepavloff updated this revision to Diff 51017.Mar 18 2016, 6:05 AM

Do not emit warning on class methods.

rsmith added a subscriber: rsmith.Mar 18 2016, 6:25 AM

It seems useful to warn on this, but I'm concerned that there are valid code patterns that this will warn about where there is no reasonable way to rewrite the code that would suppress the warning. For instance:

template<typename T> class X {
  friend void process(X<T>);
  // ...
};
void process(X<int>) { /* ... */ }
void process(X<char>) ( /* ... */ }

As an alternative, can we suppress the warning until we see an "almost matching" template declaration in the surrounding scope? For instance:

template<typename T> void process(X<T>) { /* ... */ } // warning, not a friend of X<T>
include/clang/Basic/DiagnosticSemaKinds.td
1276–1278

Maybe just: "to befriend a template specialization, use <>", along with a FixItHint showing where to add the <>.

It would also seem like a good idea to check if there is such a function template declared, and give different diagnostic if not.

sepavloff updated this revision to Diff 52527.Apr 4 2016, 12:45 AM

Updated patch

Added a check for presence of template declaration corresponding to the friend
function. Presence of similar functions but with specializations as argument
types is also checked now.

Made an atempt to make messages more clear to end user, not sure however if
they become better.

sepavloff updated this revision to Diff 56607.May 9 2016, 12:07 PM

Changed implementation of friend function set.

Friend functions declared in template classes are not added to redeclaration chains,
but access to them is needed to make some checks. This change allows using the
set of friend functions not only to emit particular warning but also to serve as a
registry of file-level friend functions.

rsmith added inline comments.May 9 2016, 5:00 PM
include/clang/Basic/DiagnosticSemaKinds.td
1275

template function -> function template

1277–1279

Rather than this long conditional note, how about producing two notes here:

note: declare function outside class template to suppress this warning
note: use '<>' to befriend a template specialization
1280–1281

This note should also point out that you need to declare the function template prior to the class template.

include/clang/Sema/Sema.h
10324

This will produce diagnostics in a nondeterministic order, and you have no need of a set because there can never be any duplicates. Just use a SmallVector?

10324

You're missing serialization code for this for the PCH / preamble case.

10326–10327

friends -> friend
template ones -> function templates

lib/Sema/SemaChecking.cpp
12050

This is a huge amount of complexity and maintenance burden for this check, and it still seems to some important cases wrong. Is there a simpler way we can get a largely-equivalent result? Or maybe we can just unconditionally produce both notes?

12282

FriendsOfTemplates.clear() here?

lib/Sema/SemaDecl.cpp
9158–9163

This should also be conditioned on the function having a dependent type and this declaration not being a definition -- this will add all non-template friends to FriendsOfTemplates, whether they're friends of a class template or not.

sepavloff updated this revision to Diff 63386.Jul 9 2016, 12:23 AM

Updated patch

sepavloff updated this revision to Diff 63387.Jul 9 2016, 12:35 AM

Repared file modes.

sepavloff marked 6 inline comments as done.Jul 9 2016, 1:21 AM
sepavloff added inline comments.
include/clang/Sema/Sema.h
10324

Do we really need it? When compiler is compiling a module containing enclosing class, it must emit these warning, as it does for separate file. The advice it issues is valid in this case also. When compiler compiles code that uses the module, warning is not needed as it must already been issued. So, it looks like serializing this array is not needed.

lib/Sema/SemaChecking.cpp
12050

The visitor class is split into two auxiliary classes. Although amount of code becomes larger, maintainability should be better, as large amount of code is obtained from RecursiveASTVisitor in standard way/ the other is not specific to friend functions.

sepavloff updated this revision to Diff 105853.Jul 10 2017, 8:23 AM

Updated patch

  • Remove changes that are not needed anymore,
  • Function matching is implemented on recursive function instead of TypeVisitor. It support subset of checks, which should be enough for practical use.
  • Added more comments.
sepavloff edited the summary of this revision. (Show Details)Jul 10 2017, 8:24 AM