Skip to content

clang evaluates is_constant_evaluated incorrectly with narrowing conversion #142707

Closed as not planned
@efriedma-quic

Description

@efriedma-quic

Consider the following example:

#include <type_traits>
struct X { unsigned u; };
void f(X x);
void g(int a) {
    f({0xFFFFFFFFLL + std::is_constant_evaluated()});
}

The standard says the conversion is narrowing if "the source is a constant expression whose value after integral promotions will fit into the target type". gcc correctly rejects because of this: it treats the expression as a constant expression, then it fails to narrow. clang incorrectly accepts because isCXX11ConstantExpr() doesn't treat the evaluation as a constant context.

We have to be a little careful here... consider the following variant:

#include <type_traits>
struct X { unsigned u; };
void f(X x);
void g(int a) {
    f({0x100000000LL - std::is_constant_evaluated()});
}

clang incorrectly rejects. gcc miscompiles: it checks the narrowing in a constant context, but then doesn't evaluate the actual expression in a constant context, so the integer overflows to 0.

(I don't expect anyone to intentionally do this... wrote some synthetic testcases while looking at isCXX11ConstantExpr() for other reasons.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:frontendLanguage frontend issues, e.g. anything involving "Sema"questionA question, not bug report. Check out https://llvm.org/docs/GettingInvolved.html instead!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions