[PATCH] D80977: Diagnose cases where the name of a class member is used within a class definition before the member name is declared.
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.
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.
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.
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: