Bug 87699 - Implement CWG 1512
Summary: Implement CWG 1512
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 9.0
: P3 normal
Target Milestone: ---
Assignee: Marek Polacek
URL:
Keywords: accepts-invalid
: 86228 86579 94563 (view as bug list)
Depends on:
Blocks: 94564
  Show dependency treegraph
 
Reported: 2018-10-23 02:59 UTC by Tiago Macarios
Modified: 2021-07-28 03:09 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2018-10-23 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tiago Macarios 2018-10-23 02:59:17 UTC
As per http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3478.html
the below should not compile.

https://godbolt.org/z/mOpxau

bool foo(int* bar)
{
    return bar > 0;
}
Comment 1 Jonathan Wakely 2018-10-23 09:15:48 UTC
Confirmed.

Martin, I thought this was a dup of an existing bug that you'd filed or commented on, but can't find anything. Am I imagining it?
Comment 2 Martin Sebor 2018-10-23 17:22:29 UTC
I raised bug 81453 for this against the C front end, but only to move the warning GCC issues with -Wextra to -Wall.
Comment 3 Marek Polacek 2019-05-25 16:37:00 UTC
The warning is in place and triggers with -Wextra:

            warning (OPT_Wextra,
                     "ordered comparison of pointer with integer zero");

I guess we should make it a permerror.
Comment 4 Marek Polacek 2020-04-13 00:28:38 UTC
Mine, for GCC 11.
Comment 5 Marek Polacek 2020-04-13 00:29:00 UTC
*** Bug 94563 has been marked as a duplicate of this bug. ***
Comment 6 Marek Polacek 2020-04-13 00:30:25 UTC
See Daniel's testcase for why this is more important than it might seem:

template<class T, decltype((((T*) 0) < nullptr), true) = false>
bool test(T*)
{
  return true;
}

int main()
{
  test((int*)(nullptr));
}
Comment 7 CVS Commits 2020-05-18 20:27:01 UTC
The master branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>:

https://gcc.gnu.org/g:ae8ed736addb2b005d54c0b3191ac599a04ec170

commit r11-467-gae8ed736addb2b005d54c0b3191ac599a04ec170
Author: Marek Polacek <polacek@redhat.com>
Date:   Wed May 13 15:52:42 2020 -0400

    c++: Implement DR 1512, Pointer comparison vs qual convs [PR87699]
    
    This patch resolves DR 1512 (and, by turn, DR 583).  This entails:
    
    1) Relational pointer comparisons against null pointer constants have
       been made ill-formed:
    
       void f(char *p) {
          if (p > 0)
            // ...
       }
    
       was always invalid in C but was -- accidentally -- allowed in C++.
    
    2) This was ill-formed:
    
       bool foo(int** x, const int** y) {
         return x < y;
       }
    
       because 'int**' couldn't be converted to 'const int**'.  This was
       fixed by re-defining a generic composite pointer type.  The composite
       type of these two pointers will be 'const int *const *', to which
       both pointers can be converted.
    
    3) The overload descriptions for built-in operators were adjusted,
       because objects of type std::nullptr_t cannot be used with relational
       operators any more.
    
    I fixed 1) by adjusting cp_build_binary_op; we already had a warning
    for it so made it a hard error now.
    
    Then 2) required tweaking composite_pointer_type_r.  [expr.type] defines
    the composite pointer type by using the "cv-combined type."  We didn't
    implement the [conv.qual]/3.3 part; previously the composite type of
    'int**' and 'const int**' was 'const int**', so this didn't compile:
    
        void f(const int **p, int **q) {
          true ? p : q;
        }
    
    I wrote a more extensive test for this which uses decltype and some
    template magic to check the composite type, see composite-ptr-type.C.
    We still don't handle everything that [expr.type] requires us to,
    but it's pretty close.
    
    And finally 3) was handled in add_builtin_candidate.  Turned out we
    weren't creating built-in operator candidates when the type was
    std::nullptr_t at all.  We should, for == and !=.  Tested in builtin4.C.
    In passing, I'm fixing some of the comments too.
    
            DR 1512
            PR c++/87699
            * call.c (add_builtin_candidate) <case EQ_EXPR>: Create candidate
            operator functions when type is std::nullptr_t for ==/!=.
            * typeck.c (composite_pointer_type_r): Add bool a * parameter.  Use it
            to maybe add "const" to the pointer type.
            (composite_pointer_type): Update the call to composite_pointer_type_r.
            (cp_build_binary_op): Turn two warning_at into error_at.  Print the
            types.
    
            * g++.dg/cpp0x/constexpr-array-ptr10.C: Change dg-warning to dg-error
            and adjust the expected messages in dg-error.
            * g++.dg/expr/composite-ptr-type.C: New test.
            * g++.dg/expr/ptr-comp1.C: New test.
            * g++.dg/expr/ptr-comp2.C: New test.
            * g++.dg/expr/ptr-comp3.C: New test.
            * g++.dg/overload/builtin4.C: New test.
            * g++.dg/warn/Wextra-3.C: Change dg-warning to dg-error.
Comment 8 Marek Polacek 2020-05-18 20:32:10 UTC
Implemented in GCC 11.
Comment 9 Jonathan Wakely 2021-03-21 23:34:02 UTC
(In reply to CVS Commits from comment #7)
>     3) The overload descriptions for built-in operators were adjusted,
>        because objects of type std::nullptr_t cannot be used with relational
>        operators any more.

This apparently wasn't completely done, see PR 99701.
Comment 10 Andrew Pinski 2021-07-22 23:48:04 UTC
*** Bug 86579 has been marked as a duplicate of this bug. ***
Comment 11 Andrew Pinski 2021-07-27 22:19:27 UTC
*** Bug 86228 has been marked as a duplicate of this bug. ***