[llvm-bugs] [Bug 47941] New: "this requires expression will only be checked for syntactic validity" suggests bad fixit, is not emitted on equally dangerous code

via llvm-bugs llvm-bugs at lists.llvm.org
Wed Oct 21 21:34:25 PDT 2020


https://bugs.llvm.org/show_bug.cgi?id=47941

            Bug ID: 47941
           Summary: "this requires expression will only be checked for
                    syntactic validity" suggests bad fixit, is not emitted
                    on equally dangerous code
           Product: clang
           Version: unspecified
          Hardware: All
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: -New Bugs
          Assignee: unassignedclangbugs at nondot.org
          Reporter: arthur.j.odwyer at gmail.com
                CC: htmldeveloper at gmail.com, llvm-bugs at lists.llvm.org,
                    neeilans at live.com, richard-llvm at metafoo.co.uk

// https://godbolt.org/z/hhWdzd

template<class T>
concept Foo = requires {
    { requires { sizeof(T)==0; } };
};
static_assert(Foo<int>);

template<class T>
concept Bar = requires {
    sizeof(T)==0;
};
static_assert(Bar<int>);

template<class T>
concept Baz = requires {
    requires requires { sizeof(T)==0; };
};
static_assert(Baz<int>);


===
These are all correct C++20 behavior, but it's surprising that the
user-programmer can end up here by the usual "add/remove braces until the
compiler stops complaining" approach. Start with

    template<class T>
    concept Foo = requires {
        requires { sizeof(T)==0 };
    };

Clang complains:
<source>:3:28: error: expected ';' at end of requirement
    requires { sizeof(T)==0 };
                           ^
                           ;
<source>:3:5: warning: this requires expression will only be checked for
syntactic validity; did you intend to place it in a nested requirement? (add
another 'requires' before the expression) [-Wrequires-expression]
    requires { sizeof(T)==0 };
    ^
    requires

That is, Clang is suggesting:
    template<class T>
    concept Foo = requires {
        requires requires { sizeof(T)==0; };
    };
(which, to be clear, ALSO does not do what the user intended!)

Or, we can throw braces around the whole thing instead, and Clang will be
equally satisfied:
    template<class T>
    concept Foo = requires {
        { requires { sizeof(T)==0; } };
    };

Or, we can "cancel out" the two `requires requires` Clang suggested, and Clang
will be equally satisfied:
    template<class T>
    concept Foo = requires {
        sizeof(T)==0;
    };

Basically, I think Clang should continue to complain about all of these. The
only way to shut it up should be the universal signal, "redundant parentheses
around the condition."

    template<class T>
    concept Foo = requires {
        ((sizeof(T)==0));              // OK, I guess
        (requires { sizeof(T)==0; });  // OK, I guess
    };

The current diagnostics seem to be in a sour spot of moral hazard, where Clang
seems to be TRYING to help the user-programmer, but actually ignores a lot of
equally dangerous alternatives.

Is Clang clever enough to detect when the condition is guaranteed to be a
constant-expression for any T? e.g. sizeof(T)==0 is a constant-expression
regardless of T, because sizeof(T) is integral. When it's a constant
expression, I think the likelihood is high that the programmer intended to test
truthiness, not well-formedness.

Also notice that sizeof(T)==0 doesn't depend on any
requires-expression-parameters; that's an obvious difference between it and
e.g. `requires(T t) { sizeof(T)==t; }` (which arguably is clear enough in its
intent to test well-formedness instead of truthiness).

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20201022/e0edd90e/attachment.html>


More information about the llvm-bugs mailing list