Bug 52869 - [DR 1207] "this" not being allowed in noexcept clauses
Summary: [DR 1207] "this" not being allowed in noexcept clauses
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.7.0
: P3 normal
Target Milestone: ---
Assignee: Marek Polacek
URL:
Keywords: rejects-valid
: 78301 (view as bug list)
Depends on:
Blocks:
 
Reported: 2012-04-04 15:46 UTC by Dave Abrahams
Modified: 2019-06-22 15:27 UTC (History)
6 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2018-08-31 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dave Abrahams 2012-04-04 15:46:47 UTC
Given the following, GCC says: "error: invalid use of 'this' at top level"
However, according to [expr.prim.general]/3 'this'
should be valid in the exception-specification as it comes after the
member function's optional cv-qualifier-seq.

  #define RETURNS(...) noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__)  { return (__VA_ARGS__); } 

  struct mul_ {
      int operator()() const { return 1; }

      template <typename A>
      A operator()(A const & a) const noexcept(A(std::move(a))) { return a; }

      template <typename A, typename B, typename... C>
      auto operator()(A const & a, B const & b, C const &... c) const
          RETURNS((*this)(a * b, c...))
  };
Comment 1 htfy96 2015-06-07 08:04:40 UTC
#include <iostream>
using namespace std;
class A
{
    public:
    void g() noexcept(false)  {}
    void f() noexcept( noexcept( g() )) {};
};

A a;
int main()
{
    cout<<noexcept(a.f())<<endl;
    return 0;
}

This is another testcase.
Comment 2 David Stone 2017-08-24 23:02:38 UTC
Simpler test case:

struct S {
    void f() noexcept(noexcept(this)) {}
};

int main() {}



Updated standard reference stating that this should be valid: http://eel.is/c++draft/expr.prim.this#2
Comment 3 Vittorio Romeo 2017-09-16 20:58:50 UTC
Any news on this? It is making writing noexcept specifications very hard since 2012...
Comment 4 Jonathan Wakely 2017-09-17 23:05:55 UTC
*** Bug 78301 has been marked as a duplicate of this bug. ***
Comment 5 Jonathan Wakely 2017-09-17 23:06:08 UTC
Testcase for both problems:

struct S {
    void f() { }
    void g() noexcept(noexcept(f())) { }
    void h() noexcept(noexcept(this->f())) { }
};

ne.cc:3:34: error: cannot call member function ‘void S::f()’ without object
     void g() noexcept(noexcept(f())) { }
                                  ^
ne.cc:4:32: error: invalid use of ‘this’ at top level
     void h() noexcept(noexcept(this->f())) { }
                                ^~~~
Comment 6 denin 2018-07-29 23:57:01 UTC
Reproduced in 8.1.1:

$ cat nyan.cpp 
struct Nyan {
	constexpr Nyan &operator++() noexcept { return *this; }
	constexpr void omg() noexcept(noexcept(++*this)) {}
};

int main() {}

$ g++ -Wall -Wextra nyan.cpp 
nyan.cpp:3:44: error: invalid use of ‘this’ at top level
  constexpr void omg() noexcept(noexcept(++*this)) {}
                                            ^~~~
$ clang++ nyan.cpp 

$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/8.1.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib --disable-werror --enable-checking=release --enable-default-pie --enable-default-ssp
Thread model: posix
gcc version 8.1.1 20180531 (GCC) 

$ uname -a
Linux home 4.17.10-1-ARCH #1 SMP PREEMPT Wed Jul 25 11:23:00 UTC 2018 x86_64 GNU/Linux
Comment 7 Neha Gowda 2018-09-04 12:52:24 UTC
cat test.cpp

==========================================================================
#define _NOEXCEPT_OP(x) noexcept(x)

template<class _Ty> inline
        bool _Swap_adl(_Ty& _Left, _Ty& _Right)
        {       
        return (true);
        }

template<class _Ty1,
        class _Ty2>
        struct pair
        {       
        typedef pair<_Ty1, _Ty2> _Myt;
        typedef _Ty1 first_type;
        typedef _Ty2 second_type;

        void swap(_Myt& _Right)
                _NOEXCEPT_OP(_NOEXCEPT_OP(_Swap_adl(this->first, _Right.first))
                        && _NOEXCEPT_OP(_Swap_adl(this->second, _Right.second)))

                {       
                if (this != &_Right)
                        {       // different, worth swapping
                        _Swap_adl(first, _Right.first);
                        _Swap_adl(second, _Right.second);
                        }
                }
        _Ty1 first;     
        _Ty2 second;    
        };
==========================================================================
g++ test.cpp -c

test.cpp:18:39: error: invalid use of ‘this’ at top level
test.cpp:19:30: error: invalid use of ‘this’ at top level

Same issue with the current upstream sources as well.
Please let me know if there is any patch or workaround to fix the issue.

Else please let me know how to fix this issue in GCC.

Thanks
Comment 8 Umesh Kalappa 2018-11-12 11:37:15 UTC
the following patch fix all the reported cases and tested with latest trunk and 8.1 source i.e 

Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c     (revision 266026)
+++ gcc/cp/parser.c     (working copy)
@@ -24615,6 +24615,8 @@
     {
       tree expr;
       cp_lexer_consume_token (parser->lexer);
+
+      inject_this_parameter (current_class_type, TYPE_UNQUALIFIED);

       if (cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN)
        {

ok to commit ?
Comment 9 Jonathan Wakely 2018-11-12 12:32:00 UTC
Please send the patch to gcc-patches@gcc.gnu.org for review.
Comment 10 Jason Merrill 2018-11-16 21:55:31 UTC
Author: jason
Date: Fri Nov 16 21:55:00 2018
New Revision: 266224

URL: https://gcc.gnu.org/viewcvs?rev=266224&root=gcc&view=rev
Log:
	PR c++/52869

	DR 1207
	* parser.c (cp_parser_noexcept_specification_opt): Call
	inject_this_parameter.

Added:
    trunk/gcc/testsuite/g++.dg/DRs/dr1207-1.C
    trunk/gcc/testsuite/g++.dg/DRs/dr1207-2.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/parser.c
Comment 11 Umesh Kalappa 2018-11-17 04:20:39 UTC
Thank you Jason and Marek for all your support .
Comment 12 Jonathan Wakely 2018-12-05 20:49:21 UTC
The exception specification seems to be processed too early, before the other class members are in scope. This slight variation of comment 5 still fails on trunk:

struct S {
    void g() noexcept(noexcept(f())) { }
    void h() noexcept(noexcept(this->f())) { }
    void f() { }
};

2869.cc:2:32: error: 'f' was not declared in this scope
    2 |     void g() noexcept(noexcept(f())) { }
      |                                ^
52869.cc:3:38: error: 'struct S' has no member named 'f'
    3 |     void h() noexcept(noexcept(this->f())) { }
      |                                      ^
Comment 13 Marek Polacek 2018-12-10 20:13:53 UTC
Thanks Jon, I'll poke at it some more.
Comment 14 Marek Polacek 2018-12-12 20:14:11 UTC
This is actually another problem, one that is tracked in PR86476.
Comment 15 denin 2018-12-12 22:06:13 UTC
(In reply to Marek Polacek from comment #14)
> This is actually another problem, one that is tracked in PR86476.

So context closure is unduly greedy: members defined above are available while those from below are not? Funny indeed.
Comment 16 denin 2018-12-12 22:41:25 UTC
(In reply to Marek Polacek from comment #14)
> This is actually another problem, one that is tracked in PR86476.

Hmm.

$ cat wat.cpp 
struct Omg {
	void f() {}
	void g() noexcept(noexcept(f())) {}
};
$ g++ wat.cpp 
wat.cpp:3:31: error: cannot call member function ‘void Omg::f()’ without object
  void g() noexcept(noexcept(f())) {}
                               ^
$ g++ -v |& grep version
gcc version 8.2.1 20181127 (GCC)
Comment 17 Marek Polacek 2018-12-12 22:49:26 UTC
(In reply to denin from comment #16)
> (In reply to Marek Polacek from comment #14)
> > This is actually another problem, one that is tracked in PR86476.
> 
> Hmm.
> 
> $ cat wat.cpp 
> struct Omg {
> 	void f() {}
> 	void g() noexcept(noexcept(f())) {}
> };
> $ g++ wat.cpp 
> wat.cpp:3:31: error: cannot call member function ‘void Omg::f()’ without
> object
>   void g() noexcept(noexcept(f())) {}
>                                ^
> $ g++ -v |& grep version
> gcc version 8.2.1 20181127 (GCC)

This is what the commit in Comment 10 fixed; it has only been fixed for GCC 9.
Comment 18 Marek Polacek 2019-06-22 15:15:01 UTC
Author: mpolacek
Date: Sat Jun 22 15:14:30 2019
New Revision: 272586

URL: https://gcc.gnu.org/viewcvs?rev=272586&root=gcc&view=rev
Log:
	PR c++/86476 - noexcept-specifier is a complete-class context.
	PR c++/52869
	* cp-tree.def (DEFAULT_ARG): Update commentary.
	* cp-tree.h (UNPARSED_NOEXCEPT_SPEC_P):	New macro.
	(tree_default_arg): Use tree_base instead of tree_common.
	(do_push_parm_decls, maybe_check_overriding_exception_spec): Declare.
	* decl.c (do_push_parm_decls): New function, broken out of...
	(store_parm_decls): ...here.  Call it.
	* except.c (nothrow_spec_p): Accept DEFAULT_ARG in the assert.
	* parser.c (cp_parser_noexcept_specification_opt,
	cp_parser_late_noexcept_specifier, noexcept_override_late_checks):
	Forward-declare.
	(unparsed_noexcepts): New macro.
	(push_unparsed_function_queues): Update initializer.
	(cp_parser_direct_declarator): Pass FRIEND_P to
	cp_parser_exception_specification_opt.
	(inject_parm_decls): New.
	(pop_injected_parms): New.
	(cp_parser_class_specifier_1): Implement delayed parsing of
	noexcept-specifiers.
	(cp_parser_save_noexcept): New.
	(cp_parser_late_noexcept_specifier): New.
	(noexcept_override_late_checks): New.
	(cp_parser_noexcept_specification_opt): Add FRIEND_P parameter.  Call
	cp_parser_save_noexcept instead of the normal processing if needed.
	(cp_parser_exception_specification_opt): Add FRIEND_P parameter and
	pass it to cp_parser_noexcept_specification_opt.
	(cp_parser_save_member_function_body): Fix comment.
	(cp_parser_save_default_args): Maybe save the noexcept-specifier to
	post process.
	(cp_parser_transaction): Update call to
	cp_parser_noexcept_specification_opt.
	(cp_parser_transaction_expression): Likewise.
	* parser.h (cp_unparsed_functions_entry): Add new field to carry
	a noexcept-specifier.
	* pt.c (dependent_type_p_r): Handle unparsed noexcept expression.
	* search.c (maybe_check_overriding_exception_spec): New function, broken
	out of...
	(check_final_overrider): ...here.  Call
	maybe_check_overriding_exception_spec.
	* tree.c (canonical_eh_spec): Handle UNPARSED_NOEXCEPT_SPEC_P.
	(cp_tree_equal): Handle DEFAULT_ARG.

	* g++.dg/cpp0x/noexcept45.C: New test.
	* g++.dg/cpp0x/noexcept46.C: New test.
	* g++.dg/cpp0x/noexcept47.C: New test.
	* g++.dg/cpp0x/noexcept48.C: New test.
	* g++.dg/cpp0x/noexcept49.C: New test.
	* g++.dg/cpp0x/noexcept50.C: New test.
	* g++.dg/cpp0x/noexcept51.C: New test.
	* g++.dg/cpp0x/noexcept52.C: New test.
	* g++.dg/cpp0x/noexcept53.C: New test.
	* g++.dg/eh/shadow1.C: Adjust dg-error.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/noexcept45.C
    trunk/gcc/testsuite/g++.dg/cpp0x/noexcept46.C
    trunk/gcc/testsuite/g++.dg/cpp0x/noexcept47.C
    trunk/gcc/testsuite/g++.dg/cpp0x/noexcept48.C
    trunk/gcc/testsuite/g++.dg/cpp0x/noexcept49.C
    trunk/gcc/testsuite/g++.dg/cpp0x/noexcept50.C
    trunk/gcc/testsuite/g++.dg/cpp0x/noexcept51.C
    trunk/gcc/testsuite/g++.dg/cpp0x/noexcept52.C
    trunk/gcc/testsuite/g++.dg/cpp0x/noexcept53.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/cp-tree.def
    trunk/gcc/cp/cp-tree.h
    trunk/gcc/cp/decl.c
    trunk/gcc/cp/except.c
    trunk/gcc/cp/parser.c
    trunk/gcc/cp/parser.h
    trunk/gcc/cp/pt.c
    trunk/gcc/cp/search.c
    trunk/gcc/cp/tree.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/g++.dg/eh/shadow1.C
Comment 19 Marek Polacek 2019-06-22 15:27:31 UTC
Fixed.