This is an archive of the discontinued LLVM Phabricator instance.

Diagnose cases where the name of a class member is used within a class definition before the member name is declared.
Needs ReviewPublic

Authored by rsmith on Jun 1 2020, 10:04 PM.

Details

Reviewers
eli.friedman
Summary

This is ill-formed per [basic.scope.class]p2.

This is done by tracking all unqualified lookups performed within the
scope of a class definition that find nothing within the class, and
checking for conflicting declarations later introduced into the class.

Diff Detail

Event Timeline

rsmith created this revision.Jun 1 2020, 10:04 PM
Herald added a project: Restricted Project. · View Herald TranscriptJun 1 2020, 10:04 PM
rsmith edited reviewers, added: eli.friedman; removed: rnk.Jun 11 2020, 4:35 PM

I'm not entirely happy with this approach; there are lots of places where we perform lookups that are incidental and shouldn't result in an error if we end up looking outside the class, and I'm not sure I've marked them all as "synthetic". That said, I've tested this over a fairly substantial amount of code and all the issues it reported were true positives.

(Partial review; I'll continue reviewing later.)

clang/lib/Sema/SemaDecl.cpp
1543

Not really about this patch, but take given the following example:

typedef int f;
class C { C (f)(); };

It looks like every compiler somehow parses this as an invalid constructor declaration. As far as I can tell, it doesn't conform to the grammar for a constructor, though: parentheses aren't allowed after the parameter-declaration-clause. So it should declare a member function f, whether or not f is a type. Maybe I'm missing something, though.

It doesn't matter for this patch, of course, because you can also write C(f());, which actually depends on whether f is a type.

clang/test/CXX/basic/basic.scope/basic.scope.class/p2.cpp
154

I'm seeing a test failure here with this patch applied.

rsmith updated this revision to Diff 311085.Dec 10 2020, 6:24 PM

Rebase and fix test failure.