[clang] [clang] pointer to member with qualified-id enclosed in parentheses in unevaluated context should be invalid (PR #89713)

2024-04-25 Thread Brian Bi via cfe-commits

t3nsor wrote:

> @t3nsor Do you know the reason for the "not enclosed in parameters" in 
> https://eel.is/c++draft/expr.unary.op#4 ?

No I don't. If I had to guess, it might be because adding parentheses is 
intended to be used as a way to not create a pointer to member (and instead get 
an ordinary pointer to a member named by a qualified  name) sort of like how 
parentheses can be used to suppress ADL.

https://github.com/llvm/llvm-project/pull/89713
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement C++26 P2748R5 "Disallow Binding a Returned Glvalue to a Temporary" (PR #89942)

2024-04-25 Thread Brian Bi via cfe-commits


@@ -8340,8 +8340,17 @@ void Sema::checkInitializerLifetime(const 
InitializedEntity &Entity,
 << Entity.getType()->isReferenceType() << CLE->getInitializer() << 
2
 << DiagRange;
   } else {
-Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
- << Entity.getType()->isReferenceType() << DiagRange;
+// P2748R5: Disallow Binding a Returned Glvalue to a Temporary.
+// [stmt.return]/p6: In a function whose return type is a reference,
+// other than an invented function for std::is_convertible 
([meta.rel]),
+// a return statement that binds the returned reference to a temporary
+// expression ([class.temporary]) is ill-formed.
+if (getLangOpts().CPlusPlus26)
+  Diag(DiagLoc, diag::err_ret_local_temp_addr_ref)
+  << Entity.getType()->isReferenceType() << DiagRange;

t3nsor wrote:

It's not normatively ill-formed because of the difficulty of specifying exactly 
which constructs of this nature are supposed to be ill-formed. In the pedantic 
mode or whatever it's called, you'd have to accept it, even though it's bad.

https://github.com/llvm/llvm-project/pull/89942
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement C++26 P2748R5 "Disallow Binding a Returned Glvalue to a Temporary" (PR #89942)

2024-04-25 Thread Brian Bi via cfe-commits


@@ -8340,8 +8340,17 @@ void Sema::checkInitializerLifetime(const 
InitializedEntity &Entity,
 << Entity.getType()->isReferenceType() << CLE->getInitializer() << 
2
 << DiagRange;
   } else {
-Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
- << Entity.getType()->isReferenceType() << DiagRange;
+// P2748R5: Disallow Binding a Returned Glvalue to a Temporary.
+// [stmt.return]/p6: In a function whose return type is a reference,
+// other than an invented function for std::is_convertible 
([meta.rel]),
+// a return statement that binds the returned reference to a temporary
+// expression ([class.temporary]) is ill-formed.

t3nsor wrote:

I don't know if Clang implements all the cases in [class.temporary], but I 
would assume "yes", because if not, then users are already not getting 
lifetime-extended temporaries in places where they would expect them, which 
would be bad. The changes to this file are basically the same as what I had 
prototyped in my branch.

https://github.com/llvm/llvm-project/pull/89942
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] fix constexpr-unknown handling of self-references. (PR #132990)

2025-03-26 Thread Brian Bi via cfe-commits


@@ -177,3 +177,50 @@ namespace extern_reference_used_as_unknown {
   int y;
   constinit int& g = (x,y); // expected-warning {{left operand of comma 
operator has no effect}}
 }
+
+namespace uninit_reference_used {
+  int y;
+  constexpr int &r = r; // expected-error {{must be initialized by a constant 
expression}} \
+  // nointerpreter-note {{initializer of 'r' is not a constant expression}} \
+  // nointerpreter-note {{declared here}}
+  constexpr int &rr = (rr, y);
+  constexpr int &g() {
+int &x = x; // expected-warning {{reference 'x' is not yet bound to a 
value when used within its own initialization}} \
+// nointerpreter-note {{declared here}} \
+// interpreter-note {{read of uninitialized object is not allowed in a 
constant expression}}
+return x;
+  }
+  constexpr int &gg = g(); // expected-error {{must be initialized by a 
constant expression}} \
+  // nointerpreter-note {{reference to 'x' is not a constant expression}} \
+  // interpreter-note {{in call to 'g()'}}
+  constexpr int g2() {
+int &x = x; // expected-warning {{reference 'x' is not yet bound to a 
value when used within its own initialization}} \
+// interpreter-note {{read of uninitialized object is not allowed in a 
constant expression}}
+return x;
+  }
+  constexpr int gg2 = g2(); // expected-error {{must be initialized by a 
constant expression}} \
+  // interpreter-note {{in call to 'g2()'}}
+  constexpr int &g3() {
+int &x = (x,y); // expected-warning{{left operand of comma operator has no 
effect}} \
+// expected-warning {{reference 'x' is not yet bound to a value when used 
within its own initialization}}
+return x;
+  }
+  constexpr int &gg3 = g3();
+  typedef decltype(sizeof(1)) uintptr_t;
+  constexpr uintptr_t g4() {
+uintptr_t * &x = x; // expected-warning {{reference 'x' is not yet bound 
to a value when used within its own initialization}} \
+// interpreter-note {{read of uninitialized object is not allowed in a 
constant expression}}
+*(uintptr_t*)x = 10;
+return 3;
+  }
+  constexpr uintptr_t gg4 = g4(); // expected-error {{must be initialized by a 
constant expression}} \
+  // interpreter-note {{in call to 'g4()'}}
+  constexpr int g5() {
+int &x = x; // expected-warning {{reference 'x' is not yet bound to a 
value when used within its own initialization}} \
+// interpreter-note {{read of uninitialized object is not allowed in a 
constant expression}}
+return 3;
+  }
+  constexpr uintptr_t gg5 = g5(); // interpreter-error {{must be initialized 
by a constant expression}} \
+  // interpreter-note {{in call to 'g5()'}}

t3nsor wrote:

I think it would be extremely strange if the intent of the standard were to not 
allow this case to be diagnosed. Going by the literal wording, yes, you have an 
id-expression that refers to a reference whose lifetime didn't begin within the 
constant evaluation (because it hasn't begun at all), which makes it an unknown 
reference, but in reality we know exactly what's happening here. It seems like 
the standard may have a defect and the rule for references really should be 
that the reference is unknown only if its *initialization* didn't begin within 
the evaluation of E.

https://github.com/llvm/llvm-project/pull/132990
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits