[PATCH] D80977: Diagnose cases where the name of a class member is used within a class definition before the member name is declared.

2020-12-10 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith updated this revision to Diff 311085.
rsmith added a comment.

Rebase and fix test failure.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80977/new/

https://reviews.llvm.org/D80977

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Lookup.h
  clang/include/clang/Sema/Scope.h
  clang/include/clang/Sema/SemaInternal.h
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Sema/Scope.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaLookup.cpp
  clang/lib/Sema/SemaTemplate.cpp
  clang/test/CXX/basic/basic.scope/basic.scope.class/p2.cpp
  clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p4.cpp
  clang/test/CXX/drs/dr2xx.cpp
  clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
  clang/test/Parser/cxx-ambig-init-templ.cpp
  clang/test/Parser/cxx0x-override-control-keywords.cpp
  clang/test/SemaTemplate/alias-templates.cpp
  clang/test/SemaTemplate/deduction-crash.cpp
  clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
  clang/test/SemaTemplate/ms-delayed-default-template-args.cpp

Index: clang/test/SemaTemplate/ms-delayed-default-template-args.cpp
===
--- clang/test/SemaTemplate/ms-delayed-default-template-args.cpp
+++ clang/test/SemaTemplate/ms-delayed-default-template-args.cpp
@@ -24,10 +24,11 @@
 namespace test_inner_class_template {
 struct Outer {
   template  // expected-warning {{using the undeclared type 'Baz' as a default template argument is a Microsoft extension}}
+  // expected-warning@-1 {{not yet been declared}}
   struct Foo {
 static_assert(sizeof(T) == 4, "should get int, not double");
   };
-  typedef int Baz;
+  typedef int Baz; // expected-note {{declared here}}
 };
 typedef double Baz;
 template struct Outer::Foo<>;
Index: clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
===
--- clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
+++ clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
@@ -64,16 +64,18 @@
 }
 
 namespace core_19754_example {
-  template T declval() noexcept;
+namespace N {
+template 
+T declval() noexcept;
 
-  template()))>
-  struct is_movable { static const bool value = true; };
+template ()))>
+struct is_movable { static const bool value = true; };
 
-  template
-  struct wrap {
-T val;
-void irrelevant(wrap ) noexcept(is_movable::value);
-  };
+template 
+struct wrap {
+  T val;
+  void irrelevant(wrap ) noexcept(is_movable::value);
+};
 
   template
   struct base {
@@ -93,13 +95,14 @@
   };
 
   struct types {
- typedef base base;
- typedef type1 type1;
- typedef type2 type2;
+typedef N::base base;
+typedef N::type1 type1;
+typedef N::type2 type2;
   };
 
   base val = base();
-}
+  } // namespace N
+  } // namespace core_19754_example
 
 namespace pr9485 {
   template  void f1(T) throw(typename T::exception); // expected-note {{candidate}}
Index: clang/test/SemaTemplate/deduction-crash.cpp
===
--- clang/test/SemaTemplate/deduction-crash.cpp
+++ clang/test/SemaTemplate/deduction-crash.cpp
@@ -19,7 +19,7 @@
 template
 struct state_machine
 {
-  typedef aaa::ae aaa;
+  typedef ::aaa::ae aaa;
   int start()
   {
 ant(0);
Index: clang/test/SemaTemplate/alias-templates.cpp
===
--- clang/test/SemaTemplate/alias-templates.cpp
+++ clang/test/SemaTemplate/alias-templates.cpp
@@ -41,7 +41,7 @@
   template struct thing {
 typedef T inner;
 typedef ptr inner_ptr;
-typedef traits> traits_type;
+typedef X::traits> traits_type;
 
 template using rebind = thing;
 
Index: clang/test/Parser/cxx0x-override-control-keywords.cpp
===
--- clang/test/Parser/cxx0x-override-control-keywords.cpp
+++ clang/test/Parser/cxx0x-override-control-keywords.cpp
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
-// expected-no-diagnostics
 
 struct Base {
   virtual void override();
@@ -14,9 +13,10 @@
   virtual void override() override { } 
 };
 
-struct override;
+struct override; // expected-note {{use a qualified name to refer to member of the global namespace}}
 struct Base2 {
-  virtual override override(int override);
+  virtual override// expected-warning {{not yet been declared}}
+  override(int override); // expected-note {{here}}
 };
 
 struct A : Base2 {
Index: clang/test/Parser/cxx-ambig-init-templ.cpp
===
--- clang/test/Parser/cxx-ambig-init-templ.cpp
+++ clang/test/Parser/cxx-ambig-init-templ.cpp
@@ 

[PATCH] D80977: Diagnose cases where the name of a class member is used within a class definition before the member name is declared.

2020-06-19 Thread Eli Friedman via Phabricator via cfe-commits
efriedma added a comment.

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




Comment at: clang/lib/Sema/SemaDecl.cpp:1543
+// in class 'C', where we look up 'f' to determine if we're declaring a
+// constructor.
+  } else if (D->isInIdentifierNamespace(Lookup.FirstIDNS)) {

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.



Comment at: clang/test/CXX/basic/basic.scope/basic.scope.class/p2.cpp:154
+
+  static int a = unique_member_function_name(); // expected-error {{undeclared 
identifier}}
+  static int unique_member_function_name();

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


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80977/new/

https://reviews.llvm.org/D80977



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D80977: Diagnose cases where the name of a class member is used within a class definition before the member name is declared.

2020-06-11 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith added a comment.

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.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80977/new/

https://reviews.llvm.org/D80977



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D80977: Diagnose cases where the name of a class member is used within a class definition before the member name is declared.

2020-06-01 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith created this revision.
rsmith added a reviewer: rnk.
Herald added a project: clang.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D80977

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Lookup.h
  clang/include/clang/Sema/Scope.h
  clang/include/clang/Sema/SemaInternal.h
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Sema/Scope.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaLookup.cpp
  clang/lib/Sema/SemaTemplate.cpp
  clang/test/CXX/basic/basic.scope/basic.scope.class/p2.cpp
  clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p4.cpp
  clang/test/CXX/drs/dr2xx.cpp
  clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
  clang/test/Parser/cxx-ambig-init-templ.cpp
  clang/test/Parser/cxx0x-override-control-keywords.cpp
  clang/test/SemaTemplate/alias-templates.cpp
  clang/test/SemaTemplate/deduction-crash.cpp
  clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
  clang/test/SemaTemplate/ms-delayed-default-template-args.cpp

Index: clang/test/SemaTemplate/ms-delayed-default-template-args.cpp
===
--- clang/test/SemaTemplate/ms-delayed-default-template-args.cpp
+++ clang/test/SemaTemplate/ms-delayed-default-template-args.cpp
@@ -24,10 +24,11 @@
 namespace test_inner_class_template {
 struct Outer {
   template  // expected-warning {{using the undeclared type 'Baz' as a default template argument is a Microsoft extension}}
+  // expected-warning@-1 {{not yet been declared}}
   struct Foo {
 static_assert(sizeof(T) == 4, "should get int, not double");
   };
-  typedef int Baz;
+  typedef int Baz; // expected-note {{declared here}}
 };
 typedef double Baz;
 template struct Outer::Foo<>;
Index: clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
===
--- clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
+++ clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
@@ -64,16 +64,18 @@
 }
 
 namespace core_19754_example {
-  template T declval() noexcept;
+namespace N {
+template 
+T declval() noexcept;
 
-  template()))>
-  struct is_movable { static const bool value = true; };
+template ()))>
+struct is_movable { static const bool value = true; };
 
-  template
-  struct wrap {
-T val;
-void irrelevant(wrap ) noexcept(is_movable::value);
-  };
+template 
+struct wrap {
+  T val;
+  void irrelevant(wrap ) noexcept(is_movable::value);
+};
 
   template
   struct base {
@@ -93,13 +95,14 @@
   };
 
   struct types {
- typedef base base;
- typedef type1 type1;
- typedef type2 type2;
+typedef N::base base;
+typedef N::type1 type1;
+typedef N::type2 type2;
   };
 
   base val = base();
-}
+  } // namespace N
+  } // namespace core_19754_example
 
 namespace pr9485 {
   template  void f1(T) throw(typename T::exception); // expected-note {{candidate}}
Index: clang/test/SemaTemplate/deduction-crash.cpp
===
--- clang/test/SemaTemplate/deduction-crash.cpp
+++ clang/test/SemaTemplate/deduction-crash.cpp
@@ -19,7 +19,7 @@
 template
 struct state_machine
 {
-  typedef aaa::ae aaa;
+  typedef ::aaa::ae aaa;
   int start()
   {
 ant(0);
Index: clang/test/SemaTemplate/alias-templates.cpp
===
--- clang/test/SemaTemplate/alias-templates.cpp
+++ clang/test/SemaTemplate/alias-templates.cpp
@@ -41,7 +41,7 @@
   template struct thing {
 typedef T inner;
 typedef ptr inner_ptr;
-typedef traits> traits_type;
+typedef X::traits> traits_type;
 
 template using rebind = thing;
 
Index: clang/test/Parser/cxx0x-override-control-keywords.cpp
===
--- clang/test/Parser/cxx0x-override-control-keywords.cpp
+++ clang/test/Parser/cxx0x-override-control-keywords.cpp
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
-// expected-no-diagnostics
 
 struct Base {
   virtual void override();
@@ -14,9 +13,10 @@
   virtual void override() override { } 
 };
 
-struct override;
+struct override; // expected-note {{use a qualified name to refer to member of the global namespace}}
 struct Base2 {
-  virtual override override(int override);
+  virtual override// expected-warning {{not yet been declared}}
+  override(int override); // expected-note {{here}}
 };
 
 struct A : Base2 {
Index: