[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning< def err_objc_object_assignment : Error< "cannot assign to class object (%0 invalid)">; +def err_typecheck_array_prvalue_operand : Error< + "array prvalue is not permitted">; languagelawyer wrote: > invalid operands to binary expression BTW, I think it is either "**in** binary expression" or "to binary **operator**" https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning<
def err_objc_object_assignment : Error<
"cannot assign to class object (%0 invalid)">;
+def err_typecheck_array_prvalue_operand : Error<
+ "array prvalue is not permitted">;
languagelawyer wrote:
> keeping in mind that `foo{}` could also be behind a macro
I doubt that presenting exact array type vs. just saying "array" would help
much in this case. There is `note: expanded from macro` to point that something
comes from macro expansion. (Not shown for `err_typecheck_invalid_operands`,
BTW!)
> `err_typecheck_invalid_operands` is the better approach here
```c++
int main()
{
using IA = int[];
IA ia = { 1, 2, 3 };
ia + 0.; // error: invalid operands to binary expression ('int[3]' and
'double')
// Where is the problem? in 'int[3]' or in 'double'?
ia + 0; // no error means the issue was in 'double'?
IA{ 1, 2, 3 } + 0; // error: invalid operands to binary expression
('int[3]' and 'int')
// Huh? What about now?
}
```
> But ultimately, `int[]` + `int` is what we should diagnose
The types are not the issue, why give misleading diagnostics?
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning< def err_objc_object_assignment : Error< "cannot assign to class object (%0 invalid)">; +def err_typecheck_array_prvalue_operand : Error< + "array prvalue is not permitted">; cor3ntin wrote: I agree with @AaronBallman and @Sirraide that using `err_typecheck_invalid_operands` is the better approach here. The "prvalue" bit is only relevant as far as array decay is concerned (eg : array-to-pointer does not apply). But ultimately, `int[]` + `int` is what we should diagnose, not how we got here. https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning<
def err_objc_object_assignment : Error<
"cannot assign to class object (%0 invalid)">;
+def err_typecheck_array_prvalue_operand : Error<
+ "array prvalue is not permitted">;
AaronBallman wrote:
>> if you're coming from a C background
> What about Python/Java background?
They're not particularly relevant because you don't directly mix Java and C++
code in the same way you do with C and C++ as happens in header files.
>> IIRC there's no rvalue conversion on the statement expression result so I
>> think that ends up being a prvalue of array type
> This is not correct, statement expressions (their "result") undergo array and
> function pointer decay (independently of the context where they appear), so
> you're getting a "dangling pointer"
I was incorrectly remembering the behavior from returning a `char` and not
having it promote to an `int`. I can confirm we decay the array:
https://godbolt.org/z/zhW1fnsej but you can hit the same concern I had via a
`typedef` or `using`, where the type information is actually slightly helpful
in understanding the issue: `using foo = int[10]; foo{} + 0;` (keeping in mind
that `foo{}` could also be behind a macro where it's not easy for the user to
spot the `{}` and realize there's a temporary involved). So I still find a
formulation that includes the type information a bit more user-friendly, but
that could be included in a new diagnostic that talks about temporary arrays.
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning<
def err_objc_object_assignment : Error<
"cannot assign to class object (%0 invalid)">;
+def err_typecheck_array_prvalue_operand : Error<
+ "array prvalue is not permitted">;
AaronBallman wrote:
It's better than "array prvalue" but if you're coming from a C background,
that's not going to look like a temporary array to you, either.
What kind of diagnostic would we get for:
```
#define X ({(int[10]){};})
void func() {
(void)(X + 0);
}
```
IIRC there's no rvalue conversion on the statement expression result so I think
that ends up being a prvalue of array type (not a decayed pointer) plus an
integer, so the type information would actually be helpful.
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
languagelawyer wrote: > it is CWG2548; that's what made it clear that array-to-pointer decay does not > happen here CWG2548 is closed as NAD, with no changes to the wording. The fact that array-to-pointer decay does not happen has always been clear > despite that being inconsistent with the rest of the language I'd say CWG hallucinated inconsistence, to me there is none https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning< def err_objc_object_assignment : Error< "cannot assign to class object (%0 invalid)">; +def err_typecheck_array_prvalue_operand : Error< + "array prvalue is not permitted">; AaronBallman wrote: The goal of diagnostics is to help the user see what's wrong with their code. Users don't generally think in terms of value categories unless they've been spending a lot of time reading the standard (which the vast majority of users have never seen, let alone read). So the important part is telling the user that the operands are invalid (and pointing to the invalid operand); the type information helps the user to determine which operand is the likely issue. https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning< def err_objc_object_assignment : Error< "cannot assign to class object (%0 invalid)">; +def err_typecheck_array_prvalue_operand : Error< + "array prvalue is not permitted">; languagelawyer wrote: > the type information helps the user The error message says "array". Ok, what about "temporary array" instead of "array prvalue"? https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
https://github.com/languagelawyer edited https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
AaronBallman wrote:
> > it is CWG2548; that's what made it clear that array-to-pointer decay does
> > not happen here
>
> CWG2548 is closed as NAD, with no changes to the wording.
Correct.
> The fact that array-to-pointer decay does not happen has always been clear
Incorrect; the reason the core issue was filed in the first place was because
it seemed like an oversight that the language was inconsistent. Clang was
implementing the consistent behavior where array to pointer decay happened.
That's why this is CWG2548.
> > despite that being inconsistent with the rest of the language
>
> I'd say CWG hallucinated inconsistence, to me there is none
```
int x[10];
(void)(x + 0); // perfectly fine, array to pointer decay on x
(void)((int[10]){} + 0); // Not okay under CWG2548 being closed NAD, no array
to pointer decay on the temporary
```
So definitely inconsistent, and EWG agreed that it was, but liked the
accidental behavior that came from it.
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning< def err_objc_object_assignment : Error< "cannot assign to class object (%0 invalid)">; +def err_typecheck_array_prvalue_operand : Error< + "array prvalue is not permitted">; languagelawyer wrote: > I think just reusing `err_typecheck_invalid_operands` would be clearer How so? `err_typecheck_invalid_operands` mentions types, but the issue is due to value category, not type https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning< def err_objc_object_assignment : Error< "cannot assign to class object (%0 invalid)">; +def err_typecheck_array_prvalue_operand : Error< + "array prvalue is not permitted">; Sirraide wrote: > It's unfortunate to mention "prvalue" at all because that's language lawyer > wording Yeah, I agree; I think just reusing `err_typecheck_invalid_operands` would be clearer. https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning<
def err_objc_object_assignment : Error<
"cannot assign to class object (%0 invalid)">;
+def err_typecheck_array_prvalue_operand : Error<
+ "array prvalue is not permitted">;
AaronBallman wrote:
It's unfortunate to mention "prvalue" at all because that's language lawyer
wording (no offense to @languagelawyer, of course!) which users aren't going to
generally be aware of. I think we can kind of get away with `lvalue` and
`rvalue` due to those being terms of art for so long, but the C++ taxonomy
terms are much more recent and nuanced.
I think `test.cxx:5:16: error: invalid operands to binary expression ('int[3]'
and 'double')` is more clearly telling the user what's wrong with their code.
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
AaronBallman wrote:
> > This is related to CWG2548
>
> Kinda, but not really. It has never been necessary to create that
> (non-)issue. Or does someone really believe that it is a C++ defect that `IA{
> 1, 2, 3 } - IA{ 1, 2, 3 }` is not allowed? So, it is just a bug since C++11
I think it is CWG2548; that's what made it clear that array-to-pointer decay
does not happen here despite that being inconsistent with the rest of the
language (https://github.com/cplusplus/papers/issues/1633)
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning< def err_objc_object_assignment : Error< "cannot assign to class object (%0 invalid)">; +def err_typecheck_array_prvalue_operand : Error< + "array prvalue is not permitted">; zwuis wrote: > is `"operand cannot be an array prvalue"` ok? This is ok to me. https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning<
def err_objc_object_assignment : Error<
"cannot assign to class object (%0 invalid)">;
+def err_typecheck_array_prvalue_operand : Error<
+ "array prvalue is not permitted">;
languagelawyer wrote:
@zwuis is `"operand cannot be an array prvalue"` ok? Comparing to an existing
error:
```c++
IA{ 1, 2, 3 } + 0.;
IA{ 1, 2, 3 } + 0;
```
```
test.cxx:5:16: error: invalid operands to binary expression ('int[3]' and
'double')
test.cxx:6:16: error: operand cannot be an array prvalue
```
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning< def err_objc_object_assignment : Error< "cannot assign to class object (%0 invalid)">; +def err_typecheck_array_prvalue_operand : Error< + "array prvalue is not permitted">; zwuis wrote: > But the operator is pointed at by `^` This part can be removed by using `-fno-caret-diagnostics` command line option. In this case, the diagnostic is as followed: ```txt test.cxx:13:23: error: array prvalue is not permitted ``` Users may get confused. https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning< def err_objc_object_assignment : Error< "cannot assign to class object (%0 invalid)">; +def err_typecheck_array_prvalue_operand : Error< + "array prvalue is not permitted">; Sirraide wrote: Hmm, in that case, maybe just ‘operand cannot be an array prvalue’. I would prefer at least including the word ‘operand’ so it’s clear that the problem is that you’re passing an array prvalue to this operator, because at the moment the diagnostic makes it sound like array prvalues aren’t permitted *at all*. https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
https://github.com/languagelawyer edited https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning<
def err_objc_object_assignment : Error<
"cannot assign to class object (%0 invalid)">;
+def err_typecheck_array_prvalue_operand : Error<
+ "array prvalue is not permitted">;
languagelawyer wrote:
But the operator is pointed at by the `^` mark, like
```
test.cxx:13:23: error: array prvalue is not permitted
13 | ((int []){ 1, 2, 3}) + 0;
| ^
```
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -15840,6 +15859,11 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation
OpLoc,
InputExpr->getType()->isSpecificBuiltinType(BuiltinType::Dependent)) {
resultType = Context.DependentTy;
} else {
+if (Opc == UO_Deref || Opc == UO_Plus) {
Sirraide wrote:
It feels a bit weird to use an `if` statement here when there’s a `switch`
statement on the same variable right after. I’d probably make this a lambda and
then call it in the cases for `*` and `+` below (the `+` case would then also
need a `[[fallthrough]]` annotation).
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning< def err_objc_object_assignment : Error< "cannot assign to class object (%0 invalid)">; +def err_typecheck_array_prvalue_operand : Error< + "array prvalue is not permitted">; Sirraide wrote: ```suggestion "operand of '%0' cannot be an array prvalue">; ``` I think it’s a bit clearer if we phrase it like this and also print out the operator rather than just saying ‘X is not permitted’. https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
@@ -16,4 +15,13 @@ int main()
f0(a1);
f1(a2);
f2(a3);
+
+ using IA = int[];
+ void(+IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
Sirraide wrote:
Can you add some tests here to make sure that we don’t complain about array
glvalues?
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
languagelawyer wrote: @pinskia the thing is, GCC started accepting ill-formed code right when it was reaffirmed it is ill-formed https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
AaronBallman wrote:
> > That probably should continue to work -- we accept it today and so does GCC
>
> GCC started accepting it from version 14, likely when fixing
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94264 (it is mentioned in
> [#54016
> (comment)](https://github.com/llvm/llvm-project/issues/54016#issuecomment-1752262953)),
> but it also started accepting `IA{ 1, 2, 3 } + 0`, which is clearly wrong
> https://godbolt.org/z/r7Yc3o1qd @pinskia @jicama
>
> I think, if someone wants 100% C compatibility, then they should make
> compound literals lvalues. If compound literals are prvalues in C++
> extension, then they should be treated like other array prvalues
Ugh, I was backwards again. They're prvalues in C++ already, not lvalues as in
C, so yes, it should be rejected in C++ with your changes. Sorry for the
confusion!
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
languagelawyer wrote:
> That probably should continue to work -- we accept it today and so does GCC
GCC started accepting it from version 14, likely when fixing
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94264 (it is mentioned in
https://github.com/llvm/llvm-project/issues/54016#issuecomment-1752262953), but
it also started accepting `IA{ 1, 2, 3 } + 0`, which is clearly wrong
https://godbolt.org/z/r7Yc3o1qd @pinskia @jicama
I think, if someone wants 100% C compatibility, then they should make compound
literals lvalues. If compound literals are prvalues in C++ extension, then they
should be treated like other array prvalues
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
AaronBallman wrote:
> However, it "breaks" compound literal C++ extension:
>
> ```
> $ build/bin/clang++ -fsyntax-only test.cxx
> test.cxx:12:2: error: array prvalue is not permitted
>12 | *((int []){ 1, 2, 3});
> | ^
> test.cxx:13:23: error: array prvalue is not permitted
>13 | ((int []){ 1, 2, 3}) + 0;
> | ^
> 2 errors generated.
> ```
That probably should continue to work -- we accept it today and so does GCC.
It's a bit of an oddity, to be sure. But I don't see why it should be rejected
either.
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
AaronBallman wrote:
> > Is this going to break behavior in C?
>
> Array **prvalues** is C++11+ exclusive thing. Compound literals are lvalues
> in C
Ah, good point, I wasn't remembering that C and C++ are different in how they
handle compound literals. And you can return a pointer to an array in C, but
that's still an lvalue.
> Anyway, here is a check:
>
> ```shell
> $ build/bin/clang -fsyntax-only test.c
> test.c:2:3: warning: expression result unused [-Wunused-value]
> 2 | *((int []){ 1, 2, 3});
> | ^
> test.c:3:24: warning: expression result unused [-Wunused-value]
> 3 | ((int []){ 1, 2, 3}) + 0;
> | ^ ~
> 2 warnings generated.
> ```
Thank you!
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
languagelawyer wrote:
> Is this going to break behavior in C?
Array **prvalues** is C++11+ exclusive thing. Compound literals are lvalues in
C https://port70.net/~nsz/c/c11/n1570.html#6.5.2.5p4
Anyway, here is a check:
```sh
$ build/bin/clang -fsyntax-only test.c
test.c:2:3: warning: expression result unused [-Wunused-value]
2 | *((int []){ 1, 2, 3});
| ^
test.c:3:24: warning: expression result unused [-Wunused-value]
3 | ((int []){ 1, 2, 3}) + 0;
| ^ ~
2 warnings generated.
```
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
https://github.com/AaronBallman commented: Is this going to break behavior in C? https://godbolt.org/z/PsPPs8ov1 https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
https://github.com/languagelawyer updated
https://github.com/llvm/llvm-project/pull/140702
>From f6067249c40ad8423048b718be53e69f74b8607d Mon Sep 17 00:00:00 2001
From: Andrey Erokhin
Date: Tue, 20 May 2025 14:58:23 +0500
Subject: [PATCH] [Clang][Sema] Reject array prvalue operands
of unary + and *, and binary + and - operators
---
.../clang/Basic/DiagnosticSemaKinds.td| 2 ++
clang/lib/Sema/SemaExpr.cpp | 24 +++
clang/test/CXX/expr/p8.cpp| 12 --
3 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d78a757c72e4a..e72d62a9a5408 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6971,6 +6971,8 @@ def err_typecheck_arc_assign_self_class_method : Error<
def err_typecheck_arr_assign_enumeration : Error<
"fast enumeration variables cannot be modified in ARC by default; "
"declare the variable __strong to allow this">;
+def err_typecheck_array_prvalue_operand : Error<
+ "array prvalue is not permitted">;
def err_typecheck_arc_assign_externally_retained : Error<
"variable declared with 'objc_externally_retained' "
"cannot be modified in ARC">;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index d1889100c382e..3e0a80602df68 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11333,6 +11333,13 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS,
ExprResult &RHS,
if (!IExp->getType()->isIntegerType())
return InvalidOperands(Loc, LHS, RHS);
+ if (OriginalOperand Orig(PExp);
+ Orig.getType()->isArrayType() && Orig.Orig->isPRValue()) {
+Diag(Loc, diag::err_typecheck_array_prvalue_operand)
+<< PExp->getSourceRange();
+return QualType();
+ }
+
// Adding to a null pointer results in undefined behavior.
if (PExp->IgnoreParenCasts()->isNullPointerConstant(
Context, Expr::NPC_ValueDependentIsNotNull)) {
@@ -11429,6 +11436,18 @@ QualType Sema::CheckSubtractionOperands(ExprResult
&LHS, ExprResult &RHS,
return compType;
}
+ OriginalOperand OrigLHS(LHS.get()), OrigRHS(RHS.get());
+ bool LHSArrP = OrigLHS.getType()->isArrayType() && OrigLHS.Orig->isPRValue();
+ bool RHSArrP = OrigRHS.getType()->isArrayType() && OrigRHS.Orig->isPRValue();
+ if (LHSArrP || RHSArrP) {
+auto &&diag = Diag(Loc, diag::err_typecheck_array_prvalue_operand);
+if (LHSArrP)
+ diag << LHS.get()->getSourceRange();
+if (RHSArrP)
+ diag << RHS.get()->getSourceRange();
+return QualType();
+ }
+
// Either ptr - int or ptr - ptr.
if (LHS.get()->getType()->isAnyPointerType()) {
QualType lpointee = LHS.get()->getType()->getPointeeType();
@@ -15840,6 +15859,11 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation
OpLoc,
InputExpr->getType()->isSpecificBuiltinType(BuiltinType::Dependent)) {
resultType = Context.DependentTy;
} else {
+if (Opc == UO_Deref || Opc == UO_Plus) {
+ if (InputExpr->getType()->isArrayType() && InputExpr->isPRValue())
+return ExprError(Diag(OpLoc, diag::err_typecheck_array_prvalue_operand)
+ << InputExpr->getSourceRange());
+}
switch (Opc) {
case UO_PreInc:
case UO_PreDec:
diff --git a/clang/test/CXX/expr/p8.cpp b/clang/test/CXX/expr/p8.cpp
index 471d1c5a30206..f736b88b3db09 100644
--- a/clang/test/CXX/expr/p8.cpp
+++ b/clang/test/CXX/expr/p8.cpp
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
int a0;
const volatile int a1 = 2;
@@ -16,4 +15,13 @@ int main()
f0(a1);
f1(a2);
f2(a3);
+
+ using IA = int[];
+ void(+IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
+ void(*IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
+ void(IA{ 1, 2, 3 } + 0); // expected-error {{array prvalue}}
+ void(IA{ 1, 2, 3 } - 0); // expected-error {{array prvalue}}
+ void(0 + IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
+ void(0 - IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
+ void(IA{ 1, 2, 3 } - IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
}
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
https://github.com/languagelawyer updated
https://github.com/llvm/llvm-project/pull/140702
>From df91056b5ccbb0f51945f21cd5b2e5bca31eee7f Mon Sep 17 00:00:00 2001
From: Andrey Erokhin
Date: Tue, 20 May 2025 14:58:23 +0500
Subject: [PATCH] [Clang][Sema] Reject array prvalue operands
of unary + and *, and binary + and - operators
---
.../clang/Basic/DiagnosticSemaKinds.td| 2 ++
clang/lib/Sema/SemaExpr.cpp | 24 +++
clang/test/CXX/expr/p8.cpp| 12 --
3 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d78a757c72e4a..2d7498a750d18 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7639,6 +7639,8 @@ def warn_param_mismatched_alignment : Warning<
def err_objc_object_assignment : Error<
"cannot assign to class object (%0 invalid)">;
+def err_typecheck_array_prvalue_operand : Error<
+ "array prvalue is not permitted">;
def err_typecheck_invalid_operands : Error<
"invalid operands to binary expression (%0 and %1)">, Deferrable;
def note_typecheck_invalid_operands_converted : Note<
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index d1889100c382e..3e0a80602df68 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11333,6 +11333,13 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS,
ExprResult &RHS,
if (!IExp->getType()->isIntegerType())
return InvalidOperands(Loc, LHS, RHS);
+ if (OriginalOperand Orig(PExp);
+ Orig.getType()->isArrayType() && Orig.Orig->isPRValue()) {
+Diag(Loc, diag::err_typecheck_array_prvalue_operand)
+<< PExp->getSourceRange();
+return QualType();
+ }
+
// Adding to a null pointer results in undefined behavior.
if (PExp->IgnoreParenCasts()->isNullPointerConstant(
Context, Expr::NPC_ValueDependentIsNotNull)) {
@@ -11429,6 +11436,18 @@ QualType Sema::CheckSubtractionOperands(ExprResult
&LHS, ExprResult &RHS,
return compType;
}
+ OriginalOperand OrigLHS(LHS.get()), OrigRHS(RHS.get());
+ bool LHSArrP = OrigLHS.getType()->isArrayType() && OrigLHS.Orig->isPRValue();
+ bool RHSArrP = OrigRHS.getType()->isArrayType() && OrigRHS.Orig->isPRValue();
+ if (LHSArrP || RHSArrP) {
+auto &&diag = Diag(Loc, diag::err_typecheck_array_prvalue_operand);
+if (LHSArrP)
+ diag << LHS.get()->getSourceRange();
+if (RHSArrP)
+ diag << RHS.get()->getSourceRange();
+return QualType();
+ }
+
// Either ptr - int or ptr - ptr.
if (LHS.get()->getType()->isAnyPointerType()) {
QualType lpointee = LHS.get()->getType()->getPointeeType();
@@ -15840,6 +15859,11 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation
OpLoc,
InputExpr->getType()->isSpecificBuiltinType(BuiltinType::Dependent)) {
resultType = Context.DependentTy;
} else {
+if (Opc == UO_Deref || Opc == UO_Plus) {
+ if (InputExpr->getType()->isArrayType() && InputExpr->isPRValue())
+return ExprError(Diag(OpLoc, diag::err_typecheck_array_prvalue_operand)
+ << InputExpr->getSourceRange());
+}
switch (Opc) {
case UO_PreInc:
case UO_PreDec:
diff --git a/clang/test/CXX/expr/p8.cpp b/clang/test/CXX/expr/p8.cpp
index 471d1c5a30206..f736b88b3db09 100644
--- a/clang/test/CXX/expr/p8.cpp
+++ b/clang/test/CXX/expr/p8.cpp
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
int a0;
const volatile int a1 = 2;
@@ -16,4 +15,13 @@ int main()
f0(a1);
f1(a2);
f2(a3);
+
+ using IA = int[];
+ void(+IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
+ void(*IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
+ void(IA{ 1, 2, 3 } + 0); // expected-error {{array prvalue}}
+ void(IA{ 1, 2, 3 } - 0); // expected-error {{array prvalue}}
+ void(0 + IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
+ void(0 - IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
+ void(IA{ 1, 2, 3 } - IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
}
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
zwuis wrote: This is related to CWG2548. CC @Endilll https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
languagelawyer wrote:
> This is related to CWG2548
Kinda, but not really. It has never been necessary to create the (non-)issue.
Or does someone really believe that it is a C++ defect that `IA{ 1, 2, 3 } -
IA{ 1, 2, 3 }` is not allowed?
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
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 HEAD~1 HEAD --extensions cpp --
clang/lib/Sema/SemaExpr.cpp clang/test/CXX/expr/p8.cpp
``
View the diff from clang-format here.
``diff
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 6b1704a10..62386d80c 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11333,8 +11333,10 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS,
ExprResult &RHS,
if (!IExp->getType()->isIntegerType())
return InvalidOperands(Loc, LHS, RHS);
- if (OriginalOperand Orig(PExp); Orig.getType()->isArrayType() &&
Orig.Orig->isPRValue()) {
-Diag(Loc, diag::err_typecheck_array_prvalue_operand) <<
PExp->getSourceRange();
+ if (OriginalOperand Orig(PExp);
+ Orig.getType()->isArrayType() && Orig.Orig->isPRValue()) {
+Diag(Loc, diag::err_typecheck_array_prvalue_operand)
+<< PExp->getSourceRange();
return QualType();
}
@@ -11435,12 +11437,16 @@ QualType Sema::CheckSubtractionOperands(ExprResult
&LHS, ExprResult &RHS,
}
OriginalOperand OrigLHS(LHS.get()), OrigRHS(RHS.get());
- bool LHSArrayPRV = OrigLHS.getType()->isArrayType() &&
OrigLHS.Orig->isPRValue();
- bool RHSArrayPRV = OrigRHS.getType()->isArrayType() &&
OrigRHS.Orig->isPRValue();
+ bool LHSArrayPRV =
+ OrigLHS.getType()->isArrayType() && OrigLHS.Orig->isPRValue();
+ bool RHSArrayPRV =
+ OrigRHS.getType()->isArrayType() && OrigRHS.Orig->isPRValue();
if (LHSArrayPRV || RHSArrayPRV) {
-auto&& diag = Diag(Loc, diag::err_typecheck_array_prvalue_operand);
-if (LHSArrayPRV) diag << LHS.get()->getSourceRange();
-if (RHSArrayPRV) diag << RHS.get()->getSourceRange();
+auto &&diag = Diag(Loc, diag::err_typecheck_array_prvalue_operand);
+if (LHSArrayPRV)
+ diag << LHS.get()->getSourceRange();
+if (RHSArrayPRV)
+ diag << RHS.get()->getSourceRange();
return QualType();
}
@@ -15856,8 +15862,10 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation
OpLoc,
resultType = Context.DependentTy;
} else {
if (Opc == UO_Deref || Opc == UO_Plus) {
- if (auto *expr = Input.get(); expr->getType()->isArrayType() &&
expr->isPRValue()) {
-Diag(OpLoc, diag::err_typecheck_array_prvalue_operand) <<
expr->getSourceRange();
+ if (auto *expr = Input.get();
+ expr->getType()->isArrayType() && expr->isPRValue()) {
+Diag(OpLoc, diag::err_typecheck_array_prvalue_operand)
+<< expr->getSourceRange();
return ExprError();
}
}
``
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
llvmbot wrote:
@llvm/pr-subscribers-clang
Author: None (languagelawyer)
Changes
of unary `+` and `*`, and binary `+` and `-` operators
Fixes #54016
---
Full diff: https://github.com/llvm/llvm-project/pull/140702.diff
2 Files Affected:
- (modified) clang/lib/Sema/SemaExpr.cpp (+21)
- (modified) clang/test/CXX/expr/p8.cpp (+10-2)
``diff
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index d1889100c382e..c0fa9bc9e895e 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11333,6 +11333,11 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS,
ExprResult &RHS,
if (!IExp->getType()->isIntegerType())
return InvalidOperands(Loc, LHS, RHS);
+ if (OriginalOperand Orig(PExp); Orig.getType()->isArrayType() &&
Orig.Orig->isPRValue()) {
+Diag(Loc, diag::err_typecheck_array_prvalue_operand) <<
PExp->getSourceRange();
+return QualType();
+ }
+
// Adding to a null pointer results in undefined behavior.
if (PExp->IgnoreParenCasts()->isNullPointerConstant(
Context, Expr::NPC_ValueDependentIsNotNull)) {
@@ -11429,6 +11434,16 @@ QualType Sema::CheckSubtractionOperands(ExprResult
&LHS, ExprResult &RHS,
return compType;
}
+ OriginalOperand OrigLHS(LHS.get()), OrigRHS(RHS.get());
+ bool LHSArrayPRV = OrigLHS.getType()->isArrayType() &&
OrigLHS.Orig->isPRValue();
+ bool RHSArrayPRV = OrigRHS.getType()->isArrayType() &&
OrigRHS.Orig->isPRValue();
+ if (LHSArrayPRV || RHSArrayPRV) {
+auto&& diag = Diag(Loc, diag::err_typecheck_array_prvalue_operand);
+if (LHSArrayPRV) diag << LHS.get()->getSourceRange();
+if (RHSArrayPRV) diag << RHS.get()->getSourceRange();
+return QualType();
+ }
+
// Either ptr - int or ptr - ptr.
if (LHS.get()->getType()->isAnyPointerType()) {
QualType lpointee = LHS.get()->getType()->getPointeeType();
@@ -15840,6 +15855,12 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation
OpLoc,
InputExpr->getType()->isSpecificBuiltinType(BuiltinType::Dependent)) {
resultType = Context.DependentTy;
} else {
+if (Opc == UO_Deref || Opc == UO_Plus) {
+ if (auto *expr = Input.get(); expr->getType()->isArrayType() &&
expr->isPRValue()) {
+Diag(OpLoc, diag::err_typecheck_array_prvalue_operand) <<
expr->getSourceRange();
+return ExprError();
+ }
+}
switch (Opc) {
case UO_PreInc:
case UO_PreDec:
diff --git a/clang/test/CXX/expr/p8.cpp b/clang/test/CXX/expr/p8.cpp
index 471d1c5a30206..f736b88b3db09 100644
--- a/clang/test/CXX/expr/p8.cpp
+++ b/clang/test/CXX/expr/p8.cpp
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
int a0;
const volatile int a1 = 2;
@@ -16,4 +15,13 @@ int main()
f0(a1);
f1(a2);
f2(a3);
+
+ using IA = int[];
+ void(+IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
+ void(*IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
+ void(IA{ 1, 2, 3 } + 0); // expected-error {{array prvalue}}
+ void(IA{ 1, 2, 3 } - 0); // expected-error {{array prvalue}}
+ void(0 + IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
+ void(0 - IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
+ void(IA{ 1, 2, 3 } - IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
}
``
https://github.com/llvm/llvm-project/pull/140702
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
github-actions[bot] wrote: Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using `@` followed by their GitHub username. If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the [LLVM GitHub User Guide](https://llvm.org/docs/GitHub.html). You can also ask questions in a comment on this PR, on the [LLVM Discord](https://discord.com/invite/xS7Z362) or on the [forums](https://discourse.llvm.org/). https://github.com/llvm/llvm-project/pull/140702 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Reject array prvalue operands (PR #140702)
https://github.com/languagelawyer created
https://github.com/llvm/llvm-project/pull/140702
of unary `+` and `*`, and binary `+` and `-` operators
Fixes #54016
>From 2914130e2273eb279b978b73f58d5a2d257decb4 Mon Sep 17 00:00:00 2001
From: Andrey Erokhin
Date: Tue, 20 May 2025 14:58:23 +0500
Subject: [PATCH] [Clang][Sema] Reject array prvalue operands
of unary + and *, and binary + and - operators
---
clang/lib/Sema/SemaExpr.cpp | 21 +
clang/test/CXX/expr/p8.cpp | 12 ++--
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index d1889100c382e..c0fa9bc9e895e 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11333,6 +11333,11 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS,
ExprResult &RHS,
if (!IExp->getType()->isIntegerType())
return InvalidOperands(Loc, LHS, RHS);
+ if (OriginalOperand Orig(PExp); Orig.getType()->isArrayType() &&
Orig.Orig->isPRValue()) {
+Diag(Loc, diag::err_typecheck_array_prvalue_operand) <<
PExp->getSourceRange();
+return QualType();
+ }
+
// Adding to a null pointer results in undefined behavior.
if (PExp->IgnoreParenCasts()->isNullPointerConstant(
Context, Expr::NPC_ValueDependentIsNotNull)) {
@@ -11429,6 +11434,16 @@ QualType Sema::CheckSubtractionOperands(ExprResult
&LHS, ExprResult &RHS,
return compType;
}
+ OriginalOperand OrigLHS(LHS.get()), OrigRHS(RHS.get());
+ bool LHSArrayPRV = OrigLHS.getType()->isArrayType() &&
OrigLHS.Orig->isPRValue();
+ bool RHSArrayPRV = OrigRHS.getType()->isArrayType() &&
OrigRHS.Orig->isPRValue();
+ if (LHSArrayPRV || RHSArrayPRV) {
+auto&& diag = Diag(Loc, diag::err_typecheck_array_prvalue_operand);
+if (LHSArrayPRV) diag << LHS.get()->getSourceRange();
+if (RHSArrayPRV) diag << RHS.get()->getSourceRange();
+return QualType();
+ }
+
// Either ptr - int or ptr - ptr.
if (LHS.get()->getType()->isAnyPointerType()) {
QualType lpointee = LHS.get()->getType()->getPointeeType();
@@ -15840,6 +15855,12 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation
OpLoc,
InputExpr->getType()->isSpecificBuiltinType(BuiltinType::Dependent)) {
resultType = Context.DependentTy;
} else {
+if (Opc == UO_Deref || Opc == UO_Plus) {
+ if (auto *expr = Input.get(); expr->getType()->isArrayType() &&
expr->isPRValue()) {
+Diag(OpLoc, diag::err_typecheck_array_prvalue_operand) <<
expr->getSourceRange();
+return ExprError();
+ }
+}
switch (Opc) {
case UO_PreInc:
case UO_PreDec:
diff --git a/clang/test/CXX/expr/p8.cpp b/clang/test/CXX/expr/p8.cpp
index 471d1c5a30206..f736b88b3db09 100644
--- a/clang/test/CXX/expr/p8.cpp
+++ b/clang/test/CXX/expr/p8.cpp
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
int a0;
const volatile int a1 = 2;
@@ -16,4 +15,13 @@ int main()
f0(a1);
f1(a2);
f2(a3);
+
+ using IA = int[];
+ void(+IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
+ void(*IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
+ void(IA{ 1, 2, 3 } + 0); // expected-error {{array prvalue}}
+ void(IA{ 1, 2, 3 } - 0); // expected-error {{array prvalue}}
+ void(0 + IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
+ void(0 - IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
+ void(IA{ 1, 2, 3 } - IA{ 1, 2, 3 }); // expected-error {{array prvalue}}
}
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
