[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
shafik wrote: > Based on #141114 and #141858 should this PR be reverted? A fix was landed: https://github.com/llvm/llvm-project/pull/142498 https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
rockwotj wrote: Based on #141114 and #141858 should this PR be reverted? https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
zygoloid wrote: > > If that mode doesn't already permit using unknown pointers and references > > in all language modes, then we should change it so that it does. > > `__builtin_object_size` is best-effort, but we should produce a constant > > value for it that's not the `-1` or `0` fallback value whenever we're able > > to do so. > > But there isn't much we can do with unknown pointers or references, is there? > > We can't have `foo` return 4 unless we know for sure that `s` isn't embedded > in a larger object. In the following case, wouldn't `foo` be expected to > return 12? > > ``` > int bar() { > S a[2]; > return foo(a[0]); > } > ``` It depends on the mode parameter in `__builtin_object_size`. For mode 1 and 3, we can use the access path and return 4 if `-fstrict-flex-arrays` is strict enough. For mode 0 or 2, or with lax flexible array rules, I agree that we can't conclude anything and would need to return `0` / `-1`. https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
shafik wrote: @kripken somewhat reduced: ```cpp struct MyStruct { double m0{-.0}; int m1{-12345}; }; constexpr MyStruct default_val; auto compute_area(double l, const MyStruct &val = default_val) -> double { if (val.m1 == 1) return 2.0; return 0; } #include auto main() -> int { MyStruct in_val{.m0 = 2.0, .m1 = 1}; double val = compute_area(1.0, in_val); assert(val == 2.0); } ``` https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
ahatanak wrote: > If that mode doesn't already permit using unknown pointers and references in > all language modes, then we should change it so that it does. > `__builtin_object_size` is best-effort, but we should produce a constant > value for it that's not the `-1` or `0` fallback value whenever we're able to > do so. But there isn't much we can do with unknown pointers or references, is there? We can't have `foo` return 4 unless we know for sure that `s` isn't embedded in a larger object. In the following case, wouldn't `foo` be expected to return 12? ``` int bar() { S a[2]; return foo(a[0]); } ``` https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
zygoloid wrote: > Should `foo` in the following code return 4 when `-fstrict-flex-arrays` is 2 > or 3 (but not when it's 0 or 1) only when the target is `-std=c++23` or > newer? Or should it return 4 for older standards too? We evaluate the operand of `__builtin_object_size` in `EM_IgnoreSideEffects` mode, which is documented as: > ```c++ > /// Evaluate in any way we know how. Don't worry about side-effects that > /// can't be modeled. > ``` If that mode doesn't already permit using unknown pointers and references in all language modes, then we should change it so that it does. `__builtin_object_size` is best-effort, but we should produce a constant value for it that's not the `-1` or `0` fallback value whenever we're able to do so. https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
ahatanak wrote: > Looks like a bug to me. This warning presumably ought to be checking whether > it's valid to read / write to the given location using something like > [`isUserWritingOffTheEnd`](https://github.com/llvm/llvm-project/blob/b2e2ae8702e9fbbe0ef0eb5929aa2d5dc867b1c5/clang/lib/AST/ExprConstant.cpp#L12699). > (But I don't think that's a bug in _this_ PR.) Should `foo` in the following code return 4 when `-fstrict-flex-arrays` is 2 or 3 (but not when it's 0 or 1) only when the target is `-std=c++23` or newer? Or should it return 4 for older standards too? ``` struct S { int count; int array[1]; }; int foo(S &s) { return __builtin_object_size(s.array, 0); } ``` And this function should return -1 regardless of what the standard is because `s` is a pointer? ``` int foo(S *s) { return __builtin_object_size(s->array, 0); } ``` https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
ahatanak wrote: `evaluateVarDeclInit` is using the default argument expression (`default_val`) to evaluate the initializer of parameter `val`. ``` // Dig out the initializer, and use the declaration which it's attached to. // FIXME: We should eventually check whether the variable has a reachable // initializing declaration. const Expr *Init = VD->getAnyInitializer(VD); ``` https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
kripken wrote: I am seeing a runtime error after this, when using C++23, which looks like a regression. Testcase: ```cpp // A.hpp #include struct MyStruct { double m0{-.0}; int m1{-12345}; }; constexpr MyStruct default_val; auto compute_area(double l, const MyStruct &val = default_val) -> double { std::cout << "compute_area : val.m0 : " << val.m0 << "\n"; std::cout << "compute_area : val.m1 : " << val.m1 << " \n"; if (val.m1 != -12345) { return val.m0 * l; } return -; } // main.cpp //#include "A.hpp" #include #include auto main() -> int { MyStruct in_val{.m0 = 2.0, .m1 = 1}; std::cout << "main : in_val.m0 : " << in_val.m0 << "\n"; std::cout << "main : in_val.m1 : " << in_val.m1 << " \n\n"; double val = compute_area(1.0, in_val); std::cout << "result = " << val << std::endl; assert(val == 2.0); return 0; } ``` Before this landed, it runs ok: ``` $ build/bin/clang++ a.cpp -std=c++23 && ./a.out main : in_val.m0 : 2 main : in_val.m1 : 1 compute_area : val.m0 : 2 compute_area : val.m1 : 1 result = 2 ``` After this landed, the assert fails: ``` $ build/bin/clang++ a.cpp -std=c++23 && ./a.out main : in_val.m0 : 2 main : in_val.m1 : 1 compute_area : val.m0 : 2 compute_area : val.m1 : -12345 result = - a.out: a.cpp:30: int main(): Assertion `val == 2.0' failed. Aborted (core dumped) ``` (original report: https://github.com/emscripten-core/emscripten/issues/24325) https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
thevar1able wrote: Hey, I'm seeing a compiler crash after this PR. https://pastila.nl/?000c2db4/648c000755344e7c43e24c25dd06a571#dyq1EG+tE1OVC+RrCFJoNw== https://pastila.nl/?/32b5c1db56a683e9e5b5b6a8cbed11f7#mDdZiawfthfoxTBwvG8dJg== https://pastila.nl/?001086ff/212fddaf6ed75f6e0320bd34509c377d#RopRZ8zp/s2UPwcKBzWVXg== https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
zygoloid wrote: Looks like a bug to me. This warning presumably ought to be checking whether it's valid to read / write to the given location using something like [`isUserWritingOffTheEnd`](https://github.com/llvm/llvm-project/blob/b2e2ae8702e9fbbe0ef0eb5929aa2d5dc867b1c5/clang/lib/AST/ExprConstant.cpp#L12699). https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
ahatanak wrote: Is passing `-fstrict-flex-arrays=1` supposed to silence the warning? I still see the warning: https://godbolt.org/z/YEKhW19nK https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
zygoloid wrote: > Is the warning valid? Is the change in clang's behavior intentional? What do you have `-fstrict-flex-arrays` set to? Per [the documentation](https://releases.llvm.org/15.0.0/tools/clang/docs/ClangCommandLineReference.html#cmdoption-clang-fstrict-flex-arrays) (which weirdly seems to be missing at HEAD...) if it's not set to `1` then we don't consider a `[1]` array bound to indicate a flexible array member, which would make the warning correct. https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
ahatanak wrote: clang started issuing a warning after this PR was merged when compiling the following code: ``` typedef long unsigned int size_t; extern "C" { void * memcpy(void * __dst, const void * __src, size_t __n); } struct MyClass { unsigned numberOfBuffers; unsigned long long buffers[1]; }; typedef struct MyClass MyClass; MyClass a0; void test() { const size_t byteSize = sizeof(MyClass) + sizeof(unsigned long long); MyClass &a1 = *(MyClass *)__builtin_alloca(byteSize); MyClass *a2 = (MyClass *)__builtin_alloca(byteSize); memcpy(&a1.buffers[0], &a0.buffers[0], sizeof(unsigned long long)); // no warnings. memcpy(&a1.buffers[1], &a0.buffers[0], sizeof(unsigned long long)); // warning: 'memcpy' will always overflow; destination buffer has size 0, but size argument is 8 [-Wfortify-source] memcpy(a2->buffers[1], &a0.buffers[0], sizeof(unsigned long long)); // no warnings. } ``` Is the warning valid? Is the change in clang's behavior intentional? https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
llvm-ci wrote: LLVM Buildbot has detected a new failure on builder `premerge-monolithic-linux` running on `premerge-linux-1` while building `clang` at step 7 "test-build-unified-tree-check-all". Full details are available at: https://lab.llvm.org/buildbot/#/builders/153/builds/20475 Here is the relevant piece of the build log for the reference ``` Step 7 (test-build-unified-tree-check-all) failure: test (failure) TEST 'Clang :: AST/ByteCode/cxx2a.cpp' FAILED Exit Code: 1 Command Output (stderr): -- RUN: at line 1: /build/buildbot/premerge-monolithic-linux/build/bin/clang -cc1 -internal-isystem /build/buildbot/premerge-monolithic-linux/build/lib/clang/20/include -nostdsysteminc -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both /build/buildbot/premerge-monolithic-linux/llvm-project/clang/test/AST/ByteCode/cxx2a.cpp + /build/buildbot/premerge-monolithic-linux/build/bin/clang -cc1 -internal-isystem /build/buildbot/premerge-monolithic-linux/build/lib/clang/20/include -nostdsysteminc -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both /build/buildbot/premerge-monolithic-linux/llvm-project/clang/test/AST/ByteCode/cxx2a.cpp error: 'both-error' diagnostics expected but not seen: File /build/buildbot/premerge-monolithic-linux/llvm-project/clang/test/AST/ByteCode/cxx2a.cpp Line 142: constant expression error: 'both-note' diagnostics expected but not seen: File /build/buildbot/premerge-monolithic-linux/llvm-project/clang/test/AST/ByteCode/cxx2a.cpp Line 142: typeid applied to object 'extern_b2' whose dynamic type is not constant 2 errors generated. -- ``` https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
llvm-ci wrote: LLVM Buildbot has detected a new failure on builder `llvm-x86_64-debian-dylib` running on `gribozavr4` while building `clang` at step 6 "test-build-unified-tree-check-clang". Full details are available at: https://lab.llvm.org/buildbot/#/builders/60/builds/17619 Here is the relevant piece of the build log for the reference ``` Step 6 (test-build-unified-tree-check-clang) failure: test (failure) TEST 'Clang :: AST/ByteCode/cxx2a.cpp' FAILED Exit Code: 1 Command Output (stderr): -- RUN: at line 1: /b/1/llvm-x86_64-debian-dylib/build/bin/clang -cc1 -internal-isystem /b/1/llvm-x86_64-debian-dylib/build/lib/clang/20/include -nostdsysteminc -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both /b/1/llvm-x86_64-debian-dylib/llvm-project/clang/test/AST/ByteCode/cxx2a.cpp + /b/1/llvm-x86_64-debian-dylib/build/bin/clang -cc1 -internal-isystem /b/1/llvm-x86_64-debian-dylib/build/lib/clang/20/include -nostdsysteminc -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both /b/1/llvm-x86_64-debian-dylib/llvm-project/clang/test/AST/ByteCode/cxx2a.cpp error: 'both-error' diagnostics expected but not seen: File /b/1/llvm-x86_64-debian-dylib/llvm-project/clang/test/AST/ByteCode/cxx2a.cpp Line 142: constant expression error: 'both-note' diagnostics expected but not seen: File /b/1/llvm-x86_64-debian-dylib/llvm-project/clang/test/AST/ByteCode/cxx2a.cpp Line 142: typeid applied to object 'extern_b2' whose dynamic type is not constant 2 errors generated. -- ``` https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
llvm-ci wrote: LLVM Buildbot has detected a new failure on builder `clang-x86_64-debian-fast` running on `gribozavr4` while building `clang` at step 6 "test-build-unified-tree-check-all". Full details are available at: https://lab.llvm.org/buildbot/#/builders/56/builds/16819 Here is the relevant piece of the build log for the reference ``` Step 6 (test-build-unified-tree-check-all) failure: test (failure) TEST 'Clang :: AST/ByteCode/cxx2a.cpp' FAILED Exit Code: 1 Command Output (stderr): -- RUN: at line 1: /b/1/clang-x86_64-debian-fast/llvm.obj/bin/clang -cc1 -internal-isystem /b/1/clang-x86_64-debian-fast/llvm.obj/lib/clang/20/include -nostdsysteminc -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both /b/1/clang-x86_64-debian-fast/llvm.src/clang/test/AST/ByteCode/cxx2a.cpp + /b/1/clang-x86_64-debian-fast/llvm.obj/bin/clang -cc1 -internal-isystem /b/1/clang-x86_64-debian-fast/llvm.obj/lib/clang/20/include -nostdsysteminc -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both /b/1/clang-x86_64-debian-fast/llvm.src/clang/test/AST/ByteCode/cxx2a.cpp error: 'both-error' diagnostics expected but not seen: File /b/1/clang-x86_64-debian-fast/llvm.src/clang/test/AST/ByteCode/cxx2a.cpp Line 142: constant expression error: 'both-note' diagnostics expected but not seen: File /b/1/clang-x86_64-debian-fast/llvm.src/clang/test/AST/ByteCode/cxx2a.cpp Line 142: typeid applied to object 'extern_b2' whose dynamic type is not constant 2 errors generated. -- ``` https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
tbaederr wrote: Just a `s/both/expected/` in those two lines should be enough https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
jplehr wrote: Thank you. https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
cor3ntin wrote: I am investigating the build failures and will revert or commit a fix shortly https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
llvm-ci wrote: LLVM Buildbot has detected a new failure on builder `llvm-clang-x86_64-sie-ubuntu-fast` running on `sie-linux-worker` while building `clang` at step 6 "test-build-unified-tree-check-all". Full details are available at: https://lab.llvm.org/buildbot/#/builders/144/builds/16245 Here is the relevant piece of the build log for the reference ``` Step 6 (test-build-unified-tree-check-all) failure: test (failure) TEST 'Clang :: AST/ByteCode/cxx2a.cpp' FAILED Exit Code: 1 Command Output (stderr): -- RUN: at line 1: /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/bin/clang -cc1 -internal-isystem /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/lib/clang/20/include -nostdsysteminc -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/AST/ByteCode/cxx2a.cpp + /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/bin/clang -cc1 -internal-isystem /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/lib/clang/20/include -nostdsysteminc -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/AST/ByteCode/cxx2a.cpp error: 'both-error' diagnostics expected but not seen: File /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/AST/ByteCode/cxx2a.cpp Line 142: constant expression error: 'both-note' diagnostics expected but not seen: File /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/AST/ByteCode/cxx2a.cpp Line 142: typeid applied to object 'extern_b2' whose dynamic type is not constant 2 errors generated. -- ``` https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
llvm-ci wrote: LLVM Buildbot has detected a new failure on builder `clang-aarch64-quick` running on `linaro-clang-aarch64-quick` while building `clang` at step 5 "ninja check 1". Full details are available at: https://lab.llvm.org/buildbot/#/builders/65/builds/11020 Here is the relevant piece of the build log for the reference ``` Step 5 (ninja check 1) failure: stage 1 checked (failure) TEST 'Clang :: AST/ByteCode/cxx2a.cpp' FAILED Exit Code: 1 Command Output (stderr): -- RUN: at line 1: /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/clang -cc1 -internal-isystem /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/lib/clang/20/include -nostdsysteminc -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both /home/tcwg-buildbot/worker/clang-aarch64-quick/llvm/clang/test/AST/ByteCode/cxx2a.cpp + /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/clang -cc1 -internal-isystem /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/lib/clang/20/include -nostdsysteminc -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both /home/tcwg-buildbot/worker/clang-aarch64-quick/llvm/clang/test/AST/ByteCode/cxx2a.cpp error: 'both-error' diagnostics expected but not seen: File /home/tcwg-buildbot/worker/clang-aarch64-quick/llvm/clang/test/AST/ByteCode/cxx2a.cpp Line 142: constant expression error: 'both-note' diagnostics expected but not seen: File /home/tcwg-buildbot/worker/clang-aarch64-quick/llvm/clang/test/AST/ByteCode/cxx2a.cpp Line 142: typeid applied to object 'extern_b2' whose dynamic type is not constant 2 errors generated. -- ``` https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
llvm-ci wrote: LLVM Buildbot has detected a new failure on builder `arc-builder` running on `arc-worker` while building `clang` at step 6 "test-build-unified-tree-check-all". Full details are available at: https://lab.llvm.org/buildbot/#/builders/3/builds/10663 Here is the relevant piece of the build log for the reference ``` Step 6 (test-build-unified-tree-check-all) failure: test (failure) TEST 'Clang :: AST/ByteCode/cxx2a.cpp' FAILED Exit Code: 1 Command Output (stderr): -- RUN: at line 1: /buildbot/worker/arc-folder/build/bin/clang -cc1 -internal-isystem /buildbot/worker/arc-folder/build/lib/clang/20/include -nostdsysteminc -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both /buildbot/worker/arc-folder/llvm-project/clang/test/AST/ByteCode/cxx2a.cpp + /buildbot/worker/arc-folder/build/bin/clang -cc1 -internal-isystem /buildbot/worker/arc-folder/build/lib/clang/20/include -nostdsysteminc -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both /buildbot/worker/arc-folder/llvm-project/clang/test/AST/ByteCode/cxx2a.cpp error: 'both-error' diagnostics expected but not seen: File /buildbot/worker/arc-folder/llvm-project/clang/test/AST/ByteCode/cxx2a.cpp Line 142: constant expression error: 'both-note' diagnostics expected but not seen: File /buildbot/worker/arc-folder/llvm-project/clang/test/AST/ByteCode/cxx2a.cpp Line 142: typeid applied to object 'extern_b2' whose dynamic type is not constant 2 errors generated. -- ``` https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
cor3ntin wrote: :tada: :rocket: https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/cor3ntin closed https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
cor3ntin wrote: As discussed in the Clang WG meeting, we think this is in good shape and should be merged this week (pending adding a release note) despite the weird warning change. This gives us the opportunity to get some experience before the branch and fix numerous bug reports, while having time to revert if something explodes in downstreams https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -1961,7 +1961,8 @@ namespace ConstexprConstructorRecovery { namespace Lifetime { void f() { -constexpr int &n = n; // expected-error {{constant expression}} expected-note {{use of reference outside its lifetime}} expected-warning {{not yet bound to a value}} +constexpr int &n = n; // expected-error {{constant expression}} cxx23-note {{reference to 'n' is not a constant expression}} cxx23-note {{address of non-static constexpr variable 'n' may differ}} expected-warning {{not yet bound to a value}} + // cxx11_20-note@-1 {{use of reference outside its lifetime is not allowed in a constant expression}} cor3ntin wrote: @shafik https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/shafik updated https://github.com/llvm/llvm-project/pull/95474 >From 69b09ea5b0f0a1c5419c488ade29b6fedc6de773 Mon Sep 17 00:00:00 2001 From: Shafik Yaghmour Date: Thu, 13 Jun 2024 14:20:50 -0700 Subject: [PATCH 01/12] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions P2280R4 allows the use of references in pointers of unknown origins in a constant expression context but only in specific cases that could be constant expressions. We track whether a variable is a constexpr unknown in a constant expression by setting a flag in either APValue or LValue and using this flag to prevent using unknown values in places where it is not allowed. In `evaluateVarDeclInit` we may need to create a new `APValue` to track the unknown referene or pointer and we track that `APValue` in the `CallStackFrame`. Fixes: https://github.com/llvm/llvm-project/issues/63139 https://github.com/llvm/llvm-project/issues/63117 --- clang/include/clang/AST/APValue.h | 48 +++ clang/lib/AST/APValue.cpp | 12 ++- clang/lib/AST/ExprConstant.cpp| 85 +-- .../SemaCXX/constant-expression-cxx11.cpp | 16 ++-- .../SemaCXX/constant-expression-cxx2a.cpp | 3 +- .../SemaCXX/constant-expression-p2280r4.cpp | 54 6 files changed, 183 insertions(+), 35 deletions(-) create mode 100644 clang/test/SemaCXX/constant-expression-p2280r4.cpp diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index c4206b73b11562..6352348107a647 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -249,6 +249,7 @@ class APValue { struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + struct ConstexprUnknown {}; template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; @@ -256,6 +257,7 @@ class APValue { private: ValueKind Kind; + bool AllowConstexprUnknown = false; struct ComplexAPSInt { APSInt Real, Imag; @@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } + + APValue() : Kind(None), AllowConstexprUnknown(false) {} + explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(None) { + explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(APFixedPoint FX) : Kind(None) { + explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { MakeFixedPoint(std::move(FX)); } - explicit APValue(const APValue *E, unsigned N) : Kind(None) { + explicit APValue(const APValue *E, unsigned N) + : Kind(None), AllowConstexprUnknown(false) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(None) { + APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(None) { + APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { + + APValue(LValueBase B, ConstexprUnknown, const CharUnits &O, + bool IsNullPtr = false) + : Kind(None), AllowConstexprUnknown(true) { +MakeLValue(); +setLValue(B, O, NoLValuePath{}, IsNullPtr); + } + + APValue(UninitArray, unsigned InitElts, unsigned Size) + : Kind(None), AllowConstexprUnknown(false) { MakeArray(InitElts, Size); } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { + APValue(UninitStruct, unsigned B, unsigned M) + : Kind(None), AllowConstexprUnknown(false) { MakeStruct(B, M); } explicit APValue(const FieldDecl *D, const APValue &V = APValue()) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeUnion(); setUnion(D, V); } APValue(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) : Kind(None) { + ArrayRef Path) + : Kind(None), Al
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -1944,6 +1956,16 @@ APValue &CallStackFrame::createTemporary(const KeyT *Key, QualType T, return createLocal(Base, Key, T, Scope); } +APValue & +CallStackFrame::createConstexprUnknownAPValues(const VarDecl *Key, + APValue::LValueBase Base) { + APValue &Result = ConstexprUnknownAPValues[MapKeyTy(Key, Base.getVersion())]; + Result = APValue(Base, CharUnits::One(), APValue::ConstexprUnknown{}); + Result.setConstexprUnknown(); cor3ntin wrote: That seems redundant https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -3566,6 +3613,21 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, } Result = VD->getEvaluatedValue(); + + // C++23 [expr.const]p8 + // ... For such an object that is not usable in constant expressions, the + // dynamic type of the object is constexpr-unknown. For such a reference that + // is not usable in constant expressions, the reference is treated as binding + // to an unspecified object of the referenced type whose lifetime and that of + // all subobjects includes the entire constant evaluation and whose dynamic + // type is constexpr-unknown. + if (AllowConstexprUnknown) { +if (!Result) { + Result = &Info.CurrentCall->createConstexprUnknownAPValues(VD, Base); +} else { + Result->setConstexprUnknown(); +} cor3ntin wrote: ```suggestion if (!Result) Result = &Info.CurrentCall->createConstexprUnknownAPValues(VD, Base); else Result->setConstexprUnknown(); ``` (Or use a ternary) https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/cor3ntin edited https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/cor3ntin commented: Just a few nits + missing cxx_status/release notes changes https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/shafik updated https://github.com/llvm/llvm-project/pull/95474 >From 69b09ea5b0f0a1c5419c488ade29b6fedc6de773 Mon Sep 17 00:00:00 2001 From: Shafik Yaghmour Date: Thu, 13 Jun 2024 14:20:50 -0700 Subject: [PATCH 01/11] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions P2280R4 allows the use of references in pointers of unknown origins in a constant expression context but only in specific cases that could be constant expressions. We track whether a variable is a constexpr unknown in a constant expression by setting a flag in either APValue or LValue and using this flag to prevent using unknown values in places where it is not allowed. In `evaluateVarDeclInit` we may need to create a new `APValue` to track the unknown referene or pointer and we track that `APValue` in the `CallStackFrame`. Fixes: https://github.com/llvm/llvm-project/issues/63139 https://github.com/llvm/llvm-project/issues/63117 --- clang/include/clang/AST/APValue.h | 48 +++ clang/lib/AST/APValue.cpp | 12 ++- clang/lib/AST/ExprConstant.cpp| 85 +-- .../SemaCXX/constant-expression-cxx11.cpp | 16 ++-- .../SemaCXX/constant-expression-cxx2a.cpp | 3 +- .../SemaCXX/constant-expression-p2280r4.cpp | 54 6 files changed, 183 insertions(+), 35 deletions(-) create mode 100644 clang/test/SemaCXX/constant-expression-p2280r4.cpp diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index c4206b73b11562..6352348107a647 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -249,6 +249,7 @@ class APValue { struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + struct ConstexprUnknown {}; template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; @@ -256,6 +257,7 @@ class APValue { private: ValueKind Kind; + bool AllowConstexprUnknown = false; struct ComplexAPSInt { APSInt Real, Imag; @@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } + + APValue() : Kind(None), AllowConstexprUnknown(false) {} + explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(None) { + explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(APFixedPoint FX) : Kind(None) { + explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { MakeFixedPoint(std::move(FX)); } - explicit APValue(const APValue *E, unsigned N) : Kind(None) { + explicit APValue(const APValue *E, unsigned N) + : Kind(None), AllowConstexprUnknown(false) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(None) { + APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(None) { + APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { + + APValue(LValueBase B, ConstexprUnknown, const CharUnits &O, + bool IsNullPtr = false) + : Kind(None), AllowConstexprUnknown(true) { +MakeLValue(); +setLValue(B, O, NoLValuePath{}, IsNullPtr); + } + + APValue(UninitArray, unsigned InitElts, unsigned Size) + : Kind(None), AllowConstexprUnknown(false) { MakeArray(InitElts, Size); } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { + APValue(UninitStruct, unsigned B, unsigned M) + : Kind(None), AllowConstexprUnknown(false) { MakeStruct(B, M); } explicit APValue(const FieldDecl *D, const APValue &V = APValue()) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeUnion(); setUnion(D, V); } APValue(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) : Kind(None) { + ArrayRef Path) + : Kind(None), Al
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/shafik updated https://github.com/llvm/llvm-project/pull/95474 >From 69b09ea5b0f0a1c5419c488ade29b6fedc6de773 Mon Sep 17 00:00:00 2001 From: Shafik Yaghmour Date: Thu, 13 Jun 2024 14:20:50 -0700 Subject: [PATCH 01/10] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions P2280R4 allows the use of references in pointers of unknown origins in a constant expression context but only in specific cases that could be constant expressions. We track whether a variable is a constexpr unknown in a constant expression by setting a flag in either APValue or LValue and using this flag to prevent using unknown values in places where it is not allowed. In `evaluateVarDeclInit` we may need to create a new `APValue` to track the unknown referene or pointer and we track that `APValue` in the `CallStackFrame`. Fixes: https://github.com/llvm/llvm-project/issues/63139 https://github.com/llvm/llvm-project/issues/63117 --- clang/include/clang/AST/APValue.h | 48 +++ clang/lib/AST/APValue.cpp | 12 ++- clang/lib/AST/ExprConstant.cpp| 85 +-- .../SemaCXX/constant-expression-cxx11.cpp | 16 ++-- .../SemaCXX/constant-expression-cxx2a.cpp | 3 +- .../SemaCXX/constant-expression-p2280r4.cpp | 54 6 files changed, 183 insertions(+), 35 deletions(-) create mode 100644 clang/test/SemaCXX/constant-expression-p2280r4.cpp diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index c4206b73b11562..6352348107a647 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -249,6 +249,7 @@ class APValue { struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + struct ConstexprUnknown {}; template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; @@ -256,6 +257,7 @@ class APValue { private: ValueKind Kind; + bool AllowConstexprUnknown = false; struct ComplexAPSInt { APSInt Real, Imag; @@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } + + APValue() : Kind(None), AllowConstexprUnknown(false) {} + explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(None) { + explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(APFixedPoint FX) : Kind(None) { + explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { MakeFixedPoint(std::move(FX)); } - explicit APValue(const APValue *E, unsigned N) : Kind(None) { + explicit APValue(const APValue *E, unsigned N) + : Kind(None), AllowConstexprUnknown(false) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(None) { + APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(None) { + APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { + + APValue(LValueBase B, ConstexprUnknown, const CharUnits &O, + bool IsNullPtr = false) + : Kind(None), AllowConstexprUnknown(true) { +MakeLValue(); +setLValue(B, O, NoLValuePath{}, IsNullPtr); + } + + APValue(UninitArray, unsigned InitElts, unsigned Size) + : Kind(None), AllowConstexprUnknown(false) { MakeArray(InitElts, Size); } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { + APValue(UninitStruct, unsigned B, unsigned M) + : Kind(None), AllowConstexprUnknown(false) { MakeStruct(B, M); } explicit APValue(const FieldDecl *D, const APValue &V = APValue()) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeUnion(); setUnion(D, V); } APValue(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) : Kind(None) { + ArrayRef Path) + : Kind(None), Al
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/shafik updated https://github.com/llvm/llvm-project/pull/95474 >From 69b09ea5b0f0a1c5419c488ade29b6fedc6de773 Mon Sep 17 00:00:00 2001 From: Shafik Yaghmour Date: Thu, 13 Jun 2024 14:20:50 -0700 Subject: [PATCH 1/9] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions P2280R4 allows the use of references in pointers of unknown origins in a constant expression context but only in specific cases that could be constant expressions. We track whether a variable is a constexpr unknown in a constant expression by setting a flag in either APValue or LValue and using this flag to prevent using unknown values in places where it is not allowed. In `evaluateVarDeclInit` we may need to create a new `APValue` to track the unknown referene or pointer and we track that `APValue` in the `CallStackFrame`. Fixes: https://github.com/llvm/llvm-project/issues/63139 https://github.com/llvm/llvm-project/issues/63117 --- clang/include/clang/AST/APValue.h | 48 +++ clang/lib/AST/APValue.cpp | 12 ++- clang/lib/AST/ExprConstant.cpp| 85 +-- .../SemaCXX/constant-expression-cxx11.cpp | 16 ++-- .../SemaCXX/constant-expression-cxx2a.cpp | 3 +- .../SemaCXX/constant-expression-p2280r4.cpp | 54 6 files changed, 183 insertions(+), 35 deletions(-) create mode 100644 clang/test/SemaCXX/constant-expression-p2280r4.cpp diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index c4206b73b11562..6352348107a647 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -249,6 +249,7 @@ class APValue { struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + struct ConstexprUnknown {}; template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; @@ -256,6 +257,7 @@ class APValue { private: ValueKind Kind; + bool AllowConstexprUnknown = false; struct ComplexAPSInt { APSInt Real, Imag; @@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } + + APValue() : Kind(None), AllowConstexprUnknown(false) {} + explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(None) { + explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(APFixedPoint FX) : Kind(None) { + explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { MakeFixedPoint(std::move(FX)); } - explicit APValue(const APValue *E, unsigned N) : Kind(None) { + explicit APValue(const APValue *E, unsigned N) + : Kind(None), AllowConstexprUnknown(false) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(None) { + APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(None) { + APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { + + APValue(LValueBase B, ConstexprUnknown, const CharUnits &O, + bool IsNullPtr = false) + : Kind(None), AllowConstexprUnknown(true) { +MakeLValue(); +setLValue(B, O, NoLValuePath{}, IsNullPtr); + } + + APValue(UninitArray, unsigned InitElts, unsigned Size) + : Kind(None), AllowConstexprUnknown(false) { MakeArray(InitElts, Size); } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { + APValue(UninitStruct, unsigned B, unsigned M) + : Kind(None), AllowConstexprUnknown(false) { MakeStruct(B, M); } explicit APValue(const FieldDecl *D, const APValue &V = APValue()) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeUnion(); setUnion(D, V); } APValue(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) : Kind(None) { + ArrayRef Path) + : Kind(None), Allo
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
shafik wrote: We have a new crash on new code introduced since I last worked on this, I am guessing it just requires some additional checks. https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/shafik updated https://github.com/llvm/llvm-project/pull/95474 >From 69b09ea5b0f0a1c5419c488ade29b6fedc6de773 Mon Sep 17 00:00:00 2001 From: Shafik Yaghmour Date: Thu, 13 Jun 2024 14:20:50 -0700 Subject: [PATCH 1/8] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions P2280R4 allows the use of references in pointers of unknown origins in a constant expression context but only in specific cases that could be constant expressions. We track whether a variable is a constexpr unknown in a constant expression by setting a flag in either APValue or LValue and using this flag to prevent using unknown values in places where it is not allowed. In `evaluateVarDeclInit` we may need to create a new `APValue` to track the unknown referene or pointer and we track that `APValue` in the `CallStackFrame`. Fixes: https://github.com/llvm/llvm-project/issues/63139 https://github.com/llvm/llvm-project/issues/63117 --- clang/include/clang/AST/APValue.h | 48 +++ clang/lib/AST/APValue.cpp | 12 ++- clang/lib/AST/ExprConstant.cpp| 85 +-- .../SemaCXX/constant-expression-cxx11.cpp | 16 ++-- .../SemaCXX/constant-expression-cxx2a.cpp | 3 +- .../SemaCXX/constant-expression-p2280r4.cpp | 54 6 files changed, 183 insertions(+), 35 deletions(-) create mode 100644 clang/test/SemaCXX/constant-expression-p2280r4.cpp diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index c4206b73b11562..6352348107a647 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -249,6 +249,7 @@ class APValue { struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + struct ConstexprUnknown {}; template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; @@ -256,6 +257,7 @@ class APValue { private: ValueKind Kind; + bool AllowConstexprUnknown = false; struct ComplexAPSInt { APSInt Real, Imag; @@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } + + APValue() : Kind(None), AllowConstexprUnknown(false) {} + explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(None) { + explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(APFixedPoint FX) : Kind(None) { + explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { MakeFixedPoint(std::move(FX)); } - explicit APValue(const APValue *E, unsigned N) : Kind(None) { + explicit APValue(const APValue *E, unsigned N) + : Kind(None), AllowConstexprUnknown(false) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(None) { + APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(None) { + APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { + + APValue(LValueBase B, ConstexprUnknown, const CharUnits &O, + bool IsNullPtr = false) + : Kind(None), AllowConstexprUnknown(true) { +MakeLValue(); +setLValue(B, O, NoLValuePath{}, IsNullPtr); + } + + APValue(UninitArray, unsigned InitElts, unsigned Size) + : Kind(None), AllowConstexprUnknown(false) { MakeArray(InitElts, Size); } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { + APValue(UninitStruct, unsigned B, unsigned M) + : Kind(None), AllowConstexprUnknown(false) { MakeStruct(B, M); } explicit APValue(const FieldDecl *D, const APValue &V = APValue()) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeUnion(); setUnion(D, V); } APValue(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) : Kind(None) { + ArrayRef Path) + : Kind(None), Allo
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/shafik updated https://github.com/llvm/llvm-project/pull/95474 >From 69b09ea5b0f0a1c5419c488ade29b6fedc6de773 Mon Sep 17 00:00:00 2001 From: Shafik Yaghmour Date: Thu, 13 Jun 2024 14:20:50 -0700 Subject: [PATCH 1/7] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions P2280R4 allows the use of references in pointers of unknown origins in a constant expression context but only in specific cases that could be constant expressions. We track whether a variable is a constexpr unknown in a constant expression by setting a flag in either APValue or LValue and using this flag to prevent using unknown values in places where it is not allowed. In `evaluateVarDeclInit` we may need to create a new `APValue` to track the unknown referene or pointer and we track that `APValue` in the `CallStackFrame`. Fixes: https://github.com/llvm/llvm-project/issues/63139 https://github.com/llvm/llvm-project/issues/63117 --- clang/include/clang/AST/APValue.h | 48 +++ clang/lib/AST/APValue.cpp | 12 ++- clang/lib/AST/ExprConstant.cpp| 85 +-- .../SemaCXX/constant-expression-cxx11.cpp | 16 ++-- .../SemaCXX/constant-expression-cxx2a.cpp | 3 +- .../SemaCXX/constant-expression-p2280r4.cpp | 54 6 files changed, 183 insertions(+), 35 deletions(-) create mode 100644 clang/test/SemaCXX/constant-expression-p2280r4.cpp diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index c4206b73b11562..6352348107a647 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -249,6 +249,7 @@ class APValue { struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + struct ConstexprUnknown {}; template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; @@ -256,6 +257,7 @@ class APValue { private: ValueKind Kind; + bool AllowConstexprUnknown = false; struct ComplexAPSInt { APSInt Real, Imag; @@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } + + APValue() : Kind(None), AllowConstexprUnknown(false) {} + explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(None) { + explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(APFixedPoint FX) : Kind(None) { + explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { MakeFixedPoint(std::move(FX)); } - explicit APValue(const APValue *E, unsigned N) : Kind(None) { + explicit APValue(const APValue *E, unsigned N) + : Kind(None), AllowConstexprUnknown(false) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(None) { + APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(None) { + APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { + + APValue(LValueBase B, ConstexprUnknown, const CharUnits &O, + bool IsNullPtr = false) + : Kind(None), AllowConstexprUnknown(true) { +MakeLValue(); +setLValue(B, O, NoLValuePath{}, IsNullPtr); + } + + APValue(UninitArray, unsigned InitElts, unsigned Size) + : Kind(None), AllowConstexprUnknown(false) { MakeArray(InitElts, Size); } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { + APValue(UninitStruct, unsigned B, unsigned M) + : Kind(None), AllowConstexprUnknown(false) { MakeStruct(B, M); } explicit APValue(const FieldDecl *D, const APValue &V = APValue()) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeUnion(); setUnion(D, V); } APValue(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) : Kind(None) { + ArrayRef Path) + : Kind(None), Allo
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
shafik wrote: Just merged in main since it has been so long in prep for updates https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/shafik updated https://github.com/llvm/llvm-project/pull/95474 >From 69b09ea5b0f0a1c5419c488ade29b6fedc6de773 Mon Sep 17 00:00:00 2001 From: Shafik Yaghmour Date: Thu, 13 Jun 2024 14:20:50 -0700 Subject: [PATCH 1/6] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions P2280R4 allows the use of references in pointers of unknown origins in a constant expression context but only in specific cases that could be constant expressions. We track whether a variable is a constexpr unknown in a constant expression by setting a flag in either APValue or LValue and using this flag to prevent using unknown values in places where it is not allowed. In `evaluateVarDeclInit` we may need to create a new `APValue` to track the unknown referene or pointer and we track that `APValue` in the `CallStackFrame`. Fixes: https://github.com/llvm/llvm-project/issues/63139 https://github.com/llvm/llvm-project/issues/63117 --- clang/include/clang/AST/APValue.h | 48 +++ clang/lib/AST/APValue.cpp | 12 ++- clang/lib/AST/ExprConstant.cpp| 85 +-- .../SemaCXX/constant-expression-cxx11.cpp | 16 ++-- .../SemaCXX/constant-expression-cxx2a.cpp | 3 +- .../SemaCXX/constant-expression-p2280r4.cpp | 54 6 files changed, 183 insertions(+), 35 deletions(-) create mode 100644 clang/test/SemaCXX/constant-expression-p2280r4.cpp diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index c4206b73b11562..6352348107a647 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -249,6 +249,7 @@ class APValue { struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + struct ConstexprUnknown {}; template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; @@ -256,6 +257,7 @@ class APValue { private: ValueKind Kind; + bool AllowConstexprUnknown = false; struct ComplexAPSInt { APSInt Real, Imag; @@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } + + APValue() : Kind(None), AllowConstexprUnknown(false) {} + explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(None) { + explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(APFixedPoint FX) : Kind(None) { + explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { MakeFixedPoint(std::move(FX)); } - explicit APValue(const APValue *E, unsigned N) : Kind(None) { + explicit APValue(const APValue *E, unsigned N) + : Kind(None), AllowConstexprUnknown(false) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(None) { + APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(None) { + APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { + + APValue(LValueBase B, ConstexprUnknown, const CharUnits &O, + bool IsNullPtr = false) + : Kind(None), AllowConstexprUnknown(true) { +MakeLValue(); +setLValue(B, O, NoLValuePath{}, IsNullPtr); + } + + APValue(UninitArray, unsigned InitElts, unsigned Size) + : Kind(None), AllowConstexprUnknown(false) { MakeArray(InitElts, Size); } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { + APValue(UninitStruct, unsigned B, unsigned M) + : Kind(None), AllowConstexprUnknown(false) { MakeStruct(B, M); } explicit APValue(const FieldDecl *D, const APValue &V = APValue()) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeUnion(); setUnion(D, V); } APValue(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) : Kind(None) { + ArrayRef Path) + : Kind(None), Allo
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/namniav edited https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/cor3ntin edited https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -1917,6 +1929,16 @@ APValue &CallStackFrame::createTemporary(const KeyT *Key, QualType T, return createLocal(Base, Key, T, Scope); } +APValue & +CallStackFrame::createConstexprUnknownAPValues(const VarDecl *Key, + APValue::LValueBase Base) { + APValue &Result = ConstexprUnknownAPValues[MapKeyTy(Key, Base.getVersion())]; + Result = APValue(Base, APValue::ConstexprUnknown{}, CharUnits::One()); + Result.setConstexprUnknown(); cor3ntin wrote: Yesm i think it can just be removed https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -0,0 +1,118 @@ +// RUN: %clang_cc1 -std=c++23 -verify %s + +using size_t = decltype(sizeof(0)); + +namespace std { +struct type_info { + const char* name() const noexcept(true); +}; +} + +template +constexpr size_t array_size(T (&)[N]) { + return N; +} + +void use_array(int const (&gold_medal_mel)[2]) { + constexpr auto gold = array_size(gold_medal_mel); // ok +} + +constexpr auto olympic_mile() { + const int ledecky = 1500; + return []{ return ledecky; }; +} +static_assert(olympic_mile()() == 1500); // ok + +struct Swim { + constexpr int phelps() { return 28; } + virtual constexpr int lochte() { return 12; } + int coughlin = 12; +}; + +constexpr int how_many(Swim& swam) { + Swim* p = &swam; + return (p + 1 - 1)->phelps(); +} + +void splash(Swim& swam) { + static_assert(swam.phelps() == 28); // ok + static_assert((&swam)->phelps() == 28); // ok + Swim* pswam = &swam;// expected-note {{declared here}} + static_assert(pswam->phelps() == 28); // expected-error {{static assertion expression is not an integral constant expression}} + // expected-note@-1 {{read of non-constexpr variable 'pswam' is not allowed in a constant expression}} + static_assert(how_many(swam) == 28);// ok + static_assert(Swim().lochte() == 12); // ok + static_assert(swam.lochte() == 12); // expected-error {{static assertion expression is not an integral constant expression}} tbaederr wrote: Why does this not work? https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } cor3ntin wrote: I think i would prefer it, yes https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } shafik wrote: It seems unnecessary but if we think this is a sufficiently common idiom (to pass in a bool argument, give it a default value and only ever use the defaulted version of it then I can do it). https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } + + APValue() : Kind(None), AllowConstexprUnknown(false) {} + explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(None) { + explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(APFixedPoint FX) : Kind(None) { + explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { MakeFixedPoint(std::move(FX)); } - explicit APValue(const APValue *E, unsigned N) : Kind(None) { + explicit APValue(const APValue *E, unsigned N) + : Kind(None), AllowConstexprUnknown(false) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(None) { + APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(None) { + APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { shafik wrote: Since we are now using a bit-field, initializing a bit-field using a default member initializer is a C++20 extension. https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -1917,6 +1929,16 @@ APValue &CallStackFrame::createTemporary(const KeyT *Key, QualType T, return createLocal(Base, Key, T, Scope); } +APValue & +CallStackFrame::createConstexprUnknownAPValues(const VarDecl *Key, + APValue::LValueBase Base) { + APValue &Result = ConstexprUnknownAPValues[MapKeyTy(Key, Base.getVersion())]; + Result = APValue(Base, APValue::ConstexprUnknown{}, CharUnits::One()); + Result.setConstexprUnknown(); shafik wrote: I might not need that anymore, there was a point where it was ambiguous with the other `APValue` constructors taking `LValueBase`. https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/shafik updated https://github.com/llvm/llvm-project/pull/95474 >From 69b09ea5b0f0a1c5419c488ade29b6fedc6de773 Mon Sep 17 00:00:00 2001 From: Shafik Yaghmour Date: Thu, 13 Jun 2024 14:20:50 -0700 Subject: [PATCH 1/5] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions P2280R4 allows the use of references in pointers of unknown origins in a constant expression context but only in specific cases that could be constant expressions. We track whether a variable is a constexpr unknown in a constant expression by setting a flag in either APValue or LValue and using this flag to prevent using unknown values in places where it is not allowed. In `evaluateVarDeclInit` we may need to create a new `APValue` to track the unknown referene or pointer and we track that `APValue` in the `CallStackFrame`. Fixes: https://github.com/llvm/llvm-project/issues/63139 https://github.com/llvm/llvm-project/issues/63117 --- clang/include/clang/AST/APValue.h | 48 +++ clang/lib/AST/APValue.cpp | 12 ++- clang/lib/AST/ExprConstant.cpp| 85 +-- .../SemaCXX/constant-expression-cxx11.cpp | 16 ++-- .../SemaCXX/constant-expression-cxx2a.cpp | 3 +- .../SemaCXX/constant-expression-p2280r4.cpp | 54 6 files changed, 183 insertions(+), 35 deletions(-) create mode 100644 clang/test/SemaCXX/constant-expression-p2280r4.cpp diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index c4206b73b1156..6352348107a64 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -249,6 +249,7 @@ class APValue { struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + struct ConstexprUnknown {}; template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; @@ -256,6 +257,7 @@ class APValue { private: ValueKind Kind; + bool AllowConstexprUnknown = false; struct ComplexAPSInt { APSInt Real, Imag; @@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } + + APValue() : Kind(None), AllowConstexprUnknown(false) {} + explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(None) { + explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(APFixedPoint FX) : Kind(None) { + explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { MakeFixedPoint(std::move(FX)); } - explicit APValue(const APValue *E, unsigned N) : Kind(None) { + explicit APValue(const APValue *E, unsigned N) + : Kind(None), AllowConstexprUnknown(false) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(None) { + APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(None) { + APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { + + APValue(LValueBase B, ConstexprUnknown, const CharUnits &O, + bool IsNullPtr = false) + : Kind(None), AllowConstexprUnknown(true) { +MakeLValue(); +setLValue(B, O, NoLValuePath{}, IsNullPtr); + } + + APValue(UninitArray, unsigned InitElts, unsigned Size) + : Kind(None), AllowConstexprUnknown(false) { MakeArray(InitElts, Size); } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { + APValue(UninitStruct, unsigned B, unsigned M) + : Kind(None), AllowConstexprUnknown(false) { MakeStruct(B, M); } explicit APValue(const FieldDecl *D, const APValue &V = APValue()) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeUnion(); setUnion(D, V); } APValue(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) : Kind(None) { + ArrayRef Path) + : Kind(None), AllowC
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/shafik updated https://github.com/llvm/llvm-project/pull/95474 >From 69b09ea5b0f0a1c5419c488ade29b6fedc6de773 Mon Sep 17 00:00:00 2001 From: Shafik Yaghmour Date: Thu, 13 Jun 2024 14:20:50 -0700 Subject: [PATCH 1/4] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions P2280R4 allows the use of references in pointers of unknown origins in a constant expression context but only in specific cases that could be constant expressions. We track whether a variable is a constexpr unknown in a constant expression by setting a flag in either APValue or LValue and using this flag to prevent using unknown values in places where it is not allowed. In `evaluateVarDeclInit` we may need to create a new `APValue` to track the unknown referene or pointer and we track that `APValue` in the `CallStackFrame`. Fixes: https://github.com/llvm/llvm-project/issues/63139 https://github.com/llvm/llvm-project/issues/63117 --- clang/include/clang/AST/APValue.h | 48 +++ clang/lib/AST/APValue.cpp | 12 ++- clang/lib/AST/ExprConstant.cpp| 85 +-- .../SemaCXX/constant-expression-cxx11.cpp | 16 ++-- .../SemaCXX/constant-expression-cxx2a.cpp | 3 +- .../SemaCXX/constant-expression-p2280r4.cpp | 54 6 files changed, 183 insertions(+), 35 deletions(-) create mode 100644 clang/test/SemaCXX/constant-expression-p2280r4.cpp diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index c4206b73b1156..6352348107a64 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -249,6 +249,7 @@ class APValue { struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + struct ConstexprUnknown {}; template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; @@ -256,6 +257,7 @@ class APValue { private: ValueKind Kind; + bool AllowConstexprUnknown = false; struct ComplexAPSInt { APSInt Real, Imag; @@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } + + APValue() : Kind(None), AllowConstexprUnknown(false) {} + explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(None) { + explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(APFixedPoint FX) : Kind(None) { + explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { MakeFixedPoint(std::move(FX)); } - explicit APValue(const APValue *E, unsigned N) : Kind(None) { + explicit APValue(const APValue *E, unsigned N) + : Kind(None), AllowConstexprUnknown(false) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(None) { + APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(None) { + APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { + + APValue(LValueBase B, ConstexprUnknown, const CharUnits &O, + bool IsNullPtr = false) + : Kind(None), AllowConstexprUnknown(true) { +MakeLValue(); +setLValue(B, O, NoLValuePath{}, IsNullPtr); + } + + APValue(UninitArray, unsigned InitElts, unsigned Size) + : Kind(None), AllowConstexprUnknown(false) { MakeArray(InitElts, Size); } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { + APValue(UninitStruct, unsigned B, unsigned M) + : Kind(None), AllowConstexprUnknown(false) { MakeStruct(B, M); } explicit APValue(const FieldDecl *D, const APValue &V = APValue()) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeUnion(); setUnion(D, V); } APValue(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) : Kind(None) { + ArrayRef Path) + : Kind(None), AllowC
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff d4a0154902fb9b0611ed857134b26a64a1d5ad1e 3c944c05fded091f9488a9786bc80c57e291b6ed --extensions h,cpp -- clang/test/SemaCXX/constant-expression-p2280r4.cpp clang/include/clang/AST/APValue.h clang/lib/AST/APValue.cpp clang/lib/AST/ExprConstant.cpp clang/test/SemaCXX/constant-expression-cxx11.cpp clang/test/SemaCXX/constant-expression-cxx2a.cpp `` View the diff from clang-format here. ``diff diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index a7e2cc455e..424df336f2 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -13654,9 +13654,10 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, return false; // If we have Unknown pointers we should fail if they are not global values. -if (!(IsGlobalLValue(LHSValue.getLValueBase()) && IsGlobalLValue(RHSValue.getLValueBase())) && - (LHSValue.AllowConstexprUnknown || RHSValue.AllowConstexprUnknown)) - return false; +if (!(IsGlobalLValue(LHSValue.getLValueBase()) && + IsGlobalLValue(RHSValue.getLValueBase())) && +(LHSValue.AllowConstexprUnknown || RHSValue.AllowConstexprUnknown)) + return false; // Reject differing bases from the normal codepath; we special-case // comparisons to null. `` https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/shafik updated https://github.com/llvm/llvm-project/pull/95474 >From 69b09ea5b0f0a1c5419c488ade29b6fedc6de773 Mon Sep 17 00:00:00 2001 From: Shafik Yaghmour Date: Thu, 13 Jun 2024 14:20:50 -0700 Subject: [PATCH 1/2] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions P2280R4 allows the use of references in pointers of unknown origins in a constant expression context but only in specific cases that could be constant expressions. We track whether a variable is a constexpr unknown in a constant expression by setting a flag in either APValue or LValue and using this flag to prevent using unknown values in places where it is not allowed. In `evaluateVarDeclInit` we may need to create a new `APValue` to track the unknown referene or pointer and we track that `APValue` in the `CallStackFrame`. Fixes: https://github.com/llvm/llvm-project/issues/63139 https://github.com/llvm/llvm-project/issues/63117 --- clang/include/clang/AST/APValue.h | 48 +++ clang/lib/AST/APValue.cpp | 12 ++- clang/lib/AST/ExprConstant.cpp| 85 +-- .../SemaCXX/constant-expression-cxx11.cpp | 16 ++-- .../SemaCXX/constant-expression-cxx2a.cpp | 3 +- .../SemaCXX/constant-expression-p2280r4.cpp | 54 6 files changed, 183 insertions(+), 35 deletions(-) create mode 100644 clang/test/SemaCXX/constant-expression-p2280r4.cpp diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index c4206b73b1156..6352348107a64 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -249,6 +249,7 @@ class APValue { struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + struct ConstexprUnknown {}; template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; @@ -256,6 +257,7 @@ class APValue { private: ValueKind Kind; + bool AllowConstexprUnknown = false; struct ComplexAPSInt { APSInt Real, Imag; @@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } + + APValue() : Kind(None), AllowConstexprUnknown(false) {} + explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(None) { + explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(APFixedPoint FX) : Kind(None) { + explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { MakeFixedPoint(std::move(FX)); } - explicit APValue(const APValue *E, unsigned N) : Kind(None) { + explicit APValue(const APValue *E, unsigned N) + : Kind(None), AllowConstexprUnknown(false) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(None) { + APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(None) { + APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { + + APValue(LValueBase B, ConstexprUnknown, const CharUnits &O, + bool IsNullPtr = false) + : Kind(None), AllowConstexprUnknown(true) { +MakeLValue(); +setLValue(B, O, NoLValuePath{}, IsNullPtr); + } + + APValue(UninitArray, unsigned InitElts, unsigned Size) + : Kind(None), AllowConstexprUnknown(false) { MakeArray(InitElts, Size); } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { + APValue(UninitStruct, unsigned B, unsigned M) + : Kind(None), AllowConstexprUnknown(false) { MakeStruct(B, M); } explicit APValue(const FieldDecl *D, const APValue &V = APValue()) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeUnion(); setUnion(D, V); } APValue(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) : Kind(None) { + ArrayRef Path) + : Kind(None), AllowC
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
Endilll wrote: Shafik contacted me offline about a libc++ test failure this PR causes. The test in question is `mem.res.eq/not_equal_pass.cpp`. I reduced it down to the following: ```cpp struct memory_resource { virtual ~memory_resource(); bool is_equal(const memory_resource &) const noexcept; }; inline bool operator==(const memory_resource &__lhs, const memory_resource &__rhs) { return &__lhs == &__rhs || __lhs.is_equal(__rhs); // frontend built from this branch believes that this is never true } void __assert_fail(); struct TestResourceImp : memory_resource { memory_resource do_is_equal_other; virtual bool do_is_equal() noexcept { return dynamic_cast(&do_is_equal_other); } }; int main() { memory_resource mr1, mr2; mr1 != mr2 ? void() : __assert_fail(); } ``` Clang built from this branch produces the following IR for `operator==` ```llvm ; Function Attrs: mustprogress noinline nounwind optnone uwtable define linkonce_odr dso_local noundef zeroext i1 @_ZeqRK15memory_resourceS1_(ptr noundef nonnull align 8 dereferenceable(8) %__lhs, ptr noundef nonnull align 8 dereferenceable(8) %__rhs) #1 comdat { entry: %__lhs.addr = alloca ptr, align 8 %__rhs.addr = alloca ptr, align 8 store ptr %__lhs, ptr %__lhs.addr, align 8 store ptr %__rhs, ptr %__rhs.addr, align 8 %0 = load ptr, ptr %__lhs.addr, align 8 %1 = load ptr, ptr %__rhs.addr, align 8 %call = call noundef zeroext i1 @_ZNK15memory_resource8is_equalERKS_(ptr noundef nonnull align 8 dereferenceable(8) %0, ptr noundef nonnull align 8 dereferenceable(8) %1) #4 ret i1 %call } ``` Whereas a recent nighly build (`++20240704100628+b298e2d2d225-1~exp1~20240704220819.2190`) properly lowers the LHS of the logical OR: ```llvm ; Function Attrs: mustprogress noinline nounwind optnone uwtable define linkonce_odr dso_local noundef zeroext i1 @_ZeqRK15memory_resourceS1_(ptr noundef nonnull align 8 dereferenceable(8) %__lhs, ptr noundef nonnull align 8 dereferenceable(8) %__rhs) #1 comdat { entry: %__lhs.addr = alloca ptr, align 8 %__rhs.addr = alloca ptr, align 8 store ptr %__lhs, ptr %__lhs.addr, align 8 store ptr %__rhs, ptr %__rhs.addr, align 8 %0 = load ptr, ptr %__lhs.addr, align 8 %1 = load ptr, ptr %__rhs.addr, align 8 %cmp = icmp eq ptr %0, %1 br i1 %cmp, label %lor.end, label %lor.rhs lor.rhs: ; preds = %entry %2 = load ptr, ptr %__lhs.addr, align 8 %3 = load ptr, ptr %__rhs.addr, align 8 %call = call noundef zeroext i1 @_ZNK15memory_resource8is_equalERKS_(ptr noundef nonnull align 8 dereferenceable(8) %2, ptr noundef nonnull align 8 dereferenceable(8) %3) #4 br label %lor.end lor.end: ; preds = %lor.rhs, %entry %4 = phi i1 [ true, %entry ], [ %call, %lor.rhs ] ret i1 %4 } ``` https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/shafik updated https://github.com/llvm/llvm-project/pull/95474 >From 69b09ea5b0f0a1c5419c488ade29b6fedc6de773 Mon Sep 17 00:00:00 2001 From: Shafik Yaghmour Date: Thu, 13 Jun 2024 14:20:50 -0700 Subject: [PATCH] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions P2280R4 allows the use of references in pointers of unknown origins in a constant expression context but only in specific cases that could be constant expressions. We track whether a variable is a constexpr unknown in a constant expression by setting a flag in either APValue or LValue and using this flag to prevent using unknown values in places where it is not allowed. In `evaluateVarDeclInit` we may need to create a new `APValue` to track the unknown referene or pointer and we track that `APValue` in the `CallStackFrame`. Fixes: https://github.com/llvm/llvm-project/issues/63139 https://github.com/llvm/llvm-project/issues/63117 --- clang/include/clang/AST/APValue.h | 48 +++ clang/lib/AST/APValue.cpp | 12 ++- clang/lib/AST/ExprConstant.cpp| 85 +-- .../SemaCXX/constant-expression-cxx11.cpp | 16 ++-- .../SemaCXX/constant-expression-cxx2a.cpp | 3 +- .../SemaCXX/constant-expression-p2280r4.cpp | 54 6 files changed, 183 insertions(+), 35 deletions(-) create mode 100644 clang/test/SemaCXX/constant-expression-p2280r4.cpp diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index c4206b73b1156..6352348107a64 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -249,6 +249,7 @@ class APValue { struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + struct ConstexprUnknown {}; template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; @@ -256,6 +257,7 @@ class APValue { private: ValueKind Kind; + bool AllowConstexprUnknown = false; struct ComplexAPSInt { APSInt Real, Imag; @@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } + + APValue() : Kind(None), AllowConstexprUnknown(false) {} + explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(None) { + explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(APFixedPoint FX) : Kind(None) { + explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { MakeFixedPoint(std::move(FX)); } - explicit APValue(const APValue *E, unsigned N) : Kind(None) { + explicit APValue(const APValue *E, unsigned N) + : Kind(None), AllowConstexprUnknown(false) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(None) { + APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(None) { + APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { + + APValue(LValueBase B, ConstexprUnknown, const CharUnits &O, + bool IsNullPtr = false) + : Kind(None), AllowConstexprUnknown(true) { +MakeLValue(); +setLValue(B, O, NoLValuePath{}, IsNullPtr); + } + + APValue(UninitArray, unsigned InitElts, unsigned Size) + : Kind(None), AllowConstexprUnknown(false) { MakeArray(InitElts, Size); } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { + APValue(UninitStruct, unsigned B, unsigned M) + : Kind(None), AllowConstexprUnknown(false) { MakeStruct(B, M); } explicit APValue(const FieldDecl *D, const APValue &V = APValue()) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeUnion(); setUnion(D, V); } APValue(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) : Kind(None) { + ArrayRef Path) + : Kind(None), AllowConst
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -249,13 +249,15 @@ class APValue { struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + struct ConstexprUnknown {}; template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; friend class ASTNodeImporter; private: ValueKind Kind; + bool AllowConstexprUnknown = false; shafik wrote: Initializing a bit-field inline is a C++20 extension and so I don't think I can use it. I set `AllowConstexprUnknown` everyplace I thought it mattered in `APValue` but I obtain different results. It means I am missing someplace where `APValue` is being initialized. I can try again and see if I can hunt down the places I missed but it left me a bit spooked that it was not obvious. https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/shafik deleted https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -249,13 +249,15 @@ class APValue { struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + struct ConstexprUnknown {}; template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; friend class ASTNodeImporter; private: ValueKind Kind; + bool AllowConstexprUnknown = false; shafik wrote: Initializing a bit-field inline is a C++20 extension and it got messy when I tried to do the init manually but I can look at it again now that this is a much simpler set of code. https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -249,13 +249,15 @@ class APValue { struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + struct ConstexprUnknown {}; template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; friend class ASTNodeImporter; private: ValueKind Kind; + bool AllowConstexprUnknown = false; AaronBallman wrote: Would it make sense to use a bit-field here so we can pack this bit together with the `Kind`? https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/AaronBallman commented: Generally seems like a reasonable direction, thank you! https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/AaronBallman edited https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
cor3ntin wrote: > Thank you work on this! I really like this feature. Will this PR also provide > support for the new constant interpreter? The new constant interpreter seems > to already support some unknown constexpr features (FYI > https://godbolt.org/z/xTYhGEfxT). It has the concept of `DummyValue`. I think that can be a separate PR @tbaederr https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
yronglin wrote: Thank you work on this! I really like this feature. Will this PR also provide support for the new constant interpreter? The new constant interpreter seems to already support some unknown constexpr features (FYI https://godbolt.org/z/xTYhGEfxT). https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -3420,6 +3441,15 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, } Result = VD->getEvaluatedValue(); + + // P2280R4 If we don't have a value because this is a reference that was not + // initialized or whose lifetime began within E then create a value with as + // a ConstexprUnknown status. + if (AllowConstexprUnknown) { +if (!Result) { + Result = new APValue(Base, APValue::ConstexprUnknown{}, CharUnits::One()); +} + } shafik wrote: Yes, this is a good point. When I started this a while ago I realized I needed to refactor this but I lost track of it since then. I think I need to use `createTemporary(...)` or something along those lines. https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } cor3ntin wrote: nitpick: I think the setter should take a bool https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -3300,6 +3308,11 @@ static bool HandleLValueComplexElement(EvalInfo &Info, const Expr *E, static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, const VarDecl *VD, CallStackFrame *Frame, unsigned Version, APValue *&Result) { + // P2280R4 If we have a reference type and we are in C++23 allow unknown + // references and pointers. + bool AllowConstexprUnknown = + Info.getLangOpts().CPlusPlus23 && VD->getType()->isReferenceType(); cor3ntin wrote: Additionally, I would prefer references to the c++ standard wording rather than the paper https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -8595,7 +8643,10 @@ bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { - + // P2280R4 if we are in C++23 track if we have an unknown reference or + // pointer. + bool AllowConstexprUnknown = + Info.getLangOpts().CPlusPlus23 && VD->getType()->isReferenceType(); cor3ntin wrote: Same comment as above for the DR/comment https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } + + APValue() : Kind(None), AllowConstexprUnknown(false) {} + explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(None) { + explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(APFixedPoint FX) : Kind(None) { + explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { MakeFixedPoint(std::move(FX)); } - explicit APValue(const APValue *E, unsigned N) : Kind(None) { + explicit APValue(const APValue *E, unsigned N) + : Kind(None), AllowConstexprUnknown(false) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(None) { + APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(None) { + APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { + + APValue(LValueBase B, ConstexprUnknown, const CharUnits &O, + bool IsNullPtr = false) + : Kind(None), AllowConstexprUnknown(true) { +MakeLValue(); +setLValue(B, O, NoLValuePath{}, IsNullPtr); + } + + APValue(UninitArray, unsigned InitElts, unsigned Size) + : Kind(None), AllowConstexprUnknown(false) { MakeArray(InitElts, Size); } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { + APValue(UninitStruct, unsigned B, unsigned M) + : Kind(None), AllowConstexprUnknown(false) { MakeStruct(B, M); } explicit APValue(const FieldDecl *D, const APValue &V = APValue()) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeUnion(); setUnion(D, V); } APValue(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) : Kind(None) { + ArrayRef Path) + : Kind(None), AllowConstexprUnknown(false) { MakeMemberPointer(Member, IsDerivedMember, Path); } - APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) - : Kind(None) { + APValue(const AddrLabelExpr *LHSExpr, const AddrLabelExpr *RHSExpr) + : Kind(None), AllowConstexprUnknown(false) { cor3ntin wrote: Ditto https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } + + APValue() : Kind(None), AllowConstexprUnknown(false) {} + explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(None) { + explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(APFixedPoint FX) : Kind(None) { + explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { MakeFixedPoint(std::move(FX)); } - explicit APValue(const APValue *E, unsigned N) : Kind(None) { + explicit APValue(const APValue *E, unsigned N) + : Kind(None), AllowConstexprUnknown(false) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(None) { + APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(None) { + APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { cor3ntin wrote: No need to change these, that's what default member initializers are for! https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/cor3ntin edited https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/cor3ntin commented: Thanks a lot Shafik! I like the direction, it looks less complex than i thought it would be I agree with @frederick-vs-ja that some diagnostics seem to have regressed. Maybe a variable should not treated as constexpr-unknown if it's not within its lifetime I'd like you to go over all the related issues we have (including the ones we closed for duplication), to make sure they work as expected. i think they make up for a good corpus of unit tests We will need changelog / status page update Just to point it out, there are a few unresolved core issues https://cplusplus.github.io/CWG/issues/2740.html https://cplusplus.github.io/CWG/issues/2633.html https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -3420,6 +3441,15 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, } Result = VD->getEvaluatedValue(); + + // P2280R4 If we don't have a value because this is a reference that was not + // initialized or whose lifetime began within E then create a value with as + // a ConstexprUnknown status. + if (AllowConstexprUnknown) { +if (!Result) { + Result = new APValue(Base, APValue::ConstexprUnknown{}, CharUnits::One()); +} + } Fznamznon wrote: ```suggestion if (AllowConstexprUnknown && !Result) Result = new APValue(Base, APValue::ConstexprUnknown{}, CharUnits::One()); ``` https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -3358,7 +3373,9 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, // FIXME: We should eventually check whether the variable has a reachable // initializing declaration. const Expr *Init = VD->getAnyInitializer(VD); - if (!Init) { + // P2280R4 struck the restriction that variable of referene type should have Fznamznon wrote: ```suggestion // P2280R4 struck the restriction that variable of reference type should have ``` https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -3420,6 +3441,15 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, } Result = VD->getEvaluatedValue(); + + // P2280R4 If we don't have a value because this is a reference that was not + // initialized or whose lifetime began within E then create a value with as + // a ConstexprUnknown status. + if (AllowConstexprUnknown) { +if (!Result) { + Result = new APValue(Base, APValue::ConstexprUnknown{}, CharUnits::One()); +} + } Fznamznon wrote: I also wonder what part of clang will free memory allocated here? https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -3700,6 +3730,11 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, const FieldDecl *LastField = nullptr; const FieldDecl *VolatileField = nullptr; + // P2280R4 If we have an unknown referene or pointer and we don't have a Fznamznon wrote: ```suggestion // P2280R4 If we have an unknown reference or pointer and we don't have a ``` https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -3334,7 +3347,9 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, return true; } - if (isa(VD)) { + // P2280R4 struck the restriction that variable of referene type lifetime Fznamznon wrote: ```suggestion // P2280R4 struck the restriction that variable of reference type lifetime ``` Though I wonder if these comments should say struck if this was a DR https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/frederick-vs-ja edited https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -3300,6 +3308,11 @@ static bool HandleLValueComplexElement(EvalInfo &Info, const Expr *E, static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, const VarDecl *VD, CallStackFrame *Frame, unsigned Version, APValue *&Result) { + // P2280R4 If we have a reference type and we are in C++23 allow unknown + // references and pointers. + bool AllowConstexprUnknown = + Info.getLangOpts().CPlusPlus23 && VD->getType()->isReferenceType(); frederick-vs-ja wrote: This is a DR per [N4916](https://wg21.link/n4916) (ditto below). ```suggestion // P2280R4 allow unknown references and pointers. bool AllowConstexprUnknown = VD->getType()->isReferenceType(); ``` https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
@@ -1961,7 +1961,8 @@ namespace ConstexprConstructorRecovery { namespace Lifetime { void f() { -constexpr int &n = n; // expected-error {{constant expression}} expected-note {{use of reference outside its lifetime}} expected-warning {{not yet bound to a value}} +constexpr int &n = n; // expected-error {{constant expression}} cxx23-note {{reference to 'n' is not a constant expression}} cxx23-note {{address of non-static constexpr variable 'n' may differ}} expected-warning {{not yet bound to a value}} + // cxx11_20-note@-1 {{use of reference outside its lifetime is not allowed in a constant expression}} frederick-vs-ja wrote: This looks strange. The old message looks better (see also [CWG453](https://cplusplus.github.io/CWG/issues/453.html)) and the new one is possibly misleading as we perhaps shoudn't say the address of a reference variable. https://github.com/llvm/llvm-project/pull/95474 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Shafik Yaghmour (shafik) Changes P2280R4 allows the use of references in pointers of unknown origins in a constant expression context but only in specific cases that could be constant expressions. We track whether a variable is a constexpr unknown in a constant expression by setting a flag in either APValue or LValue and using this flag to prevent using unknown values in places where it is not allowed. Fixes: https://github.com/llvm/llvm-project/issues/63139 https://github.com/llvm/llvm-project/issues/63117 --- Patch is 21.02 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/95474.diff 6 Files Affected: - (modified) clang/include/clang/AST/APValue.h (+33-15) - (modified) clang/lib/AST/APValue.cpp (+10-2) - (modified) clang/lib/AST/ExprConstant.cpp (+76-9) - (modified) clang/test/SemaCXX/constant-expression-cxx11.cpp (+9-7) - (modified) clang/test/SemaCXX/constant-expression-cxx2a.cpp (+1-2) - (added) clang/test/SemaCXX/constant-expression-p2280r4.cpp (+54) ``diff diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index c4206b73b1156..6352348107a64 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -249,6 +249,7 @@ class APValue { struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + struct ConstexprUnknown {}; template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; @@ -256,6 +257,7 @@ class APValue { private: ValueKind Kind; + bool AllowConstexprUnknown = false; struct ComplexAPSInt { APSInt Real, Imag; @@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } + + APValue() : Kind(None), AllowConstexprUnknown(false) {} + explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(None) { + explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(APFixedPoint FX) : Kind(None) { + explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { MakeFixedPoint(std::move(FX)); } - explicit APValue(const APValue *E, unsigned N) : Kind(None) { + explicit APValue(const APValue *E, unsigned N) + : Kind(None), AllowConstexprUnknown(false) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(None) { + APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(None) { + APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { + + APValue(LValueBase B, ConstexprUnknown, const CharUnits &O, + bool IsNullPtr = false) + : Kind(None), AllowConstexprUnknown(true) { +MakeLValue(); +setLValue(B, O, NoLValuePath{}, IsNullPtr); + } + + APValue(UninitArray, unsigned InitElts, unsigned Size) + : Kind(None), AllowConstexprUnknown(false) { MakeArray(InitElts, Size); } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { + APValue(UninitStruct, unsigned B, unsigned M) + : Kind(None), AllowConstexprUnknown(false) { MakeStruct(B, M); } explicit APValue(const FieldDecl *D, const APValue &V = APValue()) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeUnion(); setUnion(D, V); } APValue(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) : Kind(None) { + ArrayRef Path) + : Kind(None), AllowConstexprUnknown(false) { MakeMemberPointer(Member, IsDerivedMember, Path); } - APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) - : Kind(None) { + APValue(const AddrLabelExpr *LHSExpr, const AddrLabelExpr *RHSExpr) + : Kind(None), AllowConstexprUnknown(false) { MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr
[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)
https://github.com/shafik created https://github.com/llvm/llvm-project/pull/95474 P2280R4 allows the use of references in pointers of unknown origins in a constant expression context but only in specific cases that could be constant expressions. We track whether a variable is a constexpr unknown in a constant expression by setting a flag in either APValue or LValue and using this flag to prevent using unknown values in places where it is not allowed. Fixes: https://github.com/llvm/llvm-project/issues/63139 https://github.com/llvm/llvm-project/issues/63117 >From 7583d32c023f38cd2b4c6a3fad3bea5e115e9905 Mon Sep 17 00:00:00 2001 From: Shafik Yaghmour Date: Thu, 13 Jun 2024 14:20:50 -0700 Subject: [PATCH] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions P2280R4 allows the use of references in pointers of unknown origins in a constant expression context but only in specific cases that could be constant expressions. We track whether a variable is a constexpr unknown in a constant expression by setting a flag in either APValue or LValue and using this flag to prevent using unknown values in places where it is not allowed. Fixes: https://github.com/llvm/llvm-project/issues/63139 https://github.com/llvm/llvm-project/issues/63117 --- clang/include/clang/AST/APValue.h | 48 +++ clang/lib/AST/APValue.cpp | 12 ++- clang/lib/AST/ExprConstant.cpp| 85 +-- .../SemaCXX/constant-expression-cxx11.cpp | 16 ++-- .../SemaCXX/constant-expression-cxx2a.cpp | 3 +- .../SemaCXX/constant-expression-p2280r4.cpp | 54 6 files changed, 183 insertions(+), 35 deletions(-) create mode 100644 clang/test/SemaCXX/constant-expression-p2280r4.cpp diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index c4206b73b1156..6352348107a64 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -249,6 +249,7 @@ class APValue { struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + struct ConstexprUnknown {}; template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; @@ -256,6 +257,7 @@ class APValue { private: ValueKind Kind; + bool AllowConstexprUnknown = false; struct ComplexAPSInt { APSInt Real, Imag; @@ -314,53 +316,69 @@ class APValue { DataType Data; public: - APValue() : Kind(None) {} - explicit APValue(APSInt I) : Kind(None) { + bool allowConstexprUnknown() const { return AllowConstexprUnknown; } + + void setConstexprUnknown() { AllowConstexprUnknown = true; } + + APValue() : Kind(None), AllowConstexprUnknown(false) {} + explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(None) { + explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(APFixedPoint FX) : Kind(None) { + explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { MakeFixedPoint(std::move(FX)); } - explicit APValue(const APValue *E, unsigned N) : Kind(None) { + explicit APValue(const APValue *E, unsigned N) + : Kind(None), AllowConstexprUnknown(false) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(None) { + APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(None) { + APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(None) { + : Kind(None), AllowConstexprUnknown(false) { MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { + + APValue(LValueBase B, ConstexprUnknown, const CharUnits &O, + bool IsNullPtr = false) + : Kind(None), AllowConstexprUnknown(true) { +MakeLValue(); +setLValue(B, O, NoLValuePath{}, IsNullPtr); + } + + APValue(UninitArray, unsigned InitElts, unsigned Size) + : Kind(None), AllowConstexprUnknown(false) { MakeArray(InitElts, Size); } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { + APValue(UninitStruct, unsigned B, unsigned M) + : Kind(None), AllowConstexprUnknown(false) { MakeStruct(B, M); } explic