[clang] [Clang] Implement P2280R4 Using unknown pointers and references in constant expressions (PR #95474)

2025-06-03 Thread Shafik Yaghmour via cfe-commits

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)

2025-05-30 Thread Tyler Rockwood via cfe-commits

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)

2025-05-19 Thread Richard Smith via cfe-commits

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)

2025-05-19 Thread Shafik Yaghmour via cfe-commits

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)

2025-05-19 Thread Akira Hatanaka via cfe-commits

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)

2025-05-19 Thread Richard Smith via cfe-commits

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)

2025-05-19 Thread Akira Hatanaka via cfe-commits

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)

2025-05-15 Thread Akira Hatanaka via cfe-commits

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)

2025-05-15 Thread Alon Zakai via cfe-commits

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)

2025-05-11 Thread Konstantin Bogdanov via cfe-commits

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)

2025-05-01 Thread Richard Smith via cfe-commits

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)

2025-05-01 Thread Akira Hatanaka via cfe-commits

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)

2025-05-01 Thread Richard Smith via cfe-commits

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)

2025-05-01 Thread Akira Hatanaka via cfe-commits

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)

2025-01-22 Thread LLVM Continuous Integration via cfe-commits

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)

2025-01-22 Thread LLVM Continuous Integration via cfe-commits

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)

2025-01-22 Thread LLVM Continuous Integration via cfe-commits

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)

2025-01-22 Thread Timm Baeder via cfe-commits

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)

2025-01-22 Thread Jan Patrick Lehr via cfe-commits

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)

2025-01-22 Thread via cfe-commits

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)

2025-01-22 Thread LLVM Continuous Integration via cfe-commits

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)

2025-01-22 Thread LLVM Continuous Integration via cfe-commits

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)

2025-01-22 Thread LLVM Continuous Integration via cfe-commits

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)

2025-01-22 Thread via cfe-commits

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)

2025-01-22 Thread via cfe-commits

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)

2025-01-20 Thread via cfe-commits

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)

2024-12-28 Thread via cfe-commits


@@ -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)

2024-12-20 Thread Shafik Yaghmour via cfe-commits

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)

2024-12-20 Thread via cfe-commits


@@ -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)

2024-12-20 Thread via cfe-commits


@@ -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)

2024-12-20 Thread via cfe-commits

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)

2024-12-20 Thread via cfe-commits

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)

2024-12-20 Thread Shafik Yaghmour via cfe-commits

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)

2024-12-19 Thread Shafik Yaghmour via cfe-commits

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)

2024-12-19 Thread Shafik Yaghmour via cfe-commits

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)

2024-12-18 Thread Shafik Yaghmour via cfe-commits

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)

2024-12-18 Thread Shafik Yaghmour via cfe-commits

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)

2024-12-18 Thread Shafik Yaghmour via cfe-commits

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)

2024-12-18 Thread Shafik Yaghmour via cfe-commits

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)

2024-12-18 Thread Shafik Yaghmour via cfe-commits

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)

2024-09-07 Thread via cfe-commits

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)

2024-09-07 Thread via cfe-commits

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)

2024-09-07 Thread via cfe-commits


@@ -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)

2024-09-04 Thread Timm Baeder via cfe-commits


@@ -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)

2024-08-05 Thread via cfe-commits


@@ -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)

2024-07-30 Thread Shafik Yaghmour via cfe-commits


@@ -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)

2024-07-30 Thread Shafik Yaghmour via cfe-commits


@@ -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)

2024-07-30 Thread Shafik Yaghmour via cfe-commits


@@ -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)

2024-07-30 Thread Shafik Yaghmour via cfe-commits

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)

2024-07-29 Thread Shafik Yaghmour via cfe-commits

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)

2024-07-29 Thread via cfe-commits

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)

2024-07-29 Thread Shafik Yaghmour via cfe-commits

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)

2024-07-27 Thread Vlad Serebrennikov via cfe-commits

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)

2024-07-17 Thread Shafik Yaghmour via cfe-commits

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)

2024-07-09 Thread Shafik Yaghmour via cfe-commits


@@ -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)

2024-07-09 Thread Shafik Yaghmour via cfe-commits

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)

2024-07-09 Thread Shafik Yaghmour via cfe-commits


@@ -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)

2024-07-08 Thread Aaron Ballman via cfe-commits


@@ -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)

2024-07-08 Thread Aaron Ballman via cfe-commits

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)

2024-07-08 Thread Aaron Ballman via cfe-commits

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)

2024-07-06 Thread via cfe-commits

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)

2024-07-01 Thread via cfe-commits

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)

2024-06-14 Thread Shafik Yaghmour via cfe-commits


@@ -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)

2024-06-14 Thread via cfe-commits


@@ -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)

2024-06-14 Thread via cfe-commits


@@ -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)

2024-06-14 Thread via cfe-commits


@@ -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)

2024-06-14 Thread via cfe-commits


@@ -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)

2024-06-14 Thread via cfe-commits


@@ -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)

2024-06-14 Thread via cfe-commits

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)

2024-06-14 Thread via cfe-commits

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)

2024-06-14 Thread Mariya Podchishchaeva via cfe-commits


@@ -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)

2024-06-14 Thread Mariya Podchishchaeva via cfe-commits


@@ -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)

2024-06-14 Thread Mariya Podchishchaeva via cfe-commits


@@ -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)

2024-06-14 Thread Mariya Podchishchaeva via cfe-commits


@@ -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)

2024-06-14 Thread Mariya Podchishchaeva via cfe-commits


@@ -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)

2024-06-13 Thread A. Jiang via cfe-commits

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)

2024-06-13 Thread A. Jiang via cfe-commits


@@ -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)

2024-06-13 Thread A. Jiang via cfe-commits


@@ -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)

2024-06-13 Thread via cfe-commits

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)

2024-06-13 Thread Shafik Yaghmour via cfe-commits

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