Page MenuHomePhabricator

[Diagnostics] Warn for std::is_constant_evaluated in constexpr mode
ClosedPublic

Authored by xbolva00 on Oct 28 2019, 10:25 AM.

Details

Summary

constexpr int fn1() {

if constexpr (std::is_constant_evaluated()) // condition is always true!
  return 0;
else
  return 1;

}

constexpr int fn2() {

if (std::is_constant_evaluated())
  return 0;
else
  return 1;

}

Solves PR42977

Event Timeline

xbolva00 created this revision.Oct 28 2019, 10:25 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 28 2019, 10:25 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
xbolva00 edited the summary of this revision. (Show Details)Oct 28 2019, 10:27 AM
xbolva00 added a reviewer: rsmith.
xbolva00 marked an inline comment as done.
xbolva00 added inline comments.
clang/lib/Sema/SemaExprCXX.cpp
3695

Not ideal place. Missing !E case, etc...

Maybe in ActOnCompletedExpr?

xbolva00 updated this revision to Diff 226758.Oct 28 2019, 3:20 PM

Support !E.

xbolva00 updated this revision to Diff 226759.Oct 28 2019, 3:21 PM

New tests

rsmith added inline comments.Oct 29 2019, 3:02 PM
clang/include/clang/Basic/DiagnosticSemaKinds.td
8410

"constexpr mode" isn't a thing. Maybe just "in this context"?

I think this should have its own warning group, not be grouped under -Wtautological-compare.

clang/lib/Sema/SemaExprCXX.cpp
3694

As noted in PR42977, we should warn whenever we find a call to is_constant_evaluated in a manifestly constant evaluated expression, not only in the condition of a constexpr if.

This can be checked in ExprConstant.cpp when we evaluate a call to __builtin_is_constant_evaluated: if we're about to return true from __builtin_is_constant_evaluated, and there's either no calls on the call stack or exactly one call which is to std::is_constant_evaluated, then warn.

clang/test/SemaCXX/warn-std-is-constant-evaluated-constexpr.cpp
2

This second RUN line doesn't add any value; remove it?

xbolva00 marked 3 inline comments as done.Oct 29 2019, 4:00 PM
xbolva00 added inline comments.
clang/include/clang/Basic/DiagnosticSemaKinds.td
8410

I agree. just... gcc put it under -Wtautological-compare. So should I create a new subgroup of -Wtautological-compare? Or just a new group?

clang/lib/Sema/SemaExprCXX.cpp
3694

Yeah, thanks for the hint!

clang/test/SemaCXX/warn-std-is-constant-evaluated-constexpr.cpp
2

Right, I will remove it.

rsmith added inline comments.Oct 29 2019, 6:39 PM
clang/include/clang/Basic/DiagnosticSemaKinds.td
8410

I don't really imagine many people wanting to turn this warning (or -Wtautological-compare) off, so I don't think it matters all that much. But making this a subgroup of -Wtautological-compare is cheap and would preserve GCC compatibility, so let's do that.

xbolva00 updated this revision to Diff 227192.EditedOct 30 2019, 3:25 PM

Removed old unused change.

Harbormaster completed remote builds in B40311: Diff 227192.
xbolva00 marked 2 inline comments as done.Oct 30 2019, 3:28 PM
xbolva00 added inline comments.
clang/lib/AST/ExprConstant.cpp
10595 ↗(On Diff #227192)

!Info.CheckingPotentialConstantExpression

Basically just to silence test case:
namespace std {
constexpr bool is_constant_evaluated() noexcept {

return __builtin_is_constant_evaluated();

}
}

In real world code, this will not warn, since call's loc is in system header. Leave it?

10600 ↗(On Diff #227192)

Without this condition, it warns 3 times for

if constexpr (std::is_constant_evaluated() == false)

rsmith accepted this revision.Oct 30 2019, 7:13 PM
rsmith added inline comments.
clang/include/clang/Basic/DiagnosticASTKinds.td
333 ↗(On Diff #227192)

"constexpr context" doesn't mean anything, and I'm not sure it has the right implications (eg, is the body of a constexpr function a constexpr context?).

The technically-correct thing would be "in a manifestly constant-evaluated expression".

334 ↗(On Diff #227192)

Looks like you decided not to make this a subgroup of tautological-compare? (I'm OK with that, I just wanted to make sure this was intentional given the prior discussion.)

clang/lib/AST/ExprConstant.cpp
10595 ↗(On Diff #227192)

The check seems right to me.

10597 ↗(On Diff #227192)

The number of arguments check is redundant; we know the builtin has no parameters.

10600 ↗(On Diff #227192)

Please add a "// FIXME: Find a better way to avoid duplicated diagnostics." or similar. This is relying somewhat on the implementation details of callers of the constant evaluator.

This revision is now accepted and ready to land.Oct 30 2019, 7:13 PM
xbolva00 marked an inline comment as done.Oct 31 2019, 12:58 AM
xbolva00 added inline comments.
clang/include/clang/Basic/DiagnosticASTKinds.td
334 ↗(On Diff #227192)

Yes, I decided to go with a new group since the warning is more powerful than gcc's version of this warning.

The technically-correct thing would be "in a manifestly constant-evaluated expression".

I will use this message - Thanks!

xbolva00 updated this revision to Diff 227237.Oct 31 2019, 2:01 AM

Fixed review comments.

xbolva00 marked 5 inline comments as done.Oct 31 2019, 2:03 AM

Thanks you for the review and advices!

This revision was automatically updated to reflect the committed changes.

This broke two stage builds of libc++. Can we revert this until a fix is ready?

FAIL: libc++ :: std/utilities/meta/meta.const.eval/is_constant_evaluated.fail.cpp (55845 of 59103)
******************** TEST 'libc++ :: std/utilities/meta/meta.const.eval/is_constant_evaluated.fail.cpp' FAILED ********************
Command: ['/p/tllvm/bin/clang++', '-o', '/dev/null', '-x', 'c++', '/home/dave/s/lp/libcxx/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.fail.cpp', '-c', '-v', '-ftemplate-depth=270', '-fsyntax-only', '-Xclang', '-verify', '-Xclang', '-verify-ignore-unexpected=note', '-ferror-limit=1024', '-Werror=thread-safety', '-std=c++2a', '-include', '/home/dave/s/lp/libcxx/test/support/nasty_macros.h', '-nostdinc++', '-I/home/dave/s/lp/libcxx/include', '-I/tmp/_update_lc/t/projects/libcxx/include/c++build', '-D__STDC_FORMAT_MACROS', '-D__STDC_LIMIT_MACROS', '-D__STDC_CONSTANT_MACROS', '-I/home/dave/s/lp/libcxx/test/support', '-DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="/home/dave/s/lp/libcxx/test/std/input.output/filesystems/Inputs/static_test_env"', '-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT="/tmp/_update_lc/t/projects/libcxx/test/filesystem/Output/dynamic_env"', '-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER="/usr/bin/python /home/dave/s/lp/libcxx/test/support/filesystem_dynamic_test_helper.py"', '-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER', '-Wall', '-Wextra', '-Werror', '-Wuser-defined-warnings', '-Wshadow', '-Wno-unused-command-line-argument', '-Wno-attributes', '-Wno-pessimizing-move', '-Wno-c++11-extensions', '-Wno-user-defined-literals', '-Wno-noexcept-type', '-Wsign-compare', '-Wunused-variable', '-Wunused-parameter', '-Wunreachable-code', '-Wno-error=user-defined-warnings', '-c']
Exit Code: 1
Standard Error:
--
clang version 10.0.0 (/home/dave/s/lp/clang 7e1a3076419d4d453d71143a1e81409ea1db177c)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /p/tllvm/bin
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/9
Selected GCC installation: /usr/lib/gcc/x86_64-redhat-linux/9
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Selected multilib: .;@m64
 "/p/tllvm/bin/clang-10" -cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -disable-free -disable-llvm-verifier -discard-value-names -main-file-name is_constant_evaluated.fail.cpp -mrelocation-model static -mthread-model posix -mframe-pointer=all -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -v -nostdinc++ -resource-dir /p/tllvm/lib64/clang/10.0.0 -include /home/dave/s/lp/libcxx/test/support/nasty_macros.h -I /home/dave/s/lp/libcxx/include -I /tmp/_update_lc/t/projects/libcxx/include/c++build -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -I /home/dave/s/lp/libcxx/test/support -D "LIBCXX_FILESYSTEM_STATIC_TEST_ROOT=\"/home/dave/s/lp/libcxx/test/std/input.output/filesystems/Inputs/static_test_env\"" -D "LIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT=\"/tmp/_update_lc/t/projects/libcxx/test/filesystem/Output/dynamic_env\"" -D "LIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER=\"/usr/bin/python /home/dave/s/lp/libcxx/test/support/filesystem_dynamic_test_helper.py\"" -D _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -internal-isystem /usr/local/include -internal-isystem /p/tllvm/lib64/clang/10.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Werror=thread-safety -Wall -Wextra -Werror -Wuser-defined-warnings -Wshadow -Wno-unused-command-line-argument -Wno-attributes -Wno-pessimizing-move -Wno-c++11-extensions -Wno-user-defined-literals -Wno-noexcept-type -Wsign-compare -Wunused-variable -Wunused-parameter -Wunreachable-code -Wno-error=user-defined-warnings -std=c++2a -fdeprecated-macro -fdebug-compilation-dir /tmp/_update_lc/t -ftemplate-depth 270 -ferror-limit 1024 -fmessage-length 0 -fgnuc-version=4.2.1 -fno-implicit-modules -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -verify -verify-ignore-unexpected=note -faddrsig -x c++ /home/dave/s/lp/libcxx/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.fail.cpp
clang -cc1 version 10.0.0 based upon LLVM 10.0.0svn default target x86_64-unknown-linux-gnu
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
 /home/dave/s/lp/libcxx/include
 /tmp/_update_lc/t/projects/libcxx/include/c++build
 /home/dave/s/lp/libcxx/test/support
 /usr/local/include
 /p/tllvm/lib64/clang/10.0.0/include
 /usr/include
End of search list.
error: 'error' diagnostics seen but not expected: 
  File /home/dave/s/lp/libcxx/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.fail.cpp Line 26: 'std::is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression
1 error generated.
--

Expected compilation using verify to pass!

********************
FAIL: libc++ :: std/utilities/meta/meta.const.eval/is_constant_evaluated.pass.cpp (55846 of 59103)
******************** TEST 'libc++ :: std/utilities/meta/meta.const.eval/is_constant_evaluated.pass.cpp' FAILED ********************
Command: ['/p/tllvm/bin/clang++', '-o', '/tmp/_update_lc/t/projects/libcxx/test/std/utilities/meta/meta.const.eval/Output/is_constant_evaluated.pass.cpp.o', '-x', 'c++', '/home/dave/s/lp/libcxx/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.pass.cpp', '-c', '-v', '-ftemplate-depth=270', '-Werror=thread-safety', '-std=c++2a', '-include', '/home/dave/s/lp/libcxx/test/support/nasty_macros.h', '-nostdinc++', '-I/home/dave/s/lp/libcxx/include', '-I/tmp/_update_lc/t/projects/libcxx/include/c++build', '-D__STDC_FORMAT_MACROS', '-D__STDC_LIMIT_MACROS', '-D__STDC_CONSTANT_MACROS', '-I/home/dave/s/lp/libcxx/test/support', '-DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="/home/dave/s/lp/libcxx/test/std/input.output/filesystems/Inputs/static_test_env"', '-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT="/tmp/_update_lc/t/projects/libcxx/test/filesystem/Output/dynamic_env"', '-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER="/usr/bin/python /home/dave/s/lp/libcxx/test/support/filesystem_dynamic_test_helper.py"', '-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER', '-Wall', '-Wextra', '-Werror', '-Wuser-defined-warnings', '-Wshadow', '-Wno-unused-command-line-argument', '-Wno-attributes', '-Wno-pessimizing-move', '-Wno-c++11-extensions', '-Wno-user-defined-literals', '-Wno-noexcept-type', '-Wsign-compare', '-Wunused-variable', '-Wunused-parameter', '-Wunreachable-code', '-c']
Exit Code: 1
Standard Error:
--
clang version 10.0.0 (/home/dave/s/lp/clang 7e1a3076419d4d453d71143a1e81409ea1db177c)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /p/tllvm/bin
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/9
Selected GCC installation: /usr/lib/gcc/x86_64-redhat-linux/9
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Selected multilib: .;@m64
 "/p/tllvm/bin/clang-10" -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name is_constant_evaluated.pass.cpp -mrelocation-model static -mthread-model posix -mframe-pointer=all -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -v -nostdinc++ -resource-dir /p/tllvm/lib64/clang/10.0.0 -include /home/dave/s/lp/libcxx/test/support/nasty_macros.h -I /home/dave/s/lp/libcxx/include -I /tmp/_update_lc/t/projects/libcxx/include/c++build -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -I /home/dave/s/lp/libcxx/test/support -D "LIBCXX_FILESYSTEM_STATIC_TEST_ROOT=\"/home/dave/s/lp/libcxx/test/std/input.output/filesystems/Inputs/static_test_env\"" -D "LIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT=\"/tmp/_update_lc/t/projects/libcxx/test/filesystem/Output/dynamic_env\"" -D "LIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER=\"/usr/bin/python /home/dave/s/lp/libcxx/test/support/filesystem_dynamic_test_helper.py\"" -D _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -internal-isystem /usr/local/include -internal-isystem /p/tllvm/lib64/clang/10.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Werror=thread-safety -Wall -Wextra -Werror -Wuser-defined-warnings -Wshadow -Wno-unused-command-line-argument -Wno-attributes -Wno-pessimizing-move -Wno-c++11-extensions -Wno-user-defined-literals -Wno-noexcept-type -Wsign-compare -Wunused-variable -Wunused-parameter -Wunreachable-code -std=c++2a -fdeprecated-macro -fdebug-compilation-dir /tmp/_update_lc/t/projects/libcxx/test/std/utilities/meta/meta.const.eval -ftemplate-depth 270 -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fno-implicit-modules -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -faddrsig -o /tmp/_update_lc/t/projects/libcxx/test/std/utilities/meta/meta.const.eval/Output/is_constant_evaluated.pass.cpp.o -x c++ /home/dave/s/lp/libcxx/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.pass.cpp
clang -cc1 version 10.0.0 based upon LLVM 10.0.0svn default target x86_64-unknown-linux-gnu
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
 /home/dave/s/lp/libcxx/include
 /tmp/_update_lc/t/projects/libcxx/include/c++build
 /home/dave/s/lp/libcxx/test/support
 /usr/local/include
 /p/tllvm/lib64/clang/10.0.0/include
 /usr/include
End of search list.
/home/dave/s/lp/libcxx/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.pass.cpp:35:24: error: 'std::is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression [-Werror,-Wconstant-evaluated]
    constexpr bool p = std::is_constant_evaluated();
                       ^
/home/dave/s/lp/libcxx/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.pass.cpp:41:19: error: 'std::is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression [-Werror,-Wconstant-evaluated]
    static_assert(std::is_constant_evaluated(), "");
                  ^
/home/dave/s/lp/libcxx/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.pass.cpp:44:33: error: 'std::is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression [-Werror,-Wconstant-evaluated]
    ASSERT_SAME_TYPE(InTemplate<std::is_constant_evaluated()>, InTemplate<true>);
                                ^
3 errors generated.
--

Compilation failed unexpectedly!
********************
Testing Time: 111.41s
********************
Failing Tests (2):
    libc++ :: std/utilities/meta/meta.const.eval/is_constant_evaluated.fail.cpp
    libc++ :: std/utilities/meta/meta.const.eval/is_constant_evaluated.pass.cpp

  Expected Passes    : 43344
  Expected Failures  : 103
  Unsupported Tests  : 15654
  Unexpected Failures: 2
xbolva00 added a comment.EditedNov 1 2019, 4:58 AM

Line 918

Add:
self.cxx.addWarningFlagIfSupported('-Wno-constant-evaluated')

to libcxx/utils/libcxx/test/config.py

Can you please try?

cc @EricWF

xbolva00 added a subscriber: EricWF.Nov 1 2019, 4:59 AM

Hi @xbolva00 – Thanks. That does make the libcxx test suite pass.