[clang] [libcxx] [SemaCXX] Implement CWG2137 (list-initialization from objects of the same type) (PR #77768)

2024-01-11 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok created 
https://github.com/llvm/llvm-project/pull/77768

Closes #77638, #24186

Rebased from , see there for more information.

Implements wording change in [CWG2137](https://wg21.link/CWG2137) in the first 
commit.

This also implements an approach to [CWG2311](https://wg21.link/CWG2311) in the 
second commit, because too much code that relies on `T{ T_prvalue }` being an 
elision would break. Because that issue is still open and the CWG issue doesn't 
provide wording to fix the issue, there may be different behaviours on other 
compilers.



>From 08e2db75625ff4494f352df70922174275d7c2dd Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sat, 22 Jul 2023 20:07:00 +0100
Subject: [PATCH 1/2] [SemaCXX] Implement CWG2137 (list-initialization from
 objects of the same type)

Differential Revision: https://reviews.llvm.org/D156032
---
 clang/docs/ReleaseNotes.rst   |  2 +
 clang/lib/Sema/SemaInit.cpp   | 14 +++
 clang/lib/Sema/SemaOverload.cpp   | 38 +-
 clang/test/CXX/drs/dr14xx.cpp | 10 -
 clang/test/CXX/drs/dr21xx.cpp | 40 +++
 clang/www/cxx_dr_status.html  |  2 +-
 .../pairs.pair/ctor.pair_U_V_move.pass.cpp| 21 +-
 7 files changed, 98 insertions(+), 29 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 59732962caac65..a52fb805497756 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -199,6 +199,8 @@ C++2c Feature Support
 
 Resolutions to C++ Defect Reports
 ^
+- Implemented `CWG2137 `_ which allows
+  list-initialization from objects of the same type.
 
 C Language Changes
 --
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 408ee5f775804b..a3a7486af093fb 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -4199,7 +4199,7 @@ static OverloadingResult ResolveConstructorOverload(
 /// \param IsListInit Is this list-initialization?
 /// \param IsInitListCopy Is this non-list-initialization resulting from a
 ///   list-initialization from {x} where x is the same
-///   type as the entity?
+///   aggregate type as the entity?
 static void TryConstructorInitialization(Sema &S,
  const InitializedEntity &Entity,
  const InitializationKind &Kind,
@@ -4239,8 +4239,8 @@ static void TryConstructorInitialization(Sema &S,
   // ObjC++: Lambda captured by the block in the lambda to block conversion
   // should avoid copy elision.
   if (S.getLangOpts().CPlusPlus17 && !RequireActualConstructor &&
-  UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isPRValue() &&
-  S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) 
{
+  Args.size() == 1 && Args[0]->isPRValue() &&
+  S.Context.hasSameUnqualifiedType(Args[0]->getType(), DestType)) {
 // Convert qualifications if necessary.
 Sequence.AddQualificationConversionStep(DestType, VK_PRValue);
 if (ILE)
@@ -4571,9 +4571,9 @@ static void TryListInitialization(Sema &S,
 return;
   }
 
-  // C++11 [dcl.init.list]p3, per DR1467:
-  // - If T is a class type and the initializer list has a single element of
-  //   type cv U, where U is T or a class derived from T, the object is
+  // C++11 [dcl.init.list]p3, per DR1467 and DR2137:
+  // - If T is an aggregate class and the initializer list has a single element
+  //   of type cv U, where U is T or a class derived from T, the object is
   //   initialized from that element (by copy-initialization for
   //   copy-list-initialization, or by direct-initialization for
   //   direct-list-initialization).
@@ -4584,7 +4584,7 @@ static void TryListInitialization(Sema &S,
   // - Otherwise, if T is an aggregate, [...] (continue below).
   if (S.getLangOpts().CPlusPlus11 && InitList->getNumInits() == 1 &&
   !IsDesignatedInit) {
-if (DestType->isRecordType()) {
+if (DestType->isRecordType() && DestType->isAggregateType()) {
   QualType InitType = InitList->getInit(0)->getType();
   if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
   S.IsDerivedFrom(InitList->getBeginLoc(), InitType, DestType)) {
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 64bc3851980272..30bc2036cf781c 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1562,19 +1562,37 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType 
ToType,
 //   called for those cases.
 if (CXXConstructorDecl *Constructor
   = dyn_cast(ICS.UserDefined.ConversionFunction)) {
-  QualType FromCanon
-= S.Context.getCanonicalType(From->getType().getUnqualifiedType());
+  

[clang] [libcxx] [SemaCXX] Implement CWG2137 (list-initialization from objects of the same type) (PR #77768)

2024-01-11 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/77768

>From 696d4f964805d1af04d4f94dbc8f47adfbc02428 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sat, 22 Jul 2023 20:07:00 +0100
Subject: [PATCH 1/2] [SemaCXX] Implement CWG2137 (list-initialization from
 objects of the same type)

Differential Revision: https://reviews.llvm.org/D156032
---
 clang/docs/ReleaseNotes.rst   |  2 +
 clang/lib/Sema/SemaInit.cpp   | 14 +++
 clang/lib/Sema/SemaOverload.cpp   | 38 +-
 clang/test/CXX/drs/dr14xx.cpp | 10 -
 clang/test/CXX/drs/dr21xx.cpp | 40 +++
 clang/www/cxx_dr_status.html  |  2 +-
 .../pairs.pair/ctor.pair_U_V_move.pass.cpp| 21 +-
 7 files changed, 98 insertions(+), 29 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 59732962caac65..a52fb805497756 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -199,6 +199,8 @@ C++2c Feature Support
 
 Resolutions to C++ Defect Reports
 ^
+- Implemented `CWG2137 `_ which allows
+  list-initialization from objects of the same type.
 
 C Language Changes
 --
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 408ee5f775804b..a3a7486af093fb 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -4199,7 +4199,7 @@ static OverloadingResult ResolveConstructorOverload(
 /// \param IsListInit Is this list-initialization?
 /// \param IsInitListCopy Is this non-list-initialization resulting from a
 ///   list-initialization from {x} where x is the same
-///   type as the entity?
+///   aggregate type as the entity?
 static void TryConstructorInitialization(Sema &S,
  const InitializedEntity &Entity,
  const InitializationKind &Kind,
@@ -4239,8 +4239,8 @@ static void TryConstructorInitialization(Sema &S,
   // ObjC++: Lambda captured by the block in the lambda to block conversion
   // should avoid copy elision.
   if (S.getLangOpts().CPlusPlus17 && !RequireActualConstructor &&
-  UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isPRValue() &&
-  S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) 
{
+  Args.size() == 1 && Args[0]->isPRValue() &&
+  S.Context.hasSameUnqualifiedType(Args[0]->getType(), DestType)) {
 // Convert qualifications if necessary.
 Sequence.AddQualificationConversionStep(DestType, VK_PRValue);
 if (ILE)
@@ -4571,9 +4571,9 @@ static void TryListInitialization(Sema &S,
 return;
   }
 
-  // C++11 [dcl.init.list]p3, per DR1467:
-  // - If T is a class type and the initializer list has a single element of
-  //   type cv U, where U is T or a class derived from T, the object is
+  // C++11 [dcl.init.list]p3, per DR1467 and DR2137:
+  // - If T is an aggregate class and the initializer list has a single element
+  //   of type cv U, where U is T or a class derived from T, the object is
   //   initialized from that element (by copy-initialization for
   //   copy-list-initialization, or by direct-initialization for
   //   direct-list-initialization).
@@ -4584,7 +4584,7 @@ static void TryListInitialization(Sema &S,
   // - Otherwise, if T is an aggregate, [...] (continue below).
   if (S.getLangOpts().CPlusPlus11 && InitList->getNumInits() == 1 &&
   !IsDesignatedInit) {
-if (DestType->isRecordType()) {
+if (DestType->isRecordType() && DestType->isAggregateType()) {
   QualType InitType = InitList->getInit(0)->getType();
   if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
   S.IsDerivedFrom(InitList->getBeginLoc(), InitType, DestType)) {
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 64bc3851980272..30bc2036cf781c 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1562,19 +1562,37 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType 
ToType,
 //   called for those cases.
 if (CXXConstructorDecl *Constructor
   = dyn_cast(ICS.UserDefined.ConversionFunction)) {
-  QualType FromCanon
-= S.Context.getCanonicalType(From->getType().getUnqualifiedType());
+  QualType FromType;
+  SourceLocation FromLoc;
+  // C++11 [over.ics.list]p6, per DR2137:
+  // C++17 [over.ics.list]p6:
+  //   If C is not an initializer-list constructor and the initializer list
+  //   has a single element of type cv U, where U is X or a class derived
+  //   from X, the implicit conversion sequence has Exact Match rank if U 
is
+  //   X, or Conversion rank if U is derived from X.
+  if (const auto *InitList = dyn_cast(From);
+  InitList && InitList->getNumI

[clang] [libcxx] [SemaCXX] Implement CWG2137 (list-initialization from objects of the same type) (PR #77768)

2024-01-24 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

With the standard as is, `B(A)` should be a better match because of 
[[over.ics.list]p(7.1)](https://wg21.link/over.ics.list#7.1), it is an Exact 
Match, and `B(std::vector)` is a user defined conversion.

With the current CWG2311 fix, the call to `B(A)` is an Exact Match because it's 
an `A` prvalue.

https://github.com/llvm/llvm-project/blob/7b11c08c664863fbcd7a3058179b0af3de5d28e4/clang/lib/Sema/SemaOverload.cpp#L1593

^ This line is the issue: `isCopyConstructor()` checks only for lvalue 
reference copy constructors, and the move constructor is selected (i.e., if you 
force a copy constructor to be called instead, it works: 
https://godbolt.org/z/rGEsPdMx8)

Removing `Constructor->isCopyConstructor() &&` fixes the issue (`B(A)` is 
chosen, and all existing tests still pass)

@cor3ntin I have some extra test cases I would want to add too. Should I make a 
new pull request? Or are we going to reopen this one and target llvm 19?


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


[clang] [SemaCXX] Make __builtin_addressof more like std::addressof (PR #78035)

2024-01-13 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok created 
https://github.com/llvm/llvm-project/pull/78035

Fixes #77928

There are a few places which expect that, if for an expression 
`E->getType()->isBuiltinType(BuiltinType::Overload)`, then `E` must be an 
`OverloadExpr` or a `UnaryOperator` where `cast(E)->getOpcode() 
== UO_AddrOf`.

Because `__builtin_addressof` is implemented similarly to `&`: 
https://github.com/llvm/llvm-project/blob/8d817f6479a5df874028a8b40fd30aecd3479005/clang/lib/Sema/SemaExpr.cpp#L15041
 It can result in something with `OverloadTy` that isn't an `OverloadExpr` or a 
`UnaryOperator` (it's a `CallExpr`).

There are two things we can do to fix this: Either change those checks to 
accept both `&E` and `__builtin_addressof(E)`, or change it so 
`__builtin_addressof(E)` doesn't treat OverloadExprs differently.

This takes the latter approach, disabling 
`__builtin_addressof(name-of-overloaded-function)`.

It appears that GCC allows `__builtin_addressof(fn)` to be an overloaded 
function: . The problem with allowing it in 
Clang is too much code generically deals with `CallExpr`s and you would have to 
special case `__builtin_addressof` to not try to resolve the arguments. And 
also it would be so rarely used in the first place (the fix being replacing 
`__builtin_addressof` with `&`)

>From 7384e99c5fc1bcba1a304735243e49e9738691aa Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sat, 13 Jan 2024 10:48:21 +
Subject: [PATCH] [SemaCXX] Make __builtin_addressof more like std::addressof

Properly disable __builtin_addressof(f) where f is an overloaded function and 
__builtin_addressof(temporary).

__builtin_addressof(E) should now only work if E is bindable to an lvalue 
reference with the same type.
---
 clang/include/clang/Sema/Sema.h |  3 ++-
 clang/lib/Sema/SemaChecking.cpp |  2 +-
 clang/lib/Sema/SemaExpr.cpp | 24 +++--
 clang/test/SemaCXX/builtins.cpp | 38 -
 4 files changed, 57 insertions(+), 10 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index cf2d4fbe6d3ba1..9941cbaadf780a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5805,7 +5805,8 @@ class Sema final {
  const Expr *Op,
  const CXXMethodDecl *MD);
 
-  QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
+  QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc,
+ bool IsBuiltinAddressof = false);
 
   bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N);
 
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 74f8f626fb1637..e96436fd75bb68 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -242,7 +242,7 @@ static bool SemaBuiltinAddressof(Sema &S, CallExpr 
*TheCall) {
 return true;
 
   ExprResult Arg(TheCall->getArg(0));
-  QualType ResultType = S.CheckAddressOfOperand(Arg, TheCall->getBeginLoc());
+  QualType ResultType = S.CheckAddressOfOperand(Arg, TheCall->getBeginLoc(), 
true);
   if (ResultType.isNull())
 return true;
 
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 2f48ea237cdfa4..518c51e77c7a99 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -15038,9 +15038,15 @@ bool 
Sema::CheckUseOfCXXMethodAsAddressOfOperand(SourceLocation OpLoc,
 /// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue.
 /// In C++, the operand might be an overloaded function name, in which case
 /// we allow the '&' but retain the overloaded-function type.
-QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) 
{
+/// If IsBuiltinAddressof is true, this is spelt __builtin_addressof(E)
+/// instead of &E.
+QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc,
+ bool IsBuiltinAddressof) {
   if (const BuiltinType *PTy = 
OrigOp.get()->getType()->getAsPlaceholderType()){
 if (PTy->getKind() == BuiltinType::Overload) {
+  if (IsBuiltinAddressof)
+return QualType();
+
   Expr *E = OrigOp.get()->IgnoreParens();
   if (!isa(E)) {
 assert(cast(E)->getOpcode() == UO_AddrOf);
@@ -15094,7 +15100,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult 
&OrigOp, SourceLocation OpLoc) {
 }
   }
 
-  if (getLangOpts().C99) {
+  if (!IsBuiltinAddressof && getLangOpts().C99) {
 // Implement C99-only parts of addressof rules.
 if (UnaryOperator* uOp = dyn_cast(op)) {
   if (uOp->getOpcode() == UO_Deref)
@@ -15116,11 +15122,11 @@ QualType Sema::CheckAddressOfOperand(ExprResult 
&OrigOp, SourceLocation OpLoc) {
   unsigned AddressOfError = AO_No_Error;
 
   if (lval == Expr::LV_ClassTemporary || lval == Expr::LV_ArrayTemporary) {
-bool sfinae = (bool)isS

[libcxx] [clang] [SemaCXX] Implement CWG2137 (list-initialization from objects of the same type) (PR #77768)

2024-01-13 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/77768

>From 7b6bd8158ecc4645e26ec2f6fd6e7c5215bb038a Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sat, 22 Jul 2023 20:07:00 +0100
Subject: [PATCH 1/2] [SemaCXX] Implement CWG2137 (list-initialization from
 objects of the same type)

Differential Revision: https://reviews.llvm.org/D156032
---
 clang/docs/ReleaseNotes.rst   |  2 +
 clang/lib/Sema/SemaInit.cpp   | 14 +++---
 clang/lib/Sema/SemaOverload.cpp   | 38 +++-
 clang/test/CXX/drs/dr14xx.cpp | 10 -
 clang/test/CXX/drs/dr21xx.cpp | 45 +++
 clang/www/cxx_dr_status.html  |  2 +-
 .../pairs.pair/ctor.pair_U_V_move.pass.cpp| 21 -
 7 files changed, 103 insertions(+), 29 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 59732962caac652..a52fb805497756d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -199,6 +199,8 @@ C++2c Feature Support
 
 Resolutions to C++ Defect Reports
 ^
+- Implemented `CWG2137 `_ which allows
+  list-initialization from objects of the same type.
 
 C Language Changes
 --
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 408ee5f775804b6..a3a7486af093fb4 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -4199,7 +4199,7 @@ static OverloadingResult ResolveConstructorOverload(
 /// \param IsListInit Is this list-initialization?
 /// \param IsInitListCopy Is this non-list-initialization resulting from a
 ///   list-initialization from {x} where x is the same
-///   type as the entity?
+///   aggregate type as the entity?
 static void TryConstructorInitialization(Sema &S,
  const InitializedEntity &Entity,
  const InitializationKind &Kind,
@@ -4239,8 +4239,8 @@ static void TryConstructorInitialization(Sema &S,
   // ObjC++: Lambda captured by the block in the lambda to block conversion
   // should avoid copy elision.
   if (S.getLangOpts().CPlusPlus17 && !RequireActualConstructor &&
-  UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isPRValue() &&
-  S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) 
{
+  Args.size() == 1 && Args[0]->isPRValue() &&
+  S.Context.hasSameUnqualifiedType(Args[0]->getType(), DestType)) {
 // Convert qualifications if necessary.
 Sequence.AddQualificationConversionStep(DestType, VK_PRValue);
 if (ILE)
@@ -4571,9 +4571,9 @@ static void TryListInitialization(Sema &S,
 return;
   }
 
-  // C++11 [dcl.init.list]p3, per DR1467:
-  // - If T is a class type and the initializer list has a single element of
-  //   type cv U, where U is T or a class derived from T, the object is
+  // C++11 [dcl.init.list]p3, per DR1467 and DR2137:
+  // - If T is an aggregate class and the initializer list has a single element
+  //   of type cv U, where U is T or a class derived from T, the object is
   //   initialized from that element (by copy-initialization for
   //   copy-list-initialization, or by direct-initialization for
   //   direct-list-initialization).
@@ -4584,7 +4584,7 @@ static void TryListInitialization(Sema &S,
   // - Otherwise, if T is an aggregate, [...] (continue below).
   if (S.getLangOpts().CPlusPlus11 && InitList->getNumInits() == 1 &&
   !IsDesignatedInit) {
-if (DestType->isRecordType()) {
+if (DestType->isRecordType() && DestType->isAggregateType()) {
   QualType InitType = InitList->getInit(0)->getType();
   if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
   S.IsDerivedFrom(InitList->getBeginLoc(), InitType, DestType)) {
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 64bc3851980272c..30bc2036cf781c2 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1562,19 +1562,37 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType 
ToType,
 //   called for those cases.
 if (CXXConstructorDecl *Constructor
   = dyn_cast(ICS.UserDefined.ConversionFunction)) {
-  QualType FromCanon
-= S.Context.getCanonicalType(From->getType().getUnqualifiedType());
+  QualType FromType;
+  SourceLocation FromLoc;
+  // C++11 [over.ics.list]p6, per DR2137:
+  // C++17 [over.ics.list]p6:
+  //   If C is not an initializer-list constructor and the initializer list
+  //   has a single element of type cv U, where U is X or a class derived
+  //   from X, the implicit conversion sequence has Exact Match rank if U 
is
+  //   X, or Conversion rank if U is derived from X.
+  if (const auto *InitList = dyn_cast(From);
+  InitList && InitList->getN

[libcxx] [clang] [SemaCXX] Implement CWG2137 (list-initialization from objects of the same type) (PR #77768)

2024-01-13 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/77768

>From 344366c3f749c43376aca09c5bd563ec823b76f9 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sat, 22 Jul 2023 20:07:00 +0100
Subject: [PATCH 1/2] [SemaCXX] Implement CWG2137 (list-initialization from
 objects of the same type)

Differential Revision: https://reviews.llvm.org/D156032
---
 clang/docs/ReleaseNotes.rst   |  2 +
 clang/lib/Sema/SemaInit.cpp   | 14 +++---
 clang/lib/Sema/SemaOverload.cpp   | 38 +++-
 clang/test/CXX/drs/dr14xx.cpp | 10 -
 clang/test/CXX/drs/dr21xx.cpp | 45 +++
 clang/www/cxx_dr_status.html  |  2 +-
 .../pairs.pair/ctor.pair_U_V_move.pass.cpp| 21 -
 7 files changed, 103 insertions(+), 29 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 59732962caac652..a52fb805497756d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -199,6 +199,8 @@ C++2c Feature Support
 
 Resolutions to C++ Defect Reports
 ^
+- Implemented `CWG2137 `_ which allows
+  list-initialization from objects of the same type.
 
 C Language Changes
 --
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 408ee5f775804b6..a3a7486af093fb4 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -4199,7 +4199,7 @@ static OverloadingResult ResolveConstructorOverload(
 /// \param IsListInit Is this list-initialization?
 /// \param IsInitListCopy Is this non-list-initialization resulting from a
 ///   list-initialization from {x} where x is the same
-///   type as the entity?
+///   aggregate type as the entity?
 static void TryConstructorInitialization(Sema &S,
  const InitializedEntity &Entity,
  const InitializationKind &Kind,
@@ -4239,8 +4239,8 @@ static void TryConstructorInitialization(Sema &S,
   // ObjC++: Lambda captured by the block in the lambda to block conversion
   // should avoid copy elision.
   if (S.getLangOpts().CPlusPlus17 && !RequireActualConstructor &&
-  UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isPRValue() &&
-  S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) 
{
+  Args.size() == 1 && Args[0]->isPRValue() &&
+  S.Context.hasSameUnqualifiedType(Args[0]->getType(), DestType)) {
 // Convert qualifications if necessary.
 Sequence.AddQualificationConversionStep(DestType, VK_PRValue);
 if (ILE)
@@ -4571,9 +4571,9 @@ static void TryListInitialization(Sema &S,
 return;
   }
 
-  // C++11 [dcl.init.list]p3, per DR1467:
-  // - If T is a class type and the initializer list has a single element of
-  //   type cv U, where U is T or a class derived from T, the object is
+  // C++11 [dcl.init.list]p3, per DR1467 and DR2137:
+  // - If T is an aggregate class and the initializer list has a single element
+  //   of type cv U, where U is T or a class derived from T, the object is
   //   initialized from that element (by copy-initialization for
   //   copy-list-initialization, or by direct-initialization for
   //   direct-list-initialization).
@@ -4584,7 +4584,7 @@ static void TryListInitialization(Sema &S,
   // - Otherwise, if T is an aggregate, [...] (continue below).
   if (S.getLangOpts().CPlusPlus11 && InitList->getNumInits() == 1 &&
   !IsDesignatedInit) {
-if (DestType->isRecordType()) {
+if (DestType->isRecordType() && DestType->isAggregateType()) {
   QualType InitType = InitList->getInit(0)->getType();
   if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
   S.IsDerivedFrom(InitList->getBeginLoc(), InitType, DestType)) {
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 64bc3851980272c..30bc2036cf781c2 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1562,19 +1562,37 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType 
ToType,
 //   called for those cases.
 if (CXXConstructorDecl *Constructor
   = dyn_cast(ICS.UserDefined.ConversionFunction)) {
-  QualType FromCanon
-= S.Context.getCanonicalType(From->getType().getUnqualifiedType());
+  QualType FromType;
+  SourceLocation FromLoc;
+  // C++11 [over.ics.list]p6, per DR2137:
+  // C++17 [over.ics.list]p6:
+  //   If C is not an initializer-list constructor and the initializer list
+  //   has a single element of type cv U, where U is X or a class derived
+  //   from X, the implicit conversion sequence has Exact Match rank if U 
is
+  //   X, or Conversion rank if U is derived from X.
+  if (const auto *InitList = dyn_cast(From);
+  InitList && InitList->getN

[clang] [libcxx] [SemaCXX] Implement CWG2137 (list-initialization from objects of the same type) (PR #77768)

2024-01-13 Thread Mital Ashok via cfe-commits


@@ -132,6 +142,36 @@ namespace dr2126 { // dr2126: 12
 #endif
 }
 
+namespace dr2137 { // dr2137: 18
+#if __cplusplus >= 201103L
+  struct Q {
+Q();
+Q(Q&&);
+Q(std::initializer_list) = delete; // since-cxx11-note 2 {{has been 
explicitly marked deleted here}}
+  };
+
+  Q x = Q { Q() }; // since-cxx11-error {{call to deleted constructor}}
+
+  int f(Q); // since-cxx11-note {{passing argument to parameter here}}
+  int y = f({ Q() }); // since-cxx11-error {{call to deleted constructor}}

MitalAshok wrote:

@Endilll Is this good now? Thanks in advance

https://github.com/llvm/llvm-project/pull/77768/files#diff-3426b975672f064b9f32caf4ebab729b815f4f65aa3e76bda4b5bdee986e2e6fR130-R131

https://github.com/llvm/llvm-project/pull/77768/files#diff-8807231ab4d193692d6cecdc6428aaf3c55dfd96101cff8fe0eb7034654658fbR154-R161

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


[clang] [SemaCXX] Implement CWG2351 `void{}` (PR #78060)

2024-01-13 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok created 
https://github.com/llvm/llvm-project/pull/78060

As per [CWG2351](https://wg21.link/CWG2351), allow `void{}`, treated the same 
as `void()`: a prvalue expression of type `void` that performs no 
initialization.

Note that the AST for the expression `T{}` looks like:

```
// using T = int;
CXXFunctionalCastExpr 'T':'int' functional cast to T 
`-InitListExpr 'T':'int'
// using T = const int;
CXXFunctionalCastExpr 'int' functional cast to T 
`-InitListExpr 'int'
// using T = void;
CXXFunctionalCastExpr 'void' functional cast to T 
`-InitListExpr 'void'
// using T = const void;
CXXFunctionalCastExpr 'void' functional cast to T 
`-InitListExpr 'void'
```

(Since the `InitListExpr` already has `void` before anything is done, the type 
doesn't need to be adjusted)

As for `void()`/`T() [T = const void]`, that looked like 
`CXXScalarValueInitExpr 'void'` and is unchanged after this.

For reference, C++98 [5.2.3p2] says:

> The expression `T()`, where `T` is a simple-type-specifier (7.1.5.2) for a 
> non-array complete object type or the (possibly cv-qualified) void type, 
> creates an rvalue of the specified type, whose value is determined by 
> default-initialization (8.5; no initialization is done for the `void()` 
> case).  [*Note:* if `T` is a non-class type that is *cv-qualified*, the 
> `cv-qualifiers` are ignored when determining the type of the resulting rvalue 
> (3.10). ]

Though it is a bit of a misnomer that, for `T = void`, `CXXScalarValueInitExpr` 
does not perform value initialization, it would be a breaking change to change 
the AST node for `void()`, so I simply reworded the doc comment.

>From bdb4b24686e462c9b302f9a6b20ae866a1bf444f Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sat, 13 Jan 2024 18:03:15 +
Subject: [PATCH] [SemaCXX] Implement CWG2351 `void{}`

---
 clang/docs/ReleaseNotes.rst   |  2 ++
 clang/include/clang/AST/ExprCXX.h |  5 +++--
 clang/lib/Sema/SemaExprCXX.cpp| 21 +++--
 clang/test/CXX/drs/dr23xx.cpp | 31 +++
 clang/www/cxx_dr_status.html  |  2 +-
 5 files changed, 52 insertions(+), 9 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3cbce1be159437..00e200ea76e5bc 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -226,6 +226,8 @@ C++2c Feature Support
 
 Resolutions to C++ Defect Reports
 ^
+- Implemented `CWG2351 `_ which allows ``void{}``
+  as a prvalue of type ``void``.
 
 C Language Changes
 --
diff --git a/clang/include/clang/AST/ExprCXX.h 
b/clang/include/clang/AST/ExprCXX.h
index 24278016431837..e7b732e4181127 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -2160,8 +2160,9 @@ class LambdaExpr final : public Expr,
   const_child_range children() const;
 };
 
-/// An expression "T()" which creates a value-initialized rvalue of type
-/// T, which is a non-class type.  See (C++98 [5.2.3p2]).
+/// An expression "T()" which creates an rvalue of type T, which is a
+/// non-class type. For non-void T, the rvalue is value-initialized.
+/// See (C++98 [5.2.3p2]).
 class CXXScalarValueInitExpr : public Expr {
   friend class ASTStmtReader;
 
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 4ae04358d5df7c..1792ec6bb292d5 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1600,12 +1600,21 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
 return ExprError(Diag(TyBeginLoc, diag::err_init_for_function_type)
<< Ty << FullRange);
 
-  // C++17 [expr.type.conv]p2:
-  //   If the type is cv void and the initializer is (), the expression is a
-  //   prvalue of the specified type that performs no initialization.
-  if (!Ty->isVoidType() &&
-  RequireCompleteType(TyBeginLoc, ElemTy,
-  diag::err_invalid_incomplete_type_use, FullRange))
+  // C++17 [expr.type.conv]p2, per DR2351:
+  //   If the type is cv void and the initializer is () or {}, the expression 
is
+  //   a prvalue of the specified type that performs no initialization.
+  if (Ty->isVoidType()) {
+if (Exprs.empty())
+  return new (Context) CXXScalarValueInitExpr(Context.VoidTy, TInfo,
+  Kind.getRange().getEnd());
+if (ListInitialization && cast(Exprs[0])->getNumInits() == 0)
+  return CXXFunctionalCastExpr::Create(
+  Context, Context.VoidTy, VK_PRValue, TInfo, CK_NoOp, Exprs[0],
+  /*Path=*/nullptr, CurFPFeatureOverrides(), Exprs[0]->getBeginLoc(),
+  Exprs[0]->getEndLoc());
+  } else if (RequireCompleteType(TyBeginLoc, ElemTy,
+ diag::err_invalid_incomplete_type_use,
+ FullRange))
 return ExprError();
 
   //   Otherwise, the expression is a prvalue of th

[clang] [SemaCXX] Implement CWG2351 `void{}` (PR #78060)

2024-01-13 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

Initializer list syntax isn't available in C++98 mode (even as an extension? I 
can't find the option)  
Even so, as a defect report it should apply to all prior C++ versions.

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


[clang] [SemaCXX] Implement CWG2351 `void{}` (PR #78060)

2024-01-13 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

Looking at other places, it looks like init-list stuff is guarded behind 
`getLangOpts().CPlusPlus11`, so I'll add that check.

It looks like this DR is CD5 (after C++17, applies to C++17), but `void{}` in 
C++11/14 without a warning seems fine.

As for "regular tests", do you mean in 
[`/clang/test/CXX`](https://github.com/llvm/llvm-project/tree/main/clang/test/CXX)?
 Should I also add tests there?

I also found this: https://stackoverflow.com/q/41131806 that `void({})` 
apparently used to (erroneously) be accepted in Clang 3.8 but I can't find any 
tests for it

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


[clang] [SemaCXX] Implement CWG2351 `void{}` (PR #78060)

2024-01-13 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/78060

>From b33b2bc24ff0af7b2cb0f740826885f1f2dafb49 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sat, 13 Jan 2024 18:03:15 +
Subject: [PATCH] [SemaCXX] Implement CWG2351 `void{}`

---
 clang/docs/ReleaseNotes.rst|  2 ++
 clang/include/clang/AST/ExprCXX.h  |  5 +--
 clang/lib/Sema/SemaExprCXX.cpp | 25 +
 clang/test/CXX/drs/dr23xx.cpp  | 41 +-
 clang/test/SemaCXX/attr-annotate.cpp   |  4 +--
 clang/test/SemaCXX/cxx2a-explicit-bool.cpp |  4 +--
 clang/test/SemaCXX/sugared-auto.cpp|  6 
 clang/www/cxx_dr_status.html   |  2 +-
 8 files changed, 75 insertions(+), 14 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3cbce1be159437..00e200ea76e5bc 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -226,6 +226,8 @@ C++2c Feature Support
 
 Resolutions to C++ Defect Reports
 ^
+- Implemented `CWG2351 `_ which allows ``void{}``
+  as a prvalue of type ``void``.
 
 C Language Changes
 --
diff --git a/clang/include/clang/AST/ExprCXX.h 
b/clang/include/clang/AST/ExprCXX.h
index 24278016431837..e7b732e4181127 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -2160,8 +2160,9 @@ class LambdaExpr final : public Expr,
   const_child_range children() const;
 };
 
-/// An expression "T()" which creates a value-initialized rvalue of type
-/// T, which is a non-class type.  See (C++98 [5.2.3p2]).
+/// An expression "T()" which creates an rvalue of type T, which is a
+/// non-class type. For non-void T, the rvalue is value-initialized.
+/// See (C++98 [5.2.3p2]).
 class CXXScalarValueInitExpr : public Expr {
   friend class ASTStmtReader;
 
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 4ae04358d5df7c..d1229f0182d660 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1600,12 +1600,25 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
 return ExprError(Diag(TyBeginLoc, diag::err_init_for_function_type)
<< Ty << FullRange);
 
-  // C++17 [expr.type.conv]p2:
-  //   If the type is cv void and the initializer is (), the expression is a
-  //   prvalue of the specified type that performs no initialization.
-  if (!Ty->isVoidType() &&
-  RequireCompleteType(TyBeginLoc, ElemTy,
-  diag::err_invalid_incomplete_type_use, FullRange))
+  // C++17 [expr.type.conv]p2, per DR2351:
+  //   If the type is cv void and the initializer is () or {}, the expression 
is
+  //   a prvalue of the specified type that performs no initialization.
+  if (Ty->isVoidType()) {
+
+if (Exprs.empty())
+  return new (Context) CXXScalarValueInitExpr(
+  Ty.getUnqualifiedType(), TInfo, Kind.getRange().getEnd());
+if (ListInitialization &&
+cast(Exprs[0])->getNumInits() == 0) {
+  assert(getLangOpts().CPlusPlus11 && "ListInitialization in C++98/03?");
+  return CXXFunctionalCastExpr::Create(
+  Context, Ty.getUnqualifiedType(), VK_PRValue, TInfo, CK_NoOp,
+  Exprs[0], /*Path=*/nullptr, CurFPFeatureOverrides(),
+  Exprs[0]->getBeginLoc(), Exprs[0]->getEndLoc());
+}
+  } else if (RequireCompleteType(TyBeginLoc, ElemTy,
+ diag::err_invalid_incomplete_type_use,
+ FullRange))
 return ExprError();
 
   //   Otherwise, the expression is a prvalue of the specified type whose
diff --git a/clang/test/CXX/drs/dr23xx.cpp b/clang/test/CXX/drs/dr23xx.cpp
index d2f4e7652ab568..e1d1bd06235b5b 100644
--- a/clang/test/CXX/drs/dr23xx.cpp
+++ b/clang/test/CXX/drs/dr23xx.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -std=c++98 %s -verify=expected -fexceptions 
-fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-03 -fexceptions 
-fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -std=c++03 %s -verify=expected,cxx98-03 -fexceptions 
-fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 // RUN: %clang_cc1 -std=c++11 %s -verify=expected,since-cxx11 -fexceptions 
-fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 // RUN: %clang_cc1 -std=c++14 %s -verify=expected,since-cxx11,since-cxx14 
-fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 // RUN: %clang_cc1 -std=c++17 %s 
-verify=expected,since-cxx11,since-cxx14,since-cxx17 -fexceptions 
-fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
@@ -69,6 +70,44 @@ namespace dr2346 { // dr2346: 11
   }
 }
 
+namespace dr2351 { // dr2351: 18
+#if __cplusplus >= 201103L
+  static_assert((void{}, true), "");
+  // since-cxx11-warning@-1 {{left operand of comma operator has no effect}}
+
+  void f() {
+return void{};

[clang] [clang] [SemaCXX] Implement CWG2627 Bit-fields and narrowing conversions (PR #78112)

2024-01-14 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok created 
https://github.com/llvm/llvm-project/pull/78112

[CWG2627](https://wg21.link/CWG2627)

I've implemented this to apply to C++11 to 20 as well without a warning. Should 
this be a SFINAE-able error before C++23? (It isn't currently)


>From ba22259dfed861e6d33974464c3147465e864d67 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 14 Jan 2024 19:52:31 +
Subject: [PATCH] [clang] [SemaCXX] Implement CWG2627 Bit-fields and narrowing
 conversions

---
 clang/docs/ReleaseNotes.rst   |   4 +
 clang/lib/Sema/SemaOverload.cpp   | 107 +++---
 .../dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp |  24 
 clang/test/CXX/drs/dr26xx.cpp |  46 
 clang/www/cxx_dr_status.html  |   2 +-
 5 files changed, 141 insertions(+), 42 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index dc8a6fe506bce65..6fd84d9c3364d3b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -226,6 +226,10 @@ C++2c Feature Support
 
 Resolutions to C++ Defect Reports
 ^
+- Implemented `CWG2627 `_ which means casts from
+  a bit-field to an integral type is now not considered narrowing if the
+  width of the bit-field means that all potential values are in the range
+  of the target type, even if the type of the bit-field is larger.
 
 C Language Changes
 --
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 23b9bc0fe2d6e2e..b053b9ddfa5f26a 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -433,7 +433,11 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
 
   // -- from an integer type or unscoped enumeration type to an integer type
   //that cannot represent all the values of the original type, except where
-  //the source is a constant expression and the actual value after
+  //-- the source is a bit-field whose width w is less than that of its 
type
+  //(or, for an enumeration type, its underlying type) and the target type
+  //can represent all the values of a hypothetical extended integer type
+  //with width w and with the same signedness as the original type or
+  //-- the source is a constant expression and the actual value after
   //conversion will fit into the target type and will produce the original
   //value when converted back to the original type.
   case ICK_Integral_Conversion:
@@ -441,53 +445,74 @@ NarrowingKind 
StandardConversionSequence::getNarrowingKind(
 assert(FromType->isIntegralOrUnscopedEnumerationType());
 assert(ToType->isIntegralOrUnscopedEnumerationType());
 const bool FromSigned = FromType->isSignedIntegerOrEnumerationType();
-const unsigned FromWidth = Ctx.getIntWidth(FromType);
+unsigned FromWidth = Ctx.getIntWidth(FromType);
 const bool ToSigned = ToType->isSignedIntegerOrEnumerationType();
 const unsigned ToWidth = Ctx.getIntWidth(ToType);
 
-if (FromWidth > ToWidth ||
-(FromWidth == ToWidth && FromSigned != ToSigned) ||
-(FromSigned && !ToSigned)) {
-  // Not all values of FromType can be represented in ToType.
-  const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted);
+constexpr auto CanRepresentAll = [](bool FromSigned, unsigned FromWidth,
+bool ToSigned, unsigned ToWidth) {
+  return (FromWidth < ToWidth + (FromSigned == ToSigned)) &&
+ (FromSigned <= ToSigned);
+};
 
-  // If it's value-dependent, we can't tell whether it's narrowing.
-  if (Initializer->isValueDependent())
-return NK_Dependent_Narrowing;
+if (CanRepresentAll(FromSigned, FromWidth, ToSigned, ToWidth))
+  return NK_Not_Narrowing;
 
-  std::optional OptInitializerValue;
-  if (!(OptInitializerValue = Initializer->getIntegerConstantExpr(Ctx))) {
-// Such conversions on variables are always narrowing.
-return NK_Variable_Narrowing;
-  }
-  llvm::APSInt &InitializerValue = *OptInitializerValue;
-  bool Narrowing = false;
-  if (FromWidth < ToWidth) {
-// Negative -> unsigned is narrowing. Otherwise, more bits is never
-// narrowing.
-if (InitializerValue.isSigned() && InitializerValue.isNegative())
-  Narrowing = true;
-  } else {
-// Add a bit to the InitializerValue so we don't have to worry about
-// signed vs. unsigned comparisons.
-InitializerValue = InitializerValue.extend(
-  InitializerValue.getBitWidth() + 1);
-// Convert the initializer to and from the target width and 
signed-ness.
-llvm::APSInt ConvertedValue = InitializerValue;
-ConvertedValue = ConvertedValue.trunc(ToWidth);
-ConvertedValue.setIsSigned(ToSigned);
-ConvertedValue = ConvertedValue.extend(InitializerV

[clang] [clang] [SemaCXX] Implement CWG2627 Bit-fields and narrowing conversions (PR #78112)

2024-01-15 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/78112

>From 12307d487a956896f283aebf73cdb9b95587d068 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 14 Jan 2024 19:52:31 +
Subject: [PATCH] [clang] [SemaCXX] Implement CWG2627 Bit-fields and narrowing
 conversions

---
 clang/docs/ReleaseNotes.rst   |   4 +
 clang/lib/Sema/SemaOverload.cpp   | 106 +++---
 .../dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp |  24 
 clang/test/CXX/drs/dr26xx.cpp |  80 +
 clang/www/cxx_dr_status.html  |   2 +-
 5 files changed, 174 insertions(+), 42 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7e130304c5c08f..b1b753f8f29846 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -226,6 +226,10 @@ C++2c Feature Support
 
 Resolutions to C++ Defect Reports
 ^
+- Implemented `CWG2627 `_ which means casts from
+  a bit-field to an integral type is now not considered narrowing if the
+  width of the bit-field means that all potential values are in the range
+  of the target type, even if the type of the bit-field is larger.
 
 C Language Changes
 --
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 3222e04378..d9abac5e22ed5d 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -433,7 +433,11 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
 
   // -- from an integer type or unscoped enumeration type to an integer type
   //that cannot represent all the values of the original type, except where
-  //the source is a constant expression and the actual value after
+  //-- the source is a bit-field whose width w is less than that of its 
type
+  //(or, for an enumeration type, its underlying type) and the target type
+  //can represent all the values of a hypothetical extended integer type
+  //with width w and with the same signedness as the original type or
+  //-- the source is a constant expression and the actual value after
   //conversion will fit into the target type and will produce the original
   //value when converted back to the original type.
   case ICK_Integral_Conversion:
@@ -441,53 +445,73 @@ NarrowingKind 
StandardConversionSequence::getNarrowingKind(
 assert(FromType->isIntegralOrUnscopedEnumerationType());
 assert(ToType->isIntegralOrUnscopedEnumerationType());
 const bool FromSigned = FromType->isSignedIntegerOrEnumerationType();
-const unsigned FromWidth = Ctx.getIntWidth(FromType);
+unsigned FromWidth = Ctx.getIntWidth(FromType);
 const bool ToSigned = ToType->isSignedIntegerOrEnumerationType();
 const unsigned ToWidth = Ctx.getIntWidth(ToType);
 
-if (FromWidth > ToWidth ||
-(FromWidth == ToWidth && FromSigned != ToSigned) ||
-(FromSigned && !ToSigned)) {
-  // Not all values of FromType can be represented in ToType.
-  const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted);
+constexpr auto CanRepresentAll = [](bool FromSigned, unsigned FromWidth,
+bool ToSigned, unsigned ToWidth) {
+  return (FromWidth < ToWidth + (FromSigned == ToSigned)) &&
+ (FromSigned <= ToSigned);
+};
 
-  // If it's value-dependent, we can't tell whether it's narrowing.
-  if (Initializer->isValueDependent())
-return NK_Dependent_Narrowing;
+if (CanRepresentAll(FromSigned, FromWidth, ToSigned, ToWidth))
+  return NK_Not_Narrowing;
 
-  std::optional OptInitializerValue;
-  if (!(OptInitializerValue = Initializer->getIntegerConstantExpr(Ctx))) {
-// Such conversions on variables are always narrowing.
-return NK_Variable_Narrowing;
-  }
-  llvm::APSInt &InitializerValue = *OptInitializerValue;
-  bool Narrowing = false;
-  if (FromWidth < ToWidth) {
-// Negative -> unsigned is narrowing. Otherwise, more bits is never
-// narrowing.
-if (InitializerValue.isSigned() && InitializerValue.isNegative())
-  Narrowing = true;
-  } else {
-// Add a bit to the InitializerValue so we don't have to worry about
-// signed vs. unsigned comparisons.
-InitializerValue = InitializerValue.extend(
-  InitializerValue.getBitWidth() + 1);
-// Convert the initializer to and from the target width and 
signed-ness.
-llvm::APSInt ConvertedValue = InitializerValue;
-ConvertedValue = ConvertedValue.trunc(ToWidth);
-ConvertedValue.setIsSigned(ToSigned);
-ConvertedValue = ConvertedValue.extend(InitializerValue.getBitWidth());
-ConvertedValue.setIsSigned(InitializerValue.isSigned());
-// If the result is different, this was a narrowing conversion.
-if (ConvertedV

[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread Mital Ashok via cfe-commits


@@ -1383,6 +1383,34 @@ void CXXRecordDecl::addedMember(Decl *D) {
   }
 }
 
+bool CXXRecordDecl::isLiteral() const {
+  const LangOptions &LangOpts = getLangOpts();
+  if (!(LangOpts.CPlusPlus20 ? hasConstexprDestructor()
+ : hasTrivialDestructor()))
+return false;
+
+  if (isLambda() && !LangOpts.CPlusPlus17)
+return false;
+
+  if (hasNonLiteralTypeFieldsOrBases()) {
+// CWG2598
+// is an aggregate union type that has either no variant
+// members or at least one variant member of non-volatile literal type,
+if (!isUnion())
+  return false;
+bool HasAtLeastOneTrivialMember =
+fields().empty() || any_of(fields(), [this](const FieldDecl *D) {
+  return !D->getType().isVolatileQualified() &&
+ D->getType().isTrivialType(getASTContext());

MitalAshok wrote:

What about literal non-trivial types (e.g. `struct Literal { constexpr 
Literal() {} }; union union6 { NonLiteral NL; Literal L; };`?

`.isLiteralType` should work here

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


[clang] [clang] Fix direct-initialization with new expressions for arrays (PR #78201)

2024-01-15 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok created 
https://github.com/llvm/llvm-project/pull/78201

Fixes #78183

Just removed the check entirely. The diagnostic issued for trying to initialize 
an array (`array initializer must be an initializer list`) is much clearer 
(than `array 'new' cannot have initialization arguments`).


>From 730f7159c04cbb83fa18f50e8db32f6c5295ef6f Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Mon, 15 Jan 2024 18:31:06 +
Subject: [PATCH] [clang] Fix direct-initialization with new expressions for
 arrays

Fixes #78183
---
 clang/docs/ReleaseNotes.rst   |  3 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  2 --
 clang/lib/Sema/SemaExprCXX.cpp| 29 ---
 clang/test/SemaCXX/new-delete.cpp | 21 +++---
 4 files changed, 14 insertions(+), 41 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7e130304c5c08f..a2e757defb3c7f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -937,6 +937,9 @@ Bug Fixes to AST Handling
 - Fixed a bug where Template Instantiation failed to handle Lambda Expressions
   with certain types of Attributes.
   (`#76521 `_)
+- Fixed a bug where the parenthesized initialization of arrays in a new
+  expression were rejected even in C++20 mode.
+  (`#78183 `_)
 
 Miscellaneous Bug Fixes
 ^^^
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 414779a7970ab8..920edebfb70333 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7776,8 +7776,6 @@ def err_new_array_nonconst : Error<
   "only the first dimension of an allocated array may have dynamic size">;
 def err_new_array_size_unknown_from_init : Error<
   "cannot determine allocated array size from initializer">;
-def err_new_array_init_args : Error<
-  "array 'new' cannot have initialization arguments">;
 def ext_new_paren_array_nonconst : ExtWarn<
   "when type is in parentheses, array cannot have dynamic size">;
 def err_placement_new_non_placement_delete : Error<
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 4ae04358d5df7c..efb917f9bcd504 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1946,25 +1946,6 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool 
UseGlobal,
  Initializer);
 }
 
-static bool isLegalArrayNewInitializer(CXXNewInitializationStyle Style,
-   Expr *Init) {
-  if (!Init)
-return true;
-  if (ParenListExpr *PLE = dyn_cast(Init))
-return PLE->getNumExprs() == 0;
-  if (isa(Init))
-return true;
-  else if (CXXConstructExpr *CCE = dyn_cast(Init))
-return !CCE->isListInitialization() &&
-   CCE->getConstructor()->isDefaultConstructor();
-  else if (Style == CXXNewInitializationStyle::List) {
-assert(isa(Init) &&
-   "Shouldn't create list CXXConstructExprs for arrays.");
-return true;
-  }
-  return false;
-}
-
 bool
 Sema::isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const {
   if (!getLangOpts().AlignedAllocationUnavailable)
@@ -2400,16 +2381,6 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool 
UseGlobal,
 }
   }
 
-  // Array 'new' can't have any initializers except empty parentheses.
-  // Initializer lists are also allowed, in C++11. Rely on the parser for the
-  // dialect distinction.
-  if (ArraySize && !isLegalArrayNewInitializer(InitStyle, Initializer)) {
-SourceRange InitRange(Exprs.front()->getBeginLoc(),
-  Exprs.back()->getEndLoc());
-Diag(StartLoc, diag::err_new_array_init_args) << InitRange;
-return ExprError();
-  }
-
   // If we can perform the initialization, and we've not already done so,
   // do it now.
   if (!AllocType->isDependentType() &&
diff --git a/clang/test/SemaCXX/new-delete.cpp 
b/clang/test/SemaCXX/new-delete.cpp
index 0270e42b7389fe..07a8495a35f756 100644
--- a/clang/test/SemaCXX/new-delete.cpp
+++ b/clang/test/SemaCXX/new-delete.cpp
@@ -1,7 +1,8 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu 
-Wno-new-returns-null -std=c++98
-// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu 
-Wno-new-returns-null -std=c++11
-// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu 
-Wno-new-returns-null -std=c++14
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx17 %s 
-triple=i686-pc-linux-gnu -Wno-new-returns-null %std_cxx17-
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,until-cxx20 %s 
-triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++98
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,until-cxx20 %s 
-triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++11
+// RUN: %clang_cc1 -fsyntax-o

[clang] [clang] Fix direct-initialization with new expressions for arrays (PR #78201)

2024-01-15 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/78201

>From 730f7159c04cbb83fa18f50e8db32f6c5295ef6f Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Mon, 15 Jan 2024 18:31:06 +
Subject: [PATCH 1/2] [clang] Fix direct-initialization with new expressions
 for arrays

Fixes #78183
---
 clang/docs/ReleaseNotes.rst   |  3 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  2 --
 clang/lib/Sema/SemaExprCXX.cpp| 29 ---
 clang/test/SemaCXX/new-delete.cpp | 21 +++---
 4 files changed, 14 insertions(+), 41 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7e130304c5c08f8..a2e757defb3c7fd 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -937,6 +937,9 @@ Bug Fixes to AST Handling
 - Fixed a bug where Template Instantiation failed to handle Lambda Expressions
   with certain types of Attributes.
   (`#76521 `_)
+- Fixed a bug where the parenthesized initialization of arrays in a new
+  expression were rejected even in C++20 mode.
+  (`#78183 `_)
 
 Miscellaneous Bug Fixes
 ^^^
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 414779a7970ab8e..920edebfb70 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7776,8 +7776,6 @@ def err_new_array_nonconst : Error<
   "only the first dimension of an allocated array may have dynamic size">;
 def err_new_array_size_unknown_from_init : Error<
   "cannot determine allocated array size from initializer">;
-def err_new_array_init_args : Error<
-  "array 'new' cannot have initialization arguments">;
 def ext_new_paren_array_nonconst : ExtWarn<
   "when type is in parentheses, array cannot have dynamic size">;
 def err_placement_new_non_placement_delete : Error<
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 4ae04358d5df7c8..efb917f9bcd5045 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1946,25 +1946,6 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool 
UseGlobal,
  Initializer);
 }
 
-static bool isLegalArrayNewInitializer(CXXNewInitializationStyle Style,
-   Expr *Init) {
-  if (!Init)
-return true;
-  if (ParenListExpr *PLE = dyn_cast(Init))
-return PLE->getNumExprs() == 0;
-  if (isa(Init))
-return true;
-  else if (CXXConstructExpr *CCE = dyn_cast(Init))
-return !CCE->isListInitialization() &&
-   CCE->getConstructor()->isDefaultConstructor();
-  else if (Style == CXXNewInitializationStyle::List) {
-assert(isa(Init) &&
-   "Shouldn't create list CXXConstructExprs for arrays.");
-return true;
-  }
-  return false;
-}
-
 bool
 Sema::isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const {
   if (!getLangOpts().AlignedAllocationUnavailable)
@@ -2400,16 +2381,6 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool 
UseGlobal,
 }
   }
 
-  // Array 'new' can't have any initializers except empty parentheses.
-  // Initializer lists are also allowed, in C++11. Rely on the parser for the
-  // dialect distinction.
-  if (ArraySize && !isLegalArrayNewInitializer(InitStyle, Initializer)) {
-SourceRange InitRange(Exprs.front()->getBeginLoc(),
-  Exprs.back()->getEndLoc());
-Diag(StartLoc, diag::err_new_array_init_args) << InitRange;
-return ExprError();
-  }
-
   // If we can perform the initialization, and we've not already done so,
   // do it now.
   if (!AllocType->isDependentType() &&
diff --git a/clang/test/SemaCXX/new-delete.cpp 
b/clang/test/SemaCXX/new-delete.cpp
index 0270e42b7389fec..07a8495a35f7561 100644
--- a/clang/test/SemaCXX/new-delete.cpp
+++ b/clang/test/SemaCXX/new-delete.cpp
@@ -1,7 +1,8 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu 
-Wno-new-returns-null -std=c++98
-// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu 
-Wno-new-returns-null -std=c++11
-// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu 
-Wno-new-returns-null -std=c++14
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx17 %s 
-triple=i686-pc-linux-gnu -Wno-new-returns-null %std_cxx17-
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,until-cxx20 %s 
-triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++98
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,until-cxx20 %s 
-triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++11
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,until-cxx20 %s 
-triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++14
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,until-cxx20,cxx17 %s 
-triple=i686-pc-linux-gnu -Wno-new-returns-null -st

[clang] [clang] Fix direct-initialization with new expressions for arrays (PR #78201)

2024-01-16 Thread Mital Ashok via cfe-commits

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


[clang] [clang] Fix direct-initialization with new expressions for arrays (PR #78201)

2024-01-16 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

Yeah #76976 supersedes this.

I would still recommend removing `diag::err_new_array_init_args` if only so:

```c++
int x[2](1, 2);
int* y = new int[2](1, 2);
```

have similar error messages.

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


[clang] [clang] Fix direct-initialization with new expressions for arrays (PR #78201)

2024-01-16 Thread Mital Ashok via cfe-commits

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


[clang] [SemaCXX] Make __builtin_addressof more like std::addressof (PR #78035)

2024-01-16 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/78035

>From 33af5fc0a2e1ec2168a1609508cb119034801908 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sat, 13 Jan 2024 10:48:21 +
Subject: [PATCH] [SemaCXX] Make __builtin_addressof more like std::addressof

Properly disable __builtin_addressof(f) where f is an overloaded function and 
__builtin_addressof(temporary).

__builtin_addressof(E) should now only work if E is bindable to an lvalue 
reference with the same type.
---
 clang/include/clang/Sema/Sema.h |  3 ++-
 clang/lib/Sema/SemaChecking.cpp |  3 ++-
 clang/lib/Sema/SemaExpr.cpp | 26 +++---
 clang/test/SemaCXX/builtins.cpp | 38 -
 4 files changed, 59 insertions(+), 11 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b55f7584913b46..67627a338a6268 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5802,7 +5802,8 @@ class Sema final {
  const Expr *Op,
  const CXXMethodDecl *MD);
 
-  QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
+  QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc,
+ bool IsBuiltinAddressof = false);
 
   bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N);
 
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index ace3e386988f00..31f60b10e09f96 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -242,7 +242,8 @@ static bool SemaBuiltinAddressof(Sema &S, CallExpr 
*TheCall) {
 return true;
 
   ExprResult Arg(TheCall->getArg(0));
-  QualType ResultType = S.CheckAddressOfOperand(Arg, TheCall->getBeginLoc());
+  QualType ResultType = S.CheckAddressOfOperand(Arg, TheCall->getBeginLoc(),
+/*IsBuiltinAddressof=*/true);
   if (ResultType.isNull())
 return true;
 
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 2aa192c3909cbe..13c00c9bf970ed 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -15015,9 +15015,15 @@ bool 
Sema::CheckUseOfCXXMethodAsAddressOfOperand(SourceLocation OpLoc,
 /// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue.
 /// In C++, the operand might be an overloaded function name, in which case
 /// we allow the '&' but retain the overloaded-function type.
-QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) 
{
+/// If IsBuiltinAddressof is true, this is spelt __builtin_addressof(E)
+/// instead of &E.
+QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc,
+ bool IsBuiltinAddressof) {
   if (const BuiltinType *PTy = 
OrigOp.get()->getType()->getAsPlaceholderType()){
 if (PTy->getKind() == BuiltinType::Overload) {
+  if (IsBuiltinAddressof)
+return QualType();
+
   Expr *E = OrigOp.get()->IgnoreParens();
   if (!isa(E)) {
 assert(cast(E)->getOpcode() == UO_AddrOf);
@@ -15071,7 +15077,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult 
&OrigOp, SourceLocation OpLoc) {
 }
   }
 
-  if (getLangOpts().C99) {
+  if (!IsBuiltinAddressof && getLangOpts().C99) {
 // Implement C99-only parts of addressof rules.
 if (UnaryOperator* uOp = dyn_cast(op)) {
   if (uOp->getOpcode() == UO_Deref)
@@ -15093,11 +15099,11 @@ QualType Sema::CheckAddressOfOperand(ExprResult 
&OrigOp, SourceLocation OpLoc) {
   unsigned AddressOfError = AO_No_Error;
 
   if (lval == Expr::LV_ClassTemporary || lval == Expr::LV_ArrayTemporary) {
-bool sfinae = (bool)isSFINAEContext();
-Diag(OpLoc, isSFINAEContext() ? diag::err_typecheck_addrof_temporary
-  : diag::ext_typecheck_addrof_temporary)
-  << op->getType() << op->getSourceRange();
-if (sfinae)
+bool AllowTemporaryAddress = !isSFINAEContext() && !IsBuiltinAddressof;
+Diag(OpLoc, AllowTemporaryAddress ? diag::ext_typecheck_addrof_temporary
+  : diag::err_typecheck_addrof_temporary)
+<< op->getType() << op->getSourceRange();
+if (!AllowTemporaryAddress)
   return QualType();
 // Materialize the temporary as an lvalue so that we can take its address.
 OrigOp = op =
@@ -15107,6 +15113,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult 
&OrigOp, SourceLocation OpLoc) {
   } else if (lval == Expr::LV_MemberFunction) {
 // If it's an instance method, make a member pointer.
 // The expression must have exactly the form &A::foo.
+if (IsBuiltinAddressof)
+  return QualType();
 
 // If the underlying expression isn't a decl ref, give up.
 if (!isa(op)) {
@@ -15164,12 +15172,14 @@ QualType Sema::CheckAddressOfOperand(ExprResult 
&OrigOp, SourceLocat

[clang] [Clang] fix static operator()/[] call not evaluating object (PR #78356)

2024-01-16 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok created 
https://github.com/llvm/llvm-project/pull/78356

Fixes #78355

>From 08c7087d4b40a915f123ba3c448a6ca3233af6a1 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Tue, 16 Jan 2024 21:42:01 +
Subject: [PATCH] [Clang] fix static operator()/[] call not evaluating object

---
 clang/lib/Sema/SemaOverload.cpp| 20 ++--
 clang/test/SemaCXX/overloaded-operator.cpp | 28 +-
 2 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 37c62b306b3cd3..cde0f3c13e4d9c 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -15089,10 +15089,12 @@ ExprResult 
Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
   TheCall = CXXOperatorCallExpr::Create(
   Context, OO_Subscript, FnExpr.get(), MethodArgs, ResultTy, VK,
   RLoc, CurFPFeatureOverrides());
-else
-  TheCall =
-  CallExpr::Create(Context, FnExpr.get(), MethodArgs, ResultTy, VK,
-   RLoc, CurFPFeatureOverrides());
+else {
+  if (Base->isPRValue())
+Base = 
CreateMaterializeTemporaryExpr(Base->getType().getNonReferenceType(), Base, 
/*BoundToLvalueReference=*/false);
+  ExprResult OperatorAccess = MemberExpr::Create(Context, Base, 
/*IsArrow=*/false, LLoc, NestedNameSpecifierLoc(), SourceLocation(), FnDecl, 
Best->FoundDecl, OpLocInfo, nullptr, FnDecl->getType(), 
ExprValueKind::VK_LValue, ExprObjectKind::OK_Ordinary, 
NonOdrUseReason::NOUR_None);
+  TheCall = CallExpr::Create(Context, 
CallExprUnaryConversions(OperatorAccess.get()).get(), MethodArgs, ResultTy, VK, 
RLoc, CurFPFeatureOverrides());
+}
 
 if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, 
FnDecl))
   return ExprError();
@@ -15767,9 +15769,13 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
 TheCall = CXXOperatorCallExpr::Create(Context, OO_Call, NewFn.get(),
   MethodArgs, ResultTy, VK, RParenLoc,
   CurFPFeatureOverrides());
-  else
-TheCall = CallExpr::Create(Context, NewFn.get(), MethodArgs, ResultTy, VK,
-   RParenLoc, CurFPFeatureOverrides());
+  else {
+Expr *Base = Object.get();
+if (Base->isPRValue())
+  Base = 
CreateMaterializeTemporaryExpr(Base->getType().getNonReferenceType(), Base, 
/*BoundToLvalueReference=*/false);
+ExprResult OperatorAccess = MemberExpr::Create(Context, Base, 
/*IsArrow=*/false, LParenLoc, NestedNameSpecifierLoc(), SourceLocation(), 
Method, Best->FoundDecl, OpLocInfo, nullptr, Method->getType(), 
ExprValueKind::VK_LValue, ExprObjectKind::OK_Ordinary, 
NonOdrUseReason::NOUR_None);
+TheCall = CallExpr::Create(Context, 
CallExprUnaryConversions(OperatorAccess.get()).get(), MethodArgs, ResultTy, VK, 
RParenLoc, CurFPFeatureOverrides());
+  }
 
   if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
 return true;
diff --git a/clang/test/SemaCXX/overloaded-operator.cpp 
b/clang/test/SemaCXX/overloaded-operator.cpp
index 83a7e65b43dd01..361adda58e48b6 100644
--- a/clang/test/SemaCXX/overloaded-operator.cpp
+++ b/clang/test/SemaCXX/overloaded-operator.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s 
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s
+
 class X { };
 
 X operator+(X, X);
@@ -598,3 +600,27 @@ namespace B {
 }
 void g(B::X x) { A::f(x); }
 }
+
+namespace static_operator {
+#if __cplusplus >= 201703L
+struct X {
+  static constexpr int operator()() { return 0; }
+  // expected-warning@-1 {{declaring overloaded 'operator()' as 'static' is a 
C++23 extension}}
+  static constexpr int operator[](int) { return 0; }
+  // expected-warning@-1 {{declaring overloaded 'operator[]' as 'static' is a 
C++23 extension}}
+};
+
+constexpr int f(int x) {
+  return (++x, X())(), (++x, X())[1], x;
+}
+
+static_assert(f(0) == 2, "");
+
+constexpr int g(int x) {
+  return (++x, []() static { return 0; })(), x;
+  // expected-warning@-1 {{static lambdas are a C++23 extension}}
+}
+
+static_assert(g(0) == 1, "");
+#endif
+}

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] fix static operator()/[] call not evaluating object (PR #78356)

2024-01-16 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/78356

>From c6d4aca37bf7ede785313135abdad986d9cd783a Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Tue, 16 Jan 2024 21:42:01 +
Subject: [PATCH] [Clang] fix static operator()/[] call not evaluating object

---
 clang/lib/Sema/SemaOverload.cpp| 36 +-
 clang/test/SemaCXX/overloaded-operator.cpp | 28 -
 2 files changed, 56 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 37c62b306b3cd3f..d34fa54bc9889a2 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -15089,10 +15089,20 @@ ExprResult 
Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
   TheCall = CXXOperatorCallExpr::Create(
   Context, OO_Subscript, FnExpr.get(), MethodArgs, ResultTy, VK,
   RLoc, CurFPFeatureOverrides());
-else
-  TheCall =
-  CallExpr::Create(Context, FnExpr.get(), MethodArgs, ResultTy, VK,
-   RLoc, CurFPFeatureOverrides());
+else {
+  if (Base->isPRValue())
+Base = CreateMaterializeTemporaryExpr(
+Base->getType().getNonReferenceType(), Base,
+/*BoundToLvalueReference=*/false);
+  ExprResult OperatorAccess = MemberExpr::Create(
+  Context, Base, /*IsArrow=*/false, LLoc, NestedNameSpecifierLoc(),
+  SourceLocation(), FnDecl, Best->FoundDecl, OpLocInfo, nullptr,
+  FnDecl->getType(), ExprValueKind::VK_LValue,
+  ExprObjectKind::OK_Ordinary, NonOdrUseReason::NOUR_None);
+  TheCall = CallExpr::Create(
+  Context, CallExprUnaryConversions(OperatorAccess.get()).get(),
+  MethodArgs, ResultTy, VK, RLoc, CurFPFeatureOverrides());
+}
 
 if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, 
FnDecl))
   return ExprError();
@@ -15767,9 +15777,21 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
 TheCall = CXXOperatorCallExpr::Create(Context, OO_Call, NewFn.get(),
   MethodArgs, ResultTy, VK, RParenLoc,
   CurFPFeatureOverrides());
-  else
-TheCall = CallExpr::Create(Context, NewFn.get(), MethodArgs, ResultTy, VK,
-   RParenLoc, CurFPFeatureOverrides());
+  else {
+Expr *Base = Object.get();
+if (Base->isPRValue())
+  Base = CreateMaterializeTemporaryExpr(
+  Base->getType().getNonReferenceType(), Base,
+  /*BoundToLvalueReference=*/false);
+ExprResult OperatorAccess = MemberExpr::Create(
+Context, Base, /*IsArrow=*/false, LParenLoc, NestedNameSpecifierLoc(),
+SourceLocation(), Method, Best->FoundDecl, OpLocInfo, nullptr,
+Method->getType(), ExprValueKind::VK_LValue,
+ExprObjectKind::OK_Ordinary, NonOdrUseReason::NOUR_None);
+TheCall = CallExpr::Create(
+Context, CallExprUnaryConversions(OperatorAccess.get()).get(),
+MethodArgs, ResultTy, VK, RParenLoc, CurFPFeatureOverrides());
+  }
 
   if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
 return true;
diff --git a/clang/test/SemaCXX/overloaded-operator.cpp 
b/clang/test/SemaCXX/overloaded-operator.cpp
index 83a7e65b43dd012..361adda58e48b63 100644
--- a/clang/test/SemaCXX/overloaded-operator.cpp
+++ b/clang/test/SemaCXX/overloaded-operator.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s 
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s
+
 class X { };
 
 X operator+(X, X);
@@ -598,3 +600,27 @@ namespace B {
 }
 void g(B::X x) { A::f(x); }
 }
+
+namespace static_operator {
+#if __cplusplus >= 201703L
+struct X {
+  static constexpr int operator()() { return 0; }
+  // expected-warning@-1 {{declaring overloaded 'operator()' as 'static' is a 
C++23 extension}}
+  static constexpr int operator[](int) { return 0; }
+  // expected-warning@-1 {{declaring overloaded 'operator[]' as 'static' is a 
C++23 extension}}
+};
+
+constexpr int f(int x) {
+  return (++x, X())(), (++x, X())[1], x;
+}
+
+static_assert(f(0) == 2, "");
+
+constexpr int g(int x) {
+  return (++x, []() static { return 0; })(), x;
+  // expected-warning@-1 {{static lambdas are a C++23 extension}}
+}
+
+static_assert(g(0) == 1, "");
+#endif
+}

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Fix parenthesized list initialization of arrays not working with `new` (PR #76976)

2024-01-17 Thread Mital Ashok via cfe-commits


@@ -1073,7 +1075,7 @@ void CodeGenFunction::EmitNewArrayInitializer(
   return;
 }
 
-InitListElements = ILE->getNumInits();
+InitListElements = ILE ? ILE->getNumInits() : CPLIE->getInitExprs().size();

MitalAshok wrote:

```suggestion
ArrayRef InitExprs = ILE ? ILE->inits() : 
CPLIE->getInitExprs();
InitListElements = InitExprs.size();
```

If you move this up from below it can look cleaner

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


[clang] [clang] Fix parenthesized list initialization of arrays not working with `new` (PR #76976)

2024-01-17 Thread Mital Ashok via cfe-commits


@@ -1561,16 +1577,21 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const 
CXXNewExpr *E) {
   // 1. Build a call to the allocation function.
   FunctionDecl *allocator = E->getOperatorNew();
 
-  // If there is a brace-initializer, cannot allocate fewer elements than 
inits.
+  // If there is a brace-initializer or C++20 parenthesized initializer, cannot
+  // allocate fewer elements than inits.
   unsigned minElements = 0;
   if (E->isArray() && E->hasInitializer()) {
-const InitListExpr *ILE = dyn_cast(E->getInitializer());
-if (ILE && ILE->isStringLiteralInit())
+const Expr *Init = E->getInitializer();
+const InitListExpr *ILE = dyn_cast(Init);
+const CXXParenListInitExpr *CPLIE = dyn_cast(Init);
+if ((ILE && ILE->isStringLiteralInit()) || isa(Init)) {

MitalAshok wrote:

You forget to `IgnoreParenImpCasts` or check for `ObjCEncodeExpr`. Currently:

```c++
// seg fault
int n = 0; char* p = new char[n](("a"));

// throws bad_alloc (expected)
int n = 0; char* p = new char[n](("a"));
```

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


[clang] [clang] Fix parenthesized list initialization of arrays not working with `new` (PR #76976)

2024-01-17 Thread Mital Ashok via cfe-commits

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


[clang] [Clang] fix static operator()/[] call not evaluating object (PR #78356)

2024-01-19 Thread Mital Ashok via cfe-commits


@@ -598,3 +600,27 @@ namespace B {
 }
 void g(B::X x) { A::f(x); }
 }
+
+namespace static_operator {
+#if __cplusplus >= 201703L

MitalAshok wrote:

No way to modify things in a C++11/14 constexpr function (`++x` is not a 
constant expression), so no way to make a positive test that the expression was 
evaluated. Though I guess I should have done `(non_constexpr_fn(), X())()` and 
see if that failed.

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


[clang] [Clang] fix static operator()/[] call not evaluating object (PR #78356)

2024-01-19 Thread Mital Ashok via cfe-commits

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


[clang] [Clang] fix static operator()/[] call not evaluating object (PR #78356)

2024-01-19 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

This pull request changes `E(...)` to produce the same AST as 
`E.operator()(...)`, which is similar to `E.f(...)` for a static member 
function `f`.

But the linked #68485 changes this to CXXOperatorCallExpr, which is more 
appropriate since it is used for non-member call operators like anyways

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


[libcxx] [clang] [SemaCXX] Implement CWG2137 (list-initialization from objects of the same type) (PR #77768)

2024-01-19 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/77768

>From 644ec10fc357f70ca8af94ae6544e9631021eb5e Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sat, 22 Jul 2023 20:07:00 +0100
Subject: [PATCH 1/2] [SemaCXX] Implement CWG2137 (list-initialization from
 objects of the same type)

Differential Revision: https://reviews.llvm.org/D156032
---
 clang/docs/ReleaseNotes.rst   |  2 +
 clang/lib/Sema/SemaInit.cpp   | 14 +++---
 clang/lib/Sema/SemaOverload.cpp   | 38 +++-
 clang/test/CXX/drs/dr14xx.cpp | 10 -
 clang/test/CXX/drs/dr21xx.cpp | 45 +++
 clang/www/cxx_dr_status.html  |  2 +-
 .../pairs.pair/ctor.pair_U_V_move.pass.cpp| 21 -
 7 files changed, 103 insertions(+), 29 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 392f694065a242..745ec4f5b3a6d9 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -229,6 +229,8 @@ C++2c Feature Support
 
 Resolutions to C++ Defect Reports
 ^
+- Implemented `CWG2137 `_ which allows
+  list-initialization from objects of the same type.
 
 - Implemented `CWG2598 `_ and `CWG2096 
`_,
   making unions (that have either no members or at least one literal member) 
literal types.
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 18440a69e3a3d9..6b2a77690049d2 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -4200,7 +4200,7 @@ static OverloadingResult ResolveConstructorOverload(
 /// \param IsListInit Is this list-initialization?
 /// \param IsInitListCopy Is this non-list-initialization resulting from a
 ///   list-initialization from {x} where x is the same
-///   type as the entity?
+///   aggregate type as the entity?
 static void TryConstructorInitialization(Sema &S,
  const InitializedEntity &Entity,
  const InitializationKind &Kind,
@@ -4240,8 +4240,8 @@ static void TryConstructorInitialization(Sema &S,
   // ObjC++: Lambda captured by the block in the lambda to block conversion
   // should avoid copy elision.
   if (S.getLangOpts().CPlusPlus17 && !RequireActualConstructor &&
-  UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isPRValue() &&
-  S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) 
{
+  Args.size() == 1 && Args[0]->isPRValue() &&
+  S.Context.hasSameUnqualifiedType(Args[0]->getType(), DestType)) {
 // Convert qualifications if necessary.
 Sequence.AddQualificationConversionStep(DestType, VK_PRValue);
 if (ILE)
@@ -4572,9 +4572,9 @@ static void TryListInitialization(Sema &S,
 return;
   }
 
-  // C++11 [dcl.init.list]p3, per DR1467:
-  // - If T is a class type and the initializer list has a single element of
-  //   type cv U, where U is T or a class derived from T, the object is
+  // C++11 [dcl.init.list]p3, per DR1467 and DR2137:
+  // - If T is an aggregate class and the initializer list has a single element
+  //   of type cv U, where U is T or a class derived from T, the object is
   //   initialized from that element (by copy-initialization for
   //   copy-list-initialization, or by direct-initialization for
   //   direct-list-initialization).
@@ -4585,7 +4585,7 @@ static void TryListInitialization(Sema &S,
   // - Otherwise, if T is an aggregate, [...] (continue below).
   if (S.getLangOpts().CPlusPlus11 && InitList->getNumInits() == 1 &&
   !IsDesignatedInit) {
-if (DestType->isRecordType()) {
+if (DestType->isRecordType() && DestType->isAggregateType()) {
   QualType InitType = InitList->getInit(0)->getType();
   if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
   S.IsDerivedFrom(InitList->getBeginLoc(), InitType, DestType)) {
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index bbbd0abc82d740..6ee5f26d55c3a5 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1568,19 +1568,37 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType 
ToType,
 //   called for those cases.
 if (CXXConstructorDecl *Constructor
   = dyn_cast(ICS.UserDefined.ConversionFunction)) {
-  QualType FromCanon
-= S.Context.getCanonicalType(From->getType().getUnqualifiedType());
+  QualType FromType;
+  SourceLocation FromLoc;
+  // C++11 [over.ics.list]p6, per DR2137:
+  // C++17 [over.ics.list]p6:
+  //   If C is not an initializer-list constructor and the initializer list
+  //   has a single element of type cv U, where U is X or a class derived
+  //   from X, the implicit conversion sequence has Exact Match rank if U 
i

[libcxx] [clang] [SemaCXX] Implement CWG2137 (list-initialization from objects of the same type) (PR #77768)

2024-01-19 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

@cor3ntin It looks like it was in an unrelated file. I've rebased and the 
format check is passing now

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


[libcxx] [clang] [SemaCXX] Implement CWG2137 (list-initialization from objects of the same type) (PR #77768)

2024-01-19 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

@cor3ntin Still waiting for Windows checks, but yes, could you merge if you 
please

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


[clang] [clang] Warn when builtin names are used outside of invocations (PR #96097)

2024-06-29 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

Looks like `!__is_identifier()` is used instead of 
`__has_builtin` sometimes. With this patch, `__is_identifier()` is true because there's no lparen after the name

In libc++: 7f302f220e7b8727ed1bf8832dcc2d87b897e527 (Pretty easy fix to replace 
`__has_keyword(__reference_binds_to_temporary)` with 
`__has_builtin(__reference_binds_to_temporary)` again though)

In WIL which seems to be used by a few people: 
https://github.com/microsoft/wil/blob/68ab8c19ef557e1006cae6b1b84dedf12c91c9d6/include/wil/wistd_config.h#L249

libstdc++, indirectly through a macro: 
https://gcc.gnu.org/git/?p=gcc.git;a=blobdiff;f=libstdc%2B%2B-v3/include/bits/c%2B%2Bconfig;h=27302ed392eb163954c5a2d367831dbcb0ead3c3;hp=2e6c880ad95a1cc1dfdead2bbcfb977960172ac5;hb=6aa12274007bccbae2691a9d336c37fe167bb535;hpb=6ea5a23766b8077a503362c4fa6f51de92669c11

These will now all report that those things are identifiers and not available 
as builtins. It can be supported with the same workaround used for 
`__has_builtin`. Apparantly `__has_feature(__is_abstract)` is also supposed to 
be true 
(https://github.com/llvm/llvm-project/blob/8d4aa1f22ea08b12a7958b681e8a265f78cb349f/clang/docs/LanguageExtensions.rst?plain=1#L1693),
 but that seems to be broken on main and not a new issue with this patch.

---

Also it doesn't seem ideal to not support things like:

```c++
#define IS_CLASS __is_class
static_assert(!IS_CLASS(void));
```

Since these are supported by GCC and MSVC. Could you check again for an lparen 
after a macro expansion?

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


[clang] [clang][NFC] Use range-based for loops (PR #96831)

2024-06-29 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok approved this pull request.

LGTM

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


[clang] [clang] Warn when builtin names are used outside of invocations (PR #96097)

2024-06-29 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

What if we went in the other direction? We want to deprecate `__is_pointer` as 
an identifier, so only make it an identifier when it is being used by libstdc++ 
as an identifier. libstdc++ usage looks something like:

```c++
// type template
template
struct __is_pointer;
template
struct __is_pointer : true_type {};
__is_pointer::value

// variable template
template
inline constexpr bool __is_pointer = ...
__is_pointer
```

So only make it an identifier if it is preceded by `struct`/`class` or if it is 
succeeded by `<`/`=`?

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


[clang] [NFC] [Clang] Some core issues have changed status from tentatively ready -> ready / review (PR #97200)

2024-06-30 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok created 
https://github.com/llvm/llvm-project/pull/97200

Also classes the "ready" status similarly to "tentatively ready" in 
make_cxx_dr_status


>From 0dea95701ca4dfca9b7d0bd889003fc35aa3017e Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 30 Jun 2024 10:39:15 +0100
Subject: [PATCH] [NFC] [Clang] Some core issues have changed status from
 tentatively ready -> ready / review

---
 clang/test/CXX/drs/cwg25xx.cpp |   2 +-
 clang/test/CXX/drs/cwg28xx.cpp |  16 ++--
 clang/www/cxx_dr_status.html   | 130 +++--
 clang/www/make_cxx_dr_status   |   6 +-
 4 files changed, 104 insertions(+), 50 deletions(-)

diff --git a/clang/test/CXX/drs/cwg25xx.cpp b/clang/test/CXX/drs/cwg25xx.cpp
index 0934f0cc19c6a..5f8a058f8157a 100644
--- a/clang/test/CXX/drs/cwg25xx.cpp
+++ b/clang/test/CXX/drs/cwg25xx.cpp
@@ -139,7 +139,7 @@ struct D3 : B {
 #endif
 
 #if __cplusplus >= 202302L
-namespace cwg2561 { // cwg2561: no tentatively ready 2024-03-18
+namespace cwg2561 { // cwg2561: no ready 2024-03-18
 struct C {
 constexpr C(auto) { }
 };
diff --git a/clang/test/CXX/drs/cwg28xx.cpp b/clang/test/CXX/drs/cwg28xx.cpp
index c77bd433d8e21..524e67b52de51 100644
--- a/clang/test/CXX/drs/cwg28xx.cpp
+++ b/clang/test/CXX/drs/cwg28xx.cpp
@@ -30,7 +30,7 @@ using U2 = decltype(&main);
 #endif
 } // namespace cwg2811
 
-namespace cwg2819 { // cwg2819: 19 tentatively ready 2023-12-01
+namespace cwg2819 { // cwg2819: 19 ready 2023-12-01
 #if __cpp_constexpr >= 202306L
   constexpr void* p = nullptr;
   constexpr int* q = static_cast(p);
@@ -111,7 +111,7 @@ struct D : N::B {
 #endif
 } // namespace cwg2857
 
-namespace cwg2858 { // cwg2858: 19 tentatively ready 2024-04-05
+namespace cwg2858 { // cwg2858: 19 ready 2024-04-05
 
 #if __cplusplus > 202302L
 
@@ -134,7 +134,7 @@ struct A {
 
 } // namespace cwg2858
 
-namespace cwg2877 { // cwg2877: 19 tentatively ready 2024-05-31
+namespace cwg2877 { // cwg2877: 19 ready 2024-05-31
 #if __cplusplus >= 202002L
 enum E { x };
 void f() {
@@ -150,7 +150,7 @@ void g() {
 #endif
 } // namespace cwg2877
 
-namespace cwg2881 { // cwg2881: 19 tentatively ready 2024-04-19
+namespace cwg2881 { // cwg2881: 19 ready 2024-04-19
 
 #if __cplusplus >= 202302L
 
@@ -220,7 +220,7 @@ void f() {
 
 } // namespace cwg2881
 
-namespace cwg2882 { // cwg2882: 2.7 tentatively ready 2024-05-31
+namespace cwg2882 { // cwg2882: 2.7 ready 2024-05-31
 struct C {
   operator void() = delete;
   // expected-warning@-1 {{conversion function converting 'cwg2882::C' to 
'void' will never be used}}
@@ -232,7 +232,7 @@ void f(C c) {
 }
 } // namespace cwg2882
 
-namespace cwg2883 { // cwg2883: no tentatively ready 2024-05-31
+namespace cwg2883 { // cwg2883: no ready 2024-05-31
 #if __cplusplus >= 201103L
 void f() {
   int x;
@@ -257,7 +257,7 @@ void g() {
 #endif
 } // namespace cwg2883
 
-namespace cwg2885 { // cwg2885: 16 tentatively ready 2024-05-31
+namespace cwg2885 { // cwg2885: 16 review 2024-05-31
 #if __cplusplus >= 202002L
 template 
 struct A {
@@ -271,7 +271,7 @@ static_assert(!__is_trivially_constructible(B));
 #endif
 } // namespace cwg2885
 
-namespace cwg2886 { // cwg2886: 9 tentatively ready 2024-05-31
+namespace cwg2886 { // cwg2886: 9 ready 2024-05-31
 #if __cplusplus >= 201103L
 struct C {
   C() = default;
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 937f67981e296..64b361976a5a5 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -1442,7 +1442,7 @@ C++ defect report implementation 
status
   
   
 https://cplusplus.github.io/CWG/issues/233.html";>233
-tentatively ready
+ready
 References vs pointers in UDC overload resolution
 Not resolved
   
@@ -7329,11 +7329,11 @@ C++ defect report implementation 
status
 Overloading member function templates based on dependent return 
type
 Unknown
   
-  
+  
 https://cplusplus.github.io/CWG/issues/1253.html";>1253
-open
+C++17
 Generic non-template members
-Not resolved
+Unknown
   
   
 https://cplusplus.github.io/CWG/issues/1254.html";>1254
@@ -12677,7 +12677,7 @@ C++ defect report implementation 
status
   
   
 https://cplusplus.github.io/CWG/issues/2144.html";>2144
-tentatively ready
+ready
 Function/variable declaration ambiguity
 Not resolved
   
@@ -15179,7 +15179,7 @@ C++ defect report implementation 
status
   
   
 https://cplusplus.github.io/CWG/issues/2561.html";>2561
-tentatively ready
+ready
 Conversion to function pointer for lambda with explicit object 
parameter
 Not Resolved*
   
@@ -15341,7 +15341,7 @@ C++ defect report implementation 
status
   
   
 https://cplusplus.github.io/CWG/issues/2588.html";>2588
-tentatively ready
+ready
 friend declarations and module linkage
 Not resolved
   
@@ -15541,7 +15541,7 @@ C++ defect report implementation 
status
 https://cplusplus.github.io/CWG/issues/2621.html";>26

[clang] [Clang] [C23] Implement N2653: u8 strings are char8_t[] (PR #97208)

2024-06-30 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok created 
https://github.com/llvm/llvm-project/pull/97208

https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2653.htm

Closes #97202


>From ef0072d1fc9b14f7ee657fa95f44a686b78b525a Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 30 Jun 2024 12:07:54 +0100
Subject: [PATCH] [Clang] [C23] Implement N2653: u8 strings are char8_t[]

---
 clang/docs/ReleaseNotes.rst   |  6 
 .../clang/Basic/DiagnosticSemaKinds.td|  5 +++-
 clang/lib/Frontend/InitPreprocessor.cpp   |  6 ++--
 clang/lib/Headers/stdatomic.h |  5 
 clang/lib/Sema/SemaExpr.cpp   | 23 ++-
 clang/test/C/C2x/n2653.c  | 29 +++
 clang/www/c_status.html   |  2 +-
 7 files changed, 65 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/C/C2x/n2653.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c720e47dbe35b..e51be81d8b11a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -337,6 +337,12 @@ C23 Feature Support
 - Properly promote bit-fields of bit-precise integer types to the field's type
   rather than to ``int``. #GH87641
 
+- Compiler support for `N2653 char8_t: A type for UTF-8 characters and strings`
+  `_: ``u8`` string
+  literals are now of type ``char8_t[N]`` in C23 and expose
+  ``__CLANG_ATOMIC_CHAR8_T_LOCK_FREE``/``__GCC_ATOMIC_CHAR8_T_LOCK_FREE`` to
+  implement the corresponding macro in .
+
 Non-comprehensive list of changes in this release
 -
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5dc36c594bcb7..6a00b92df1c36 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7252,7 +7252,10 @@ def err_array_init_utf8_string_into_char : Error<
 def warn_cxx20_compat_utf8_string : Warning<
   "type of UTF-8 string literal will change from array of const char to "
   "array of const char8_t in C++20">, InGroup, DefaultIgnore;
-def note_cxx20_compat_utf8_string_remove_u8 : Note<
+def warn_c23_compat_utf8_string : Warning<
+  "type of UTF-8 string literal will change from array of char to "
+  "array of char8_t in C23">, InGroup, DefaultIgnore;
+def note_cxx20_c23_compat_utf8_string_remove_u8 : Note<
   "remove 'u8' prefix to avoid a change of behavior; "
   "Clang encodes unprefixed narrow string literals as UTF-8">;
 def err_array_init_different_type : Error<
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp 
b/clang/lib/Frontend/InitPreprocessor.cpp
index 55ec460064830..6270c37342bcf 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -1342,8 +1342,10 @@ static void InitializePredefinedMacros(const TargetInfo 
&TI,
   getLockFreeValue(TI.get##Type##Width(), TI));
 DEFINE_LOCK_FREE_MACRO(BOOL, Bool);
 DEFINE_LOCK_FREE_MACRO(CHAR, Char);
-if (LangOpts.Char8)
-  DEFINE_LOCK_FREE_MACRO(CHAR8_T, Char); // Treat char8_t like char.
+// char8_t has the same representation / width as unsigned
+// char in C++ and is a typedef for unsigned char in C23
+if (LangOpts.Char8 || LangOpts.C23)
+  DEFINE_LOCK_FREE_MACRO(CHAR8_T, Char);
 DEFINE_LOCK_FREE_MACRO(CHAR16_T, Char16);
 DEFINE_LOCK_FREE_MACRO(CHAR32_T, Char32);
 DEFINE_LOCK_FREE_MACRO(WCHAR_T, WChar);
diff --git a/clang/lib/Headers/stdatomic.h b/clang/lib/Headers/stdatomic.h
index 9c103d98af8c5..c33cd8083525c 100644
--- a/clang/lib/Headers/stdatomic.h
+++ b/clang/lib/Headers/stdatomic.h
@@ -35,6 +35,10 @@ extern "C" {
 
 #define ATOMIC_BOOL_LOCK_FREE   __CLANG_ATOMIC_BOOL_LOCK_FREE
 #define ATOMIC_CHAR_LOCK_FREE   __CLANG_ATOMIC_CHAR_LOCK_FREE
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) ||  
\
+defined(__cplusplus)
+#define ATOMIC_CHAR8_T_LOCK_FREE__CLANG_ATOMIC_CHAR8_T_LOCK_FREE
+#endif
 #define ATOMIC_CHAR16_T_LOCK_FREE   __CLANG_ATOMIC_CHAR16_T_LOCK_FREE
 #define ATOMIC_CHAR32_T_LOCK_FREE   __CLANG_ATOMIC_CHAR32_T_LOCK_FREE
 #define ATOMIC_WCHAR_T_LOCK_FREE__CLANG_ATOMIC_WCHAR_T_LOCK_FREE
@@ -104,6 +108,7 @@ typedef _Atomic(long)   atomic_long;
 typedef _Atomic(unsigned long)  atomic_ulong;
 typedef _Atomic(long long)  atomic_llong;
 typedef _Atomic(unsigned long long) atomic_ullong;
+typedef _Atomic(unsigned char)  atomic_char8_t;
 typedef _Atomic(uint_least16_t) atomic_char16_t;
 typedef _Atomic(uint_least32_t) atomic_char32_t;
 typedef _Atomic(wchar_t)atomic_wchar_t;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index db44cfe1288b6..a1b060f7f1510 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2082,6 +2082,8 @@ Sema::ActOnStringLiteral(ArrayRef S

[clang] [Clang] [C23] Implement N2653: u8 strings are char8_t[] (PR #97208)

2024-06-30 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

CC @AaronBallman

Also the clang-format issues are intentional to fit the style of the 
surrounding lines

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


[clang] [Clang] Warn with -Wpre-c23-compat instead of -Wpre-c++17-compat for u8 character literals in C23 (PR #97210)

2024-06-30 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok created 
https://github.com/llvm/llvm-project/pull/97210

None

>From c6ee783243e1888074778e2cb6de05df41cc8333 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 30 Jun 2024 12:55:04 +0100
Subject: [PATCH] [Clang] Warn with -Wpre-c23-compat instead of
 -Wpre-c++17-compat for u8 character literals in C23

---
 clang/docs/ReleaseNotes.rst | 2 ++
 clang/include/clang/Basic/DiagnosticLexKinds.td | 3 +++
 clang/lib/Lex/Lexer.cpp | 4 +++-
 clang/test/Sema/pre-c2x-compat.c| 1 +
 4 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c720e47dbe35b..d2939ef7a875c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -627,6 +627,8 @@ Improvements to Clang's diagnostics
   used rather than when they are needed for constant evaluation or when code 
is generated for them.
   The check is now stricter to prevent crashes for some unsupported 
declarations (Fixes #GH95495).
 
+- Clang now warns for u8 character literals used in C23 with 
``-Wpre-c23-compat`` instead of ``-Wpre-c++17-compat``.
+
 Improvements to Clang's time-trace
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td 
b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 12d7b8c0205ee..fc14bb6aa2165 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -283,6 +283,9 @@ def warn_cxx98_compat_unicode_literal : Warning<
 def warn_cxx14_compat_u8_character_literal : Warning<
   "unicode literals are incompatible with C++ standards before C++17">,
   InGroup, DefaultIgnore;
+def warn_c17_compat_u8_character_literal : Warning<
+  "unicode literals are incompatible with C standards before C23">,
+  InGroup, DefaultIgnore;
 def warn_cxx11_compat_user_defined_literal : Warning<
   "identifier after literal will be treated as a user-defined literal suffix "
   "in C++11">, InGroup, DefaultIgnore;
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index e59c7805b3862..c61d81e93d990 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -2428,7 +2428,9 @@ bool Lexer::LexCharConstant(Token &Result, const char 
*CurPtr,
   ? diag::warn_cxx98_compat_unicode_literal
   : diag::warn_c99_compat_unicode_literal);
 else if (Kind == tok::utf8_char_constant)
-  Diag(BufferPtr, diag::warn_cxx14_compat_u8_character_literal);
+  Diag(BufferPtr, LangOpts.CPlusPlus
+  ? diag::warn_cxx14_compat_u8_character_literal
+  : diag::warn_c17_compat_u8_character_literal);
   }
 
   char C = getAndAdvanceChar(CurPtr, Result);
diff --git a/clang/test/Sema/pre-c2x-compat.c b/clang/test/Sema/pre-c2x-compat.c
index fad472f1f72d5..15bb9b58349fa 100644
--- a/clang/test/Sema/pre-c2x-compat.c
+++ b/clang/test/Sema/pre-c2x-compat.c
@@ -1,3 +1,4 @@
 // RUN: %clang_cc1 %s -std=c2x -Wpre-c2x-compat -pedantic -fsyntax-only -verify
 
 int digit_seps = 123'456; // expected-warning {{digit separators are 
incompatible with C standards before C23}}
+unsigned char u8_char = u8'x'; // expected-warning {{unicode literals are 
incompatible with C standards before C23}}

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [NFC] [Clang] Some core issues have changed status from tentatively ready -> ready / review (PR #97200)

2024-06-30 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/97200

>From 0dea95701ca4dfca9b7d0bd889003fc35aa3017e Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 30 Jun 2024 10:39:15 +0100
Subject: [PATCH 1/8] [NFC] [Clang] Some core issues have changed status from
 tentatively ready -> ready / review

---
 clang/test/CXX/drs/cwg25xx.cpp |   2 +-
 clang/test/CXX/drs/cwg28xx.cpp |  16 ++--
 clang/www/cxx_dr_status.html   | 130 +++--
 clang/www/make_cxx_dr_status   |   6 +-
 4 files changed, 104 insertions(+), 50 deletions(-)

diff --git a/clang/test/CXX/drs/cwg25xx.cpp b/clang/test/CXX/drs/cwg25xx.cpp
index 0934f0cc19c6a..5f8a058f8157a 100644
--- a/clang/test/CXX/drs/cwg25xx.cpp
+++ b/clang/test/CXX/drs/cwg25xx.cpp
@@ -139,7 +139,7 @@ struct D3 : B {
 #endif
 
 #if __cplusplus >= 202302L
-namespace cwg2561 { // cwg2561: no tentatively ready 2024-03-18
+namespace cwg2561 { // cwg2561: no ready 2024-03-18
 struct C {
 constexpr C(auto) { }
 };
diff --git a/clang/test/CXX/drs/cwg28xx.cpp b/clang/test/CXX/drs/cwg28xx.cpp
index c77bd433d8e21..524e67b52de51 100644
--- a/clang/test/CXX/drs/cwg28xx.cpp
+++ b/clang/test/CXX/drs/cwg28xx.cpp
@@ -30,7 +30,7 @@ using U2 = decltype(&main);
 #endif
 } // namespace cwg2811
 
-namespace cwg2819 { // cwg2819: 19 tentatively ready 2023-12-01
+namespace cwg2819 { // cwg2819: 19 ready 2023-12-01
 #if __cpp_constexpr >= 202306L
   constexpr void* p = nullptr;
   constexpr int* q = static_cast(p);
@@ -111,7 +111,7 @@ struct D : N::B {
 #endif
 } // namespace cwg2857
 
-namespace cwg2858 { // cwg2858: 19 tentatively ready 2024-04-05
+namespace cwg2858 { // cwg2858: 19 ready 2024-04-05
 
 #if __cplusplus > 202302L
 
@@ -134,7 +134,7 @@ struct A {
 
 } // namespace cwg2858
 
-namespace cwg2877 { // cwg2877: 19 tentatively ready 2024-05-31
+namespace cwg2877 { // cwg2877: 19 ready 2024-05-31
 #if __cplusplus >= 202002L
 enum E { x };
 void f() {
@@ -150,7 +150,7 @@ void g() {
 #endif
 } // namespace cwg2877
 
-namespace cwg2881 { // cwg2881: 19 tentatively ready 2024-04-19
+namespace cwg2881 { // cwg2881: 19 ready 2024-04-19
 
 #if __cplusplus >= 202302L
 
@@ -220,7 +220,7 @@ void f() {
 
 } // namespace cwg2881
 
-namespace cwg2882 { // cwg2882: 2.7 tentatively ready 2024-05-31
+namespace cwg2882 { // cwg2882: 2.7 ready 2024-05-31
 struct C {
   operator void() = delete;
   // expected-warning@-1 {{conversion function converting 'cwg2882::C' to 
'void' will never be used}}
@@ -232,7 +232,7 @@ void f(C c) {
 }
 } // namespace cwg2882
 
-namespace cwg2883 { // cwg2883: no tentatively ready 2024-05-31
+namespace cwg2883 { // cwg2883: no ready 2024-05-31
 #if __cplusplus >= 201103L
 void f() {
   int x;
@@ -257,7 +257,7 @@ void g() {
 #endif
 } // namespace cwg2883
 
-namespace cwg2885 { // cwg2885: 16 tentatively ready 2024-05-31
+namespace cwg2885 { // cwg2885: 16 review 2024-05-31
 #if __cplusplus >= 202002L
 template 
 struct A {
@@ -271,7 +271,7 @@ static_assert(!__is_trivially_constructible(B));
 #endif
 } // namespace cwg2885
 
-namespace cwg2886 { // cwg2886: 9 tentatively ready 2024-05-31
+namespace cwg2886 { // cwg2886: 9 ready 2024-05-31
 #if __cplusplus >= 201103L
 struct C {
   C() = default;
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 937f67981e296..64b361976a5a5 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -1442,7 +1442,7 @@ C++ defect report implementation 
status
   
   
 https://cplusplus.github.io/CWG/issues/233.html";>233
-tentatively ready
+ready
 References vs pointers in UDC overload resolution
 Not resolved
   
@@ -7329,11 +7329,11 @@ C++ defect report implementation 
status
 Overloading member function templates based on dependent return 
type
 Unknown
   
-  
+  
 https://cplusplus.github.io/CWG/issues/1253.html";>1253
-open
+C++17
 Generic non-template members
-Not resolved
+Unknown
   
   
 https://cplusplus.github.io/CWG/issues/1254.html";>1254
@@ -12677,7 +12677,7 @@ C++ defect report implementation 
status
   
   
 https://cplusplus.github.io/CWG/issues/2144.html";>2144
-tentatively ready
+ready
 Function/variable declaration ambiguity
 Not resolved
   
@@ -15179,7 +15179,7 @@ C++ defect report implementation 
status
   
   
 https://cplusplus.github.io/CWG/issues/2561.html";>2561
-tentatively ready
+ready
 Conversion to function pointer for lambda with explicit object 
parameter
 Not Resolved*
   
@@ -15341,7 +15341,7 @@ C++ defect report implementation 
status
   
   
 https://cplusplus.github.io/CWG/issues/2588.html";>2588
-tentatively ready
+ready
 friend declarations and module linkage
 Not resolved
   
@@ -15541,7 +15541,7 @@ C++ defect report implementation 
status
 https://cplusplus.github.io/CWG/issues/2621.html";>2621
 C++23
 Kind of lookup for using enum declarations
-Superseded by 2877

[clang] [NFC] [Clang] Some core issues have changed status from tentatively ready -> ready / review (PR #97200)

2024-06-30 Thread Mital Ashok via cfe-commits


@@ -111,7 +111,7 @@ struct D : N::B {
 #endif
 } // namespace cwg2857
 
-namespace cwg2858 { // cwg2858: 19 tentatively ready 2024-04-05
+namespace cwg2858 { // cwg2858: 19 ready 2024-04-05

MitalAshok wrote:

The date of the proposed resolution did not change for this one: 
https://cplusplus.github.io/CWG/issues/2858.html

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


[clang] [NFC] [Clang] Some core issues have changed status from tentatively ready -> ready / review (PR #97200)

2024-06-30 Thread Mital Ashok via cfe-commits

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


[clang] [NFC] [Clang] Some core issues have changed status from tentatively ready -> ready / review (PR #97200)

2024-06-30 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/97200

>From 0dea95701ca4dfca9b7d0bd889003fc35aa3017e Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 30 Jun 2024 10:39:15 +0100
Subject: [PATCH 1/9] [NFC] [Clang] Some core issues have changed status from
 tentatively ready -> ready / review

---
 clang/test/CXX/drs/cwg25xx.cpp |   2 +-
 clang/test/CXX/drs/cwg28xx.cpp |  16 ++--
 clang/www/cxx_dr_status.html   | 130 +++--
 clang/www/make_cxx_dr_status   |   6 +-
 4 files changed, 104 insertions(+), 50 deletions(-)

diff --git a/clang/test/CXX/drs/cwg25xx.cpp b/clang/test/CXX/drs/cwg25xx.cpp
index 0934f0cc19c6a..5f8a058f8157a 100644
--- a/clang/test/CXX/drs/cwg25xx.cpp
+++ b/clang/test/CXX/drs/cwg25xx.cpp
@@ -139,7 +139,7 @@ struct D3 : B {
 #endif
 
 #if __cplusplus >= 202302L
-namespace cwg2561 { // cwg2561: no tentatively ready 2024-03-18
+namespace cwg2561 { // cwg2561: no ready 2024-03-18
 struct C {
 constexpr C(auto) { }
 };
diff --git a/clang/test/CXX/drs/cwg28xx.cpp b/clang/test/CXX/drs/cwg28xx.cpp
index c77bd433d8e21..524e67b52de51 100644
--- a/clang/test/CXX/drs/cwg28xx.cpp
+++ b/clang/test/CXX/drs/cwg28xx.cpp
@@ -30,7 +30,7 @@ using U2 = decltype(&main);
 #endif
 } // namespace cwg2811
 
-namespace cwg2819 { // cwg2819: 19 tentatively ready 2023-12-01
+namespace cwg2819 { // cwg2819: 19 ready 2023-12-01
 #if __cpp_constexpr >= 202306L
   constexpr void* p = nullptr;
   constexpr int* q = static_cast(p);
@@ -111,7 +111,7 @@ struct D : N::B {
 #endif
 } // namespace cwg2857
 
-namespace cwg2858 { // cwg2858: 19 tentatively ready 2024-04-05
+namespace cwg2858 { // cwg2858: 19 ready 2024-04-05
 
 #if __cplusplus > 202302L
 
@@ -134,7 +134,7 @@ struct A {
 
 } // namespace cwg2858
 
-namespace cwg2877 { // cwg2877: 19 tentatively ready 2024-05-31
+namespace cwg2877 { // cwg2877: 19 ready 2024-05-31
 #if __cplusplus >= 202002L
 enum E { x };
 void f() {
@@ -150,7 +150,7 @@ void g() {
 #endif
 } // namespace cwg2877
 
-namespace cwg2881 { // cwg2881: 19 tentatively ready 2024-04-19
+namespace cwg2881 { // cwg2881: 19 ready 2024-04-19
 
 #if __cplusplus >= 202302L
 
@@ -220,7 +220,7 @@ void f() {
 
 } // namespace cwg2881
 
-namespace cwg2882 { // cwg2882: 2.7 tentatively ready 2024-05-31
+namespace cwg2882 { // cwg2882: 2.7 ready 2024-05-31
 struct C {
   operator void() = delete;
   // expected-warning@-1 {{conversion function converting 'cwg2882::C' to 
'void' will never be used}}
@@ -232,7 +232,7 @@ void f(C c) {
 }
 } // namespace cwg2882
 
-namespace cwg2883 { // cwg2883: no tentatively ready 2024-05-31
+namespace cwg2883 { // cwg2883: no ready 2024-05-31
 #if __cplusplus >= 201103L
 void f() {
   int x;
@@ -257,7 +257,7 @@ void g() {
 #endif
 } // namespace cwg2883
 
-namespace cwg2885 { // cwg2885: 16 tentatively ready 2024-05-31
+namespace cwg2885 { // cwg2885: 16 review 2024-05-31
 #if __cplusplus >= 202002L
 template 
 struct A {
@@ -271,7 +271,7 @@ static_assert(!__is_trivially_constructible(B));
 #endif
 } // namespace cwg2885
 
-namespace cwg2886 { // cwg2886: 9 tentatively ready 2024-05-31
+namespace cwg2886 { // cwg2886: 9 ready 2024-05-31
 #if __cplusplus >= 201103L
 struct C {
   C() = default;
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 937f67981e296..64b361976a5a5 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -1442,7 +1442,7 @@ C++ defect report implementation 
status
   
   
 https://cplusplus.github.io/CWG/issues/233.html";>233
-tentatively ready
+ready
 References vs pointers in UDC overload resolution
 Not resolved
   
@@ -7329,11 +7329,11 @@ C++ defect report implementation 
status
 Overloading member function templates based on dependent return 
type
 Unknown
   
-  
+  
 https://cplusplus.github.io/CWG/issues/1253.html";>1253
-open
+C++17
 Generic non-template members
-Not resolved
+Unknown
   
   
 https://cplusplus.github.io/CWG/issues/1254.html";>1254
@@ -12677,7 +12677,7 @@ C++ defect report implementation 
status
   
   
 https://cplusplus.github.io/CWG/issues/2144.html";>2144
-tentatively ready
+ready
 Function/variable declaration ambiguity
 Not resolved
   
@@ -15179,7 +15179,7 @@ C++ defect report implementation 
status
   
   
 https://cplusplus.github.io/CWG/issues/2561.html";>2561
-tentatively ready
+ready
 Conversion to function pointer for lambda with explicit object 
parameter
 Not Resolved*
   
@@ -15341,7 +15341,7 @@ C++ defect report implementation 
status
   
   
 https://cplusplus.github.io/CWG/issues/2588.html";>2588
-tentatively ready
+ready
 friend declarations and module linkage
 Not resolved
   
@@ -15541,7 +15541,7 @@ C++ defect report implementation 
status
 https://cplusplus.github.io/CWG/issues/2621.html";>2621
 C++23
 Kind of lookup for using enum declarations
-Superseded by 2877

[clang] [Clang] [C23] Implement N2653: u8 strings are char8_t[] (PR #97208)

2024-07-01 Thread Mital Ashok via cfe-commits


@@ -1342,8 +1342,10 @@ static void InitializePredefinedMacros(const TargetInfo 
&TI,
   getLockFreeValue(TI.get##Type##Width(), TI));
 DEFINE_LOCK_FREE_MACRO(BOOL, Bool);
 DEFINE_LOCK_FREE_MACRO(CHAR, Char);
-if (LangOpts.Char8)
-  DEFINE_LOCK_FREE_MACRO(CHAR8_T, Char); // Treat char8_t like char.
+// char8_t has the same representation / width as unsigned
+// char in C++ and is a typedef for unsigned char in C23
+if (LangOpts.Char8 || LangOpts.C23)

MitalAshok wrote:

Looks like that also controls if `char8_t` is a keyword/builtin type, which it 
isn't in C23. (`LangOpts.Char8` is also false in C++20 with `-fno-char8_t`)

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


[clang] [Clang] [C23] Implement N2653: u8 strings are char8_t[] (PR #97208)

2024-07-01 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/97208

>From ef0072d1fc9b14f7ee657fa95f44a686b78b525a Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 30 Jun 2024 12:07:54 +0100
Subject: [PATCH 1/3] [Clang] [C23] Implement N2653: u8 strings are char8_t[]

---
 clang/docs/ReleaseNotes.rst   |  6 
 .../clang/Basic/DiagnosticSemaKinds.td|  5 +++-
 clang/lib/Frontend/InitPreprocessor.cpp   |  6 ++--
 clang/lib/Headers/stdatomic.h |  5 
 clang/lib/Sema/SemaExpr.cpp   | 23 ++-
 clang/test/C/C2x/n2653.c  | 29 +++
 clang/www/c_status.html   |  2 +-
 7 files changed, 65 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/C/C2x/n2653.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c720e47dbe35b..e51be81d8b11a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -337,6 +337,12 @@ C23 Feature Support
 - Properly promote bit-fields of bit-precise integer types to the field's type
   rather than to ``int``. #GH87641
 
+- Compiler support for `N2653 char8_t: A type for UTF-8 characters and strings`
+  `_: ``u8`` string
+  literals are now of type ``char8_t[N]`` in C23 and expose
+  ``__CLANG_ATOMIC_CHAR8_T_LOCK_FREE``/``__GCC_ATOMIC_CHAR8_T_LOCK_FREE`` to
+  implement the corresponding macro in .
+
 Non-comprehensive list of changes in this release
 -
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5dc36c594bcb7..6a00b92df1c36 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7252,7 +7252,10 @@ def err_array_init_utf8_string_into_char : Error<
 def warn_cxx20_compat_utf8_string : Warning<
   "type of UTF-8 string literal will change from array of const char to "
   "array of const char8_t in C++20">, InGroup, DefaultIgnore;
-def note_cxx20_compat_utf8_string_remove_u8 : Note<
+def warn_c23_compat_utf8_string : Warning<
+  "type of UTF-8 string literal will change from array of char to "
+  "array of char8_t in C23">, InGroup, DefaultIgnore;
+def note_cxx20_c23_compat_utf8_string_remove_u8 : Note<
   "remove 'u8' prefix to avoid a change of behavior; "
   "Clang encodes unprefixed narrow string literals as UTF-8">;
 def err_array_init_different_type : Error<
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp 
b/clang/lib/Frontend/InitPreprocessor.cpp
index 55ec460064830..6270c37342bcf 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -1342,8 +1342,10 @@ static void InitializePredefinedMacros(const TargetInfo 
&TI,
   getLockFreeValue(TI.get##Type##Width(), TI));
 DEFINE_LOCK_FREE_MACRO(BOOL, Bool);
 DEFINE_LOCK_FREE_MACRO(CHAR, Char);
-if (LangOpts.Char8)
-  DEFINE_LOCK_FREE_MACRO(CHAR8_T, Char); // Treat char8_t like char.
+// char8_t has the same representation / width as unsigned
+// char in C++ and is a typedef for unsigned char in C23
+if (LangOpts.Char8 || LangOpts.C23)
+  DEFINE_LOCK_FREE_MACRO(CHAR8_T, Char);
 DEFINE_LOCK_FREE_MACRO(CHAR16_T, Char16);
 DEFINE_LOCK_FREE_MACRO(CHAR32_T, Char32);
 DEFINE_LOCK_FREE_MACRO(WCHAR_T, WChar);
diff --git a/clang/lib/Headers/stdatomic.h b/clang/lib/Headers/stdatomic.h
index 9c103d98af8c5..c33cd8083525c 100644
--- a/clang/lib/Headers/stdatomic.h
+++ b/clang/lib/Headers/stdatomic.h
@@ -35,6 +35,10 @@ extern "C" {
 
 #define ATOMIC_BOOL_LOCK_FREE   __CLANG_ATOMIC_BOOL_LOCK_FREE
 #define ATOMIC_CHAR_LOCK_FREE   __CLANG_ATOMIC_CHAR_LOCK_FREE
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) ||  
\
+defined(__cplusplus)
+#define ATOMIC_CHAR8_T_LOCK_FREE__CLANG_ATOMIC_CHAR8_T_LOCK_FREE
+#endif
 #define ATOMIC_CHAR16_T_LOCK_FREE   __CLANG_ATOMIC_CHAR16_T_LOCK_FREE
 #define ATOMIC_CHAR32_T_LOCK_FREE   __CLANG_ATOMIC_CHAR32_T_LOCK_FREE
 #define ATOMIC_WCHAR_T_LOCK_FREE__CLANG_ATOMIC_WCHAR_T_LOCK_FREE
@@ -104,6 +108,7 @@ typedef _Atomic(long)   atomic_long;
 typedef _Atomic(unsigned long)  atomic_ulong;
 typedef _Atomic(long long)  atomic_llong;
 typedef _Atomic(unsigned long long) atomic_ullong;
+typedef _Atomic(unsigned char)  atomic_char8_t;
 typedef _Atomic(uint_least16_t) atomic_char16_t;
 typedef _Atomic(uint_least32_t) atomic_char32_t;
 typedef _Atomic(wchar_t)atomic_wchar_t;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index db44cfe1288b6..a1b060f7f1510 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2082,6 +2082,8 @@ Sema::ActOnStringLiteral(ArrayRef StringToks, 
Scope *UDLScope) {
   } else if (Literal.isUTF8()) {
 if

[clang] [Clang] [C23] Implement N2653: u8 strings are char8_t[] (PR #97208)

2024-07-01 Thread Mital Ashok via cfe-commits


@@ -104,6 +107,7 @@ typedef _Atomic(long)   atomic_long;
 typedef _Atomic(unsigned long)  atomic_ulong;
 typedef _Atomic(long long)  atomic_llong;
 typedef _Atomic(unsigned long long) atomic_ullong;
+typedef _Atomic(unsigned char)  atomic_char8_t;
 typedef _Atomic(uint_least16_t) atomic_char16_t;
 typedef _Atomic(uint_least32_t) atomic_char32_t;

MitalAshok wrote:

Should the definition of `atomic_char8_t` also be gated behind C23/C++20?

Also in C++20, this should be `_Atomic(char8_t)`, but the next two are also 
wrong in C++11 (`_Atomic(char16_t)`/`_Atomic(char32_t)`)

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


[clang] [NFC] [Clang] Some core issues have changed status from tentatively ready -> ready / review (PR #97200)

2024-07-01 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/97200

>From 0dea95701ca4dfca9b7d0bd889003fc35aa3017e Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 30 Jun 2024 10:39:15 +0100
Subject: [PATCH 01/10] [NFC] [Clang] Some core issues have changed status from
 tentatively ready -> ready / review

---
 clang/test/CXX/drs/cwg25xx.cpp |   2 +-
 clang/test/CXX/drs/cwg28xx.cpp |  16 ++--
 clang/www/cxx_dr_status.html   | 130 +++--
 clang/www/make_cxx_dr_status   |   6 +-
 4 files changed, 104 insertions(+), 50 deletions(-)

diff --git a/clang/test/CXX/drs/cwg25xx.cpp b/clang/test/CXX/drs/cwg25xx.cpp
index 0934f0cc19c6a..5f8a058f8157a 100644
--- a/clang/test/CXX/drs/cwg25xx.cpp
+++ b/clang/test/CXX/drs/cwg25xx.cpp
@@ -139,7 +139,7 @@ struct D3 : B {
 #endif
 
 #if __cplusplus >= 202302L
-namespace cwg2561 { // cwg2561: no tentatively ready 2024-03-18
+namespace cwg2561 { // cwg2561: no ready 2024-03-18
 struct C {
 constexpr C(auto) { }
 };
diff --git a/clang/test/CXX/drs/cwg28xx.cpp b/clang/test/CXX/drs/cwg28xx.cpp
index c77bd433d8e21..524e67b52de51 100644
--- a/clang/test/CXX/drs/cwg28xx.cpp
+++ b/clang/test/CXX/drs/cwg28xx.cpp
@@ -30,7 +30,7 @@ using U2 = decltype(&main);
 #endif
 } // namespace cwg2811
 
-namespace cwg2819 { // cwg2819: 19 tentatively ready 2023-12-01
+namespace cwg2819 { // cwg2819: 19 ready 2023-12-01
 #if __cpp_constexpr >= 202306L
   constexpr void* p = nullptr;
   constexpr int* q = static_cast(p);
@@ -111,7 +111,7 @@ struct D : N::B {
 #endif
 } // namespace cwg2857
 
-namespace cwg2858 { // cwg2858: 19 tentatively ready 2024-04-05
+namespace cwg2858 { // cwg2858: 19 ready 2024-04-05
 
 #if __cplusplus > 202302L
 
@@ -134,7 +134,7 @@ struct A {
 
 } // namespace cwg2858
 
-namespace cwg2877 { // cwg2877: 19 tentatively ready 2024-05-31
+namespace cwg2877 { // cwg2877: 19 ready 2024-05-31
 #if __cplusplus >= 202002L
 enum E { x };
 void f() {
@@ -150,7 +150,7 @@ void g() {
 #endif
 } // namespace cwg2877
 
-namespace cwg2881 { // cwg2881: 19 tentatively ready 2024-04-19
+namespace cwg2881 { // cwg2881: 19 ready 2024-04-19
 
 #if __cplusplus >= 202302L
 
@@ -220,7 +220,7 @@ void f() {
 
 } // namespace cwg2881
 
-namespace cwg2882 { // cwg2882: 2.7 tentatively ready 2024-05-31
+namespace cwg2882 { // cwg2882: 2.7 ready 2024-05-31
 struct C {
   operator void() = delete;
   // expected-warning@-1 {{conversion function converting 'cwg2882::C' to 
'void' will never be used}}
@@ -232,7 +232,7 @@ void f(C c) {
 }
 } // namespace cwg2882
 
-namespace cwg2883 { // cwg2883: no tentatively ready 2024-05-31
+namespace cwg2883 { // cwg2883: no ready 2024-05-31
 #if __cplusplus >= 201103L
 void f() {
   int x;
@@ -257,7 +257,7 @@ void g() {
 #endif
 } // namespace cwg2883
 
-namespace cwg2885 { // cwg2885: 16 tentatively ready 2024-05-31
+namespace cwg2885 { // cwg2885: 16 review 2024-05-31
 #if __cplusplus >= 202002L
 template 
 struct A {
@@ -271,7 +271,7 @@ static_assert(!__is_trivially_constructible(B));
 #endif
 } // namespace cwg2885
 
-namespace cwg2886 { // cwg2886: 9 tentatively ready 2024-05-31
+namespace cwg2886 { // cwg2886: 9 ready 2024-05-31
 #if __cplusplus >= 201103L
 struct C {
   C() = default;
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 937f67981e296..64b361976a5a5 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -1442,7 +1442,7 @@ C++ defect report implementation 
status
   
   
 https://cplusplus.github.io/CWG/issues/233.html";>233
-tentatively ready
+ready
 References vs pointers in UDC overload resolution
 Not resolved
   
@@ -7329,11 +7329,11 @@ C++ defect report implementation 
status
 Overloading member function templates based on dependent return 
type
 Unknown
   
-  
+  
 https://cplusplus.github.io/CWG/issues/1253.html";>1253
-open
+C++17
 Generic non-template members
-Not resolved
+Unknown
   
   
 https://cplusplus.github.io/CWG/issues/1254.html";>1254
@@ -12677,7 +12677,7 @@ C++ defect report implementation 
status
   
   
 https://cplusplus.github.io/CWG/issues/2144.html";>2144
-tentatively ready
+ready
 Function/variable declaration ambiguity
 Not resolved
   
@@ -15179,7 +15179,7 @@ C++ defect report implementation 
status
   
   
 https://cplusplus.github.io/CWG/issues/2561.html";>2561
-tentatively ready
+ready
 Conversion to function pointer for lambda with explicit object 
parameter
 Not Resolved*
   
@@ -15341,7 +15341,7 @@ C++ defect report implementation 
status
   
   
 https://cplusplus.github.io/CWG/issues/2588.html";>2588
-tentatively ready
+ready
 friend declarations and module linkage
 Not resolved
   
@@ -15541,7 +15541,7 @@ C++ defect report implementation 
status
 https://cplusplus.github.io/CWG/issues/2621.html";>2621
 C++23
 Kind of lookup for using enum declarations
-Superseded by 287

[clang] [libcxx] [Clang] Implement CWG2137 (list-initialization from objects of the same type) (PR #94355)

2024-07-02 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

I'm waiting to rebase on #97403 to remove the libc++ component of this now

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


[clang] [Clang] Implement CWG2351 `void{}` (PR #78060)

2024-07-02 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

Is there anything else that needs to be done for this? Also, thanks for all the 
reviews and help on this!

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


[clang] [Clang] [C23] Implement N2653: u8 strings are char8_t[] (PR #97208)

2024-07-03 Thread Mital Ashok via cfe-commits


@@ -104,6 +107,7 @@ typedef _Atomic(long)   atomic_long;
 typedef _Atomic(unsigned long)  atomic_ulong;
 typedef _Atomic(long long)  atomic_llong;
 typedef _Atomic(unsigned long long) atomic_ullong;
+typedef _Atomic(unsigned char)  atomic_char8_t;
 typedef _Atomic(uint_least16_t) atomic_char16_t;
 typedef _Atomic(uint_least32_t) atomic_char32_t;

MitalAshok wrote:

It seems like this header doesn't properly implement 
[P0943R6](https://wg21.link/P0943R6) in C++23 (Where `#define _Atomic(T) 
std::atomic` and all these typedefs should just be `using std::atomic_*`.

So `::atomic_char8_t` should be `std::atomic`, not 
`std::atomic` (nor `unsigned char _Atomic`), but that is outside 
the scope of this PR. I'll just make this match the surrounding typedefs for 
now.

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


[clang] [Clang] [C23] Implement N2653: u8 strings are char8_t[] (PR #97208)

2024-07-03 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/97208

>From ef0072d1fc9b14f7ee657fa95f44a686b78b525a Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 30 Jun 2024 12:07:54 +0100
Subject: [PATCH 1/5] [Clang] [C23] Implement N2653: u8 strings are char8_t[]

---
 clang/docs/ReleaseNotes.rst   |  6 
 .../clang/Basic/DiagnosticSemaKinds.td|  5 +++-
 clang/lib/Frontend/InitPreprocessor.cpp   |  6 ++--
 clang/lib/Headers/stdatomic.h |  5 
 clang/lib/Sema/SemaExpr.cpp   | 23 ++-
 clang/test/C/C2x/n2653.c  | 29 +++
 clang/www/c_status.html   |  2 +-
 7 files changed, 65 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/C/C2x/n2653.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c720e47dbe35b..e51be81d8b11a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -337,6 +337,12 @@ C23 Feature Support
 - Properly promote bit-fields of bit-precise integer types to the field's type
   rather than to ``int``. #GH87641
 
+- Compiler support for `N2653 char8_t: A type for UTF-8 characters and strings`
+  `_: ``u8`` string
+  literals are now of type ``char8_t[N]`` in C23 and expose
+  ``__CLANG_ATOMIC_CHAR8_T_LOCK_FREE``/``__GCC_ATOMIC_CHAR8_T_LOCK_FREE`` to
+  implement the corresponding macro in .
+
 Non-comprehensive list of changes in this release
 -
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5dc36c594bcb7..6a00b92df1c36 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7252,7 +7252,10 @@ def err_array_init_utf8_string_into_char : Error<
 def warn_cxx20_compat_utf8_string : Warning<
   "type of UTF-8 string literal will change from array of const char to "
   "array of const char8_t in C++20">, InGroup, DefaultIgnore;
-def note_cxx20_compat_utf8_string_remove_u8 : Note<
+def warn_c23_compat_utf8_string : Warning<
+  "type of UTF-8 string literal will change from array of char to "
+  "array of char8_t in C23">, InGroup, DefaultIgnore;
+def note_cxx20_c23_compat_utf8_string_remove_u8 : Note<
   "remove 'u8' prefix to avoid a change of behavior; "
   "Clang encodes unprefixed narrow string literals as UTF-8">;
 def err_array_init_different_type : Error<
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp 
b/clang/lib/Frontend/InitPreprocessor.cpp
index 55ec460064830..6270c37342bcf 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -1342,8 +1342,10 @@ static void InitializePredefinedMacros(const TargetInfo 
&TI,
   getLockFreeValue(TI.get##Type##Width(), TI));
 DEFINE_LOCK_FREE_MACRO(BOOL, Bool);
 DEFINE_LOCK_FREE_MACRO(CHAR, Char);
-if (LangOpts.Char8)
-  DEFINE_LOCK_FREE_MACRO(CHAR8_T, Char); // Treat char8_t like char.
+// char8_t has the same representation / width as unsigned
+// char in C++ and is a typedef for unsigned char in C23
+if (LangOpts.Char8 || LangOpts.C23)
+  DEFINE_LOCK_FREE_MACRO(CHAR8_T, Char);
 DEFINE_LOCK_FREE_MACRO(CHAR16_T, Char16);
 DEFINE_LOCK_FREE_MACRO(CHAR32_T, Char32);
 DEFINE_LOCK_FREE_MACRO(WCHAR_T, WChar);
diff --git a/clang/lib/Headers/stdatomic.h b/clang/lib/Headers/stdatomic.h
index 9c103d98af8c5..c33cd8083525c 100644
--- a/clang/lib/Headers/stdatomic.h
+++ b/clang/lib/Headers/stdatomic.h
@@ -35,6 +35,10 @@ extern "C" {
 
 #define ATOMIC_BOOL_LOCK_FREE   __CLANG_ATOMIC_BOOL_LOCK_FREE
 #define ATOMIC_CHAR_LOCK_FREE   __CLANG_ATOMIC_CHAR_LOCK_FREE
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) ||  
\
+defined(__cplusplus)
+#define ATOMIC_CHAR8_T_LOCK_FREE__CLANG_ATOMIC_CHAR8_T_LOCK_FREE
+#endif
 #define ATOMIC_CHAR16_T_LOCK_FREE   __CLANG_ATOMIC_CHAR16_T_LOCK_FREE
 #define ATOMIC_CHAR32_T_LOCK_FREE   __CLANG_ATOMIC_CHAR32_T_LOCK_FREE
 #define ATOMIC_WCHAR_T_LOCK_FREE__CLANG_ATOMIC_WCHAR_T_LOCK_FREE
@@ -104,6 +108,7 @@ typedef _Atomic(long)   atomic_long;
 typedef _Atomic(unsigned long)  atomic_ulong;
 typedef _Atomic(long long)  atomic_llong;
 typedef _Atomic(unsigned long long) atomic_ullong;
+typedef _Atomic(unsigned char)  atomic_char8_t;
 typedef _Atomic(uint_least16_t) atomic_char16_t;
 typedef _Atomic(uint_least32_t) atomic_char32_t;
 typedef _Atomic(wchar_t)atomic_wchar_t;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index db44cfe1288b6..a1b060f7f1510 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2082,6 +2082,8 @@ Sema::ActOnStringLiteral(ArrayRef StringToks, 
Scope *UDLScope) {
   } else if (Literal.isUTF8()) {
 if

[clang] [Clang] [C23] Implement N2653: u8 strings are char8_t[] (PR #97208)

2024-07-03 Thread Mital Ashok via cfe-commits


@@ -1165,6 +1165,8 @@ static void InitializePredefinedMacros(const TargetInfo 
&TI,
   DefineType("__WCHAR_TYPE__", TI.getWCharType(), Builder);
   DefineType("__WINT_TYPE__", TI.getWIntType(), Builder);
   DefineTypeSizeAndWidth("__SIG_ATOMIC", TI.getSigAtomicType(), TI, Builder);
+  if (LangOpts.Char8 || LangOpts.C23)
+DefineType("__CHAR8_TYPE__", TI.UnsignedChar, Builder);

MitalAshok wrote:

This matches GCC behaviour: https://godbolt.org/z/6Eax3eqrd

But I'm not sure why it's defined in C++ at all

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


[clang] [Clang] Warn on backslash-newline-EOF (PR #97585)

2024-07-03 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok created 
https://github.com/llvm/llvm-project/pull/97585

C99 §5.1.1.2p2, C23 §5.1.1.2p2

> A source file that is not empty shall end in a new-line character, which 
> shall not be immediately preceded by a backslash character before any such 
> splicing takes place.

Also adds tests for C++ DRs 
[CWG1698](https://cplusplus.github.io/CWG/issues/1698.html) and 
[CWG2747](https://cplusplus.github.io/CWG/issues/2747.html) related to line 
splices near the end of a source file.


>From 8af656659b79d76c971b01f1f4c14dc7315565b8 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Fri, 21 Jun 2024 18:55:38 +0100
Subject: [PATCH] [Clang] Warn on backslash-newline-EOF

---
 clang/docs/ReleaseNotes.rst   |  2 +
 .../include/clang/Basic/DiagnosticLexKinds.td |  1 +
 clang/lib/Lex/Lexer.cpp   | 39 +--
 clang/test/CXX/drs/cwg16xx.cpp|  9 +
 clang/test/CXX/drs/cwg2747.cpp| 11 ++
 clang/test/CXX/drs/cwg27xx.cpp|  2 +
 .../test/Preprocessor/backslash_newline_eof.c | 12 ++
 .../Preprocessor/backslash_without_newline.c  |  8 
 .../Preprocessor/backslash_without_newline.h  |  4 ++
 clang/www/cxx_dr_status.html  |  4 +-
 10 files changed, 87 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/CXX/drs/cwg2747.cpp
 create mode 100644 clang/test/Preprocessor/backslash_newline_eof.c
 create mode 100644 clang/test/Preprocessor/backslash_without_newline.c
 create mode 100644 clang/test/Preprocessor/backslash_without_newline.h

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f40fd1cd145bb..7c0ac3a504f98 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -647,6 +647,8 @@ Improvements to Clang's diagnostics
 
 - Clang now shows implicit deduction guides when diagnosing overload 
resolution failure. #GH92393.
 
+- Clang now emits ``-Wnewline-eof`` when the last newline is deleted by a 
preceding backslash.
+
 Improvements to Clang's time-trace
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td 
b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 12d7b8c0205ee..e6b2c1385944c 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -56,6 +56,7 @@ def ext_no_newline_eof : Extension<"no newline at end of 
file">,
   InGroup;
 def warn_no_newline_eof : Warning<"no newline at end of file">,
   InGroup, DefaultIgnore;
+def note_backslash_newline_eof : Note<"last newline deleted by splice here">;
 
 def warn_cxx98_compat_no_newline_eof : Warning<
   "C++98 requires newline at end of file">,
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index e59c7805b3862..0e540834b473b 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -3165,7 +3165,17 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
 
   // C99 5.1.1.2p2: If the file is non-empty and didn't end in a newline, issue
   // a pedwarn.
-  if (CurPtr != BufferStart && (CurPtr[-1] != '\n' && CurPtr[-1] != '\r')) {
+  if (CurPtr != BufferStart) {
+StringRef LastNewline;
+if (CurPtr[-1] == '\r' || CurPtr[-1] == '\n') {
+  LastNewline = StringRef(CurPtr - 1, 1);
+  if (CurPtr - 1 != BufferStart && CurPtr[-2] != CurPtr[-1] &&
+  (CurPtr[-2] == '\r' || CurPtr[-2] == '\n')) {
+// \r\n or \n\r is one newline
+LastNewline = StringRef(CurPtr - 2, 2);
+  }
+}
+
 DiagnosticsEngine &Diags = PP->getDiagnostics();
 SourceLocation EndLoc = getSourceLocation(BufferEnd);
 unsigned DiagID;
@@ -3183,8 +3193,31 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
   DiagID = diag::ext_no_newline_eof;
 }
 
-Diag(BufferEnd, DiagID)
-  << FixItHint::CreateInsertion(EndLoc, "\n");
+if (LastNewline.empty()) {
+  Diag(BufferEnd, DiagID) << FixItHint::CreateInsertion(EndLoc, "\n");
+} else {
+  // While the file physically ends in a newline, the previous
+  // line might have ended in a splice, so it would be deleted
+  const char *LastSpliceLocation = LastNewline.data();
+  while (LastSpliceLocation != BufferStart &&
+ isHorizontalWhitespace(*--LastSpliceLocation))
+;
+
+  bool LastIsSplice = *LastSpliceLocation == '\\';
+  if (*LastSpliceLocation == '/' && LangOpts.Trigraphs)
+// Check for "??/" trigraph for "\"
+LastIsSplice =
+LastSpliceLocation != BufferStart && *--LastSpliceLocation == '?' 
&&
+LastSpliceLocation != BufferStart && *--LastSpliceLocation == '?';
+
+  if (LastIsSplice) {
+PP->Diag(getSourceLocation(LastNewline.data(), LastNewline.size()),
+ DiagID);
+Diag(LastSpliceLocation, diag::note_backslash_newline_eof)
+<< FixItHint::CreateRemoval(getSourceLocation(
+   LastSpliceLocation

[clang] [Clang] [C23] Implement N2653: u8 strings are char8_t[] (PR #97208)

2024-07-03 Thread Mital Ashok via cfe-commits


@@ -1165,6 +1165,8 @@ static void InitializePredefinedMacros(const TargetInfo 
&TI,
   DefineType("__WCHAR_TYPE__", TI.getWCharType(), Builder);
   DefineType("__WINT_TYPE__", TI.getWIntType(), Builder);
   DefineTypeSizeAndWidth("__SIG_ATOMIC", TI.getSigAtomicType(), TI, Builder);
+  if (LangOpts.Char8 || LangOpts.C23)
+DefineType("__CHAR8_TYPE__", TI.UnsignedChar, Builder);

MitalAshok wrote:

According to https://gcc.gnu.org/legacy-ml/gcc-patches/2018-11/msg00295.html 
`__CHAR8_TYPE__` is "the underlying type of `char8_t`" in C++. `char8_t` in C++ 
was added in GCC9 which explains the difference between GCC8 and 9

And this made me realise `-std=c++11 -fchar8_t` sets `LangOpts.Char8` in C++11, 
which I think this patch handles fine (See also: #97601).
Also `-std=c23 -fchar8_t` is a mode that exists. It makes `typeof(u8'x')` 
`char8_t` and `typeof(u8"")` `char8_t[1]`, even with this patch, which I guess 
is fine. Pending #55373 if `-std=c23 -fchar8_t` even makes sense.

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


[clang] [Clang] Warn on backslash-newline-EOF (PR #97585)

2024-07-04 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/97585

>From 8af656659b79d76c971b01f1f4c14dc7315565b8 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Fri, 21 Jun 2024 18:55:38 +0100
Subject: [PATCH 1/2] [Clang] Warn on backslash-newline-EOF

---
 clang/docs/ReleaseNotes.rst   |  2 +
 .../include/clang/Basic/DiagnosticLexKinds.td |  1 +
 clang/lib/Lex/Lexer.cpp   | 39 +--
 clang/test/CXX/drs/cwg16xx.cpp|  9 +
 clang/test/CXX/drs/cwg2747.cpp| 11 ++
 clang/test/CXX/drs/cwg27xx.cpp|  2 +
 .../test/Preprocessor/backslash_newline_eof.c | 12 ++
 .../Preprocessor/backslash_without_newline.c  |  8 
 .../Preprocessor/backslash_without_newline.h  |  4 ++
 clang/www/cxx_dr_status.html  |  4 +-
 10 files changed, 87 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/CXX/drs/cwg2747.cpp
 create mode 100644 clang/test/Preprocessor/backslash_newline_eof.c
 create mode 100644 clang/test/Preprocessor/backslash_without_newline.c
 create mode 100644 clang/test/Preprocessor/backslash_without_newline.h

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f40fd1cd145bb..7c0ac3a504f98 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -647,6 +647,8 @@ Improvements to Clang's diagnostics
 
 - Clang now shows implicit deduction guides when diagnosing overload 
resolution failure. #GH92393.
 
+- Clang now emits ``-Wnewline-eof`` when the last newline is deleted by a 
preceding backslash.
+
 Improvements to Clang's time-trace
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td 
b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 12d7b8c0205ee..e6b2c1385944c 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -56,6 +56,7 @@ def ext_no_newline_eof : Extension<"no newline at end of 
file">,
   InGroup;
 def warn_no_newline_eof : Warning<"no newline at end of file">,
   InGroup, DefaultIgnore;
+def note_backslash_newline_eof : Note<"last newline deleted by splice here">;
 
 def warn_cxx98_compat_no_newline_eof : Warning<
   "C++98 requires newline at end of file">,
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index e59c7805b3862..0e540834b473b 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -3165,7 +3165,17 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
 
   // C99 5.1.1.2p2: If the file is non-empty and didn't end in a newline, issue
   // a pedwarn.
-  if (CurPtr != BufferStart && (CurPtr[-1] != '\n' && CurPtr[-1] != '\r')) {
+  if (CurPtr != BufferStart) {
+StringRef LastNewline;
+if (CurPtr[-1] == '\r' || CurPtr[-1] == '\n') {
+  LastNewline = StringRef(CurPtr - 1, 1);
+  if (CurPtr - 1 != BufferStart && CurPtr[-2] != CurPtr[-1] &&
+  (CurPtr[-2] == '\r' || CurPtr[-2] == '\n')) {
+// \r\n or \n\r is one newline
+LastNewline = StringRef(CurPtr - 2, 2);
+  }
+}
+
 DiagnosticsEngine &Diags = PP->getDiagnostics();
 SourceLocation EndLoc = getSourceLocation(BufferEnd);
 unsigned DiagID;
@@ -3183,8 +3193,31 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
   DiagID = diag::ext_no_newline_eof;
 }
 
-Diag(BufferEnd, DiagID)
-  << FixItHint::CreateInsertion(EndLoc, "\n");
+if (LastNewline.empty()) {
+  Diag(BufferEnd, DiagID) << FixItHint::CreateInsertion(EndLoc, "\n");
+} else {
+  // While the file physically ends in a newline, the previous
+  // line might have ended in a splice, so it would be deleted
+  const char *LastSpliceLocation = LastNewline.data();
+  while (LastSpliceLocation != BufferStart &&
+ isHorizontalWhitespace(*--LastSpliceLocation))
+;
+
+  bool LastIsSplice = *LastSpliceLocation == '\\';
+  if (*LastSpliceLocation == '/' && LangOpts.Trigraphs)
+// Check for "??/" trigraph for "\"
+LastIsSplice =
+LastSpliceLocation != BufferStart && *--LastSpliceLocation == '?' 
&&
+LastSpliceLocation != BufferStart && *--LastSpliceLocation == '?';
+
+  if (LastIsSplice) {
+PP->Diag(getSourceLocation(LastNewline.data(), LastNewline.size()),
+ DiagID);
+Diag(LastSpliceLocation, diag::note_backslash_newline_eof)
+<< FixItHint::CreateRemoval(getSourceLocation(
+   LastSpliceLocation, *LastSpliceLocation == '\\' ? 1 : 3));
+  }
+}
   }
 
   BufferPtr = CurPtr;
diff --git a/clang/test/CXX/drs/cwg16xx.cpp b/clang/test/CXX/drs/cwg16xx.cpp
index cf6b45ceabf2c..dca941fa30624 100644
--- a/clang/test/CXX/drs/cwg16xx.cpp
+++ b/clang/test/CXX/drs/cwg16xx.cpp
@@ -536,3 +536,12 @@ namespace cwg1696 { // cwg1696: 7
   };
 #endif
 }
+
+// cwg1698: yes
+// This file intentionally does not end in a ne

[clang] [Clang] Warn on backslash-newline-EOF (PR #97585)

2024-07-04 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/97585

>From 8af656659b79d76c971b01f1f4c14dc7315565b8 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Fri, 21 Jun 2024 18:55:38 +0100
Subject: [PATCH 1/3] [Clang] Warn on backslash-newline-EOF

---
 clang/docs/ReleaseNotes.rst   |  2 +
 .../include/clang/Basic/DiagnosticLexKinds.td |  1 +
 clang/lib/Lex/Lexer.cpp   | 39 +--
 clang/test/CXX/drs/cwg16xx.cpp|  9 +
 clang/test/CXX/drs/cwg2747.cpp| 11 ++
 clang/test/CXX/drs/cwg27xx.cpp|  2 +
 .../test/Preprocessor/backslash_newline_eof.c | 12 ++
 .../Preprocessor/backslash_without_newline.c  |  8 
 .../Preprocessor/backslash_without_newline.h  |  4 ++
 clang/www/cxx_dr_status.html  |  4 +-
 10 files changed, 87 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/CXX/drs/cwg2747.cpp
 create mode 100644 clang/test/Preprocessor/backslash_newline_eof.c
 create mode 100644 clang/test/Preprocessor/backslash_without_newline.c
 create mode 100644 clang/test/Preprocessor/backslash_without_newline.h

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f40fd1cd145bb..7c0ac3a504f98 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -647,6 +647,8 @@ Improvements to Clang's diagnostics
 
 - Clang now shows implicit deduction guides when diagnosing overload 
resolution failure. #GH92393.
 
+- Clang now emits ``-Wnewline-eof`` when the last newline is deleted by a 
preceding backslash.
+
 Improvements to Clang's time-trace
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td 
b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 12d7b8c0205ee..e6b2c1385944c 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -56,6 +56,7 @@ def ext_no_newline_eof : Extension<"no newline at end of 
file">,
   InGroup;
 def warn_no_newline_eof : Warning<"no newline at end of file">,
   InGroup, DefaultIgnore;
+def note_backslash_newline_eof : Note<"last newline deleted by splice here">;
 
 def warn_cxx98_compat_no_newline_eof : Warning<
   "C++98 requires newline at end of file">,
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index e59c7805b3862..0e540834b473b 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -3165,7 +3165,17 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
 
   // C99 5.1.1.2p2: If the file is non-empty and didn't end in a newline, issue
   // a pedwarn.
-  if (CurPtr != BufferStart && (CurPtr[-1] != '\n' && CurPtr[-1] != '\r')) {
+  if (CurPtr != BufferStart) {
+StringRef LastNewline;
+if (CurPtr[-1] == '\r' || CurPtr[-1] == '\n') {
+  LastNewline = StringRef(CurPtr - 1, 1);
+  if (CurPtr - 1 != BufferStart && CurPtr[-2] != CurPtr[-1] &&
+  (CurPtr[-2] == '\r' || CurPtr[-2] == '\n')) {
+// \r\n or \n\r is one newline
+LastNewline = StringRef(CurPtr - 2, 2);
+  }
+}
+
 DiagnosticsEngine &Diags = PP->getDiagnostics();
 SourceLocation EndLoc = getSourceLocation(BufferEnd);
 unsigned DiagID;
@@ -3183,8 +3193,31 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
   DiagID = diag::ext_no_newline_eof;
 }
 
-Diag(BufferEnd, DiagID)
-  << FixItHint::CreateInsertion(EndLoc, "\n");
+if (LastNewline.empty()) {
+  Diag(BufferEnd, DiagID) << FixItHint::CreateInsertion(EndLoc, "\n");
+} else {
+  // While the file physically ends in a newline, the previous
+  // line might have ended in a splice, so it would be deleted
+  const char *LastSpliceLocation = LastNewline.data();
+  while (LastSpliceLocation != BufferStart &&
+ isHorizontalWhitespace(*--LastSpliceLocation))
+;
+
+  bool LastIsSplice = *LastSpliceLocation == '\\';
+  if (*LastSpliceLocation == '/' && LangOpts.Trigraphs)
+// Check for "??/" trigraph for "\"
+LastIsSplice =
+LastSpliceLocation != BufferStart && *--LastSpliceLocation == '?' 
&&
+LastSpliceLocation != BufferStart && *--LastSpliceLocation == '?';
+
+  if (LastIsSplice) {
+PP->Diag(getSourceLocation(LastNewline.data(), LastNewline.size()),
+ DiagID);
+Diag(LastSpliceLocation, diag::note_backslash_newline_eof)
+<< FixItHint::CreateRemoval(getSourceLocation(
+   LastSpliceLocation, *LastSpliceLocation == '\\' ? 1 : 3));
+  }
+}
   }
 
   BufferPtr = CurPtr;
diff --git a/clang/test/CXX/drs/cwg16xx.cpp b/clang/test/CXX/drs/cwg16xx.cpp
index cf6b45ceabf2c..dca941fa30624 100644
--- a/clang/test/CXX/drs/cwg16xx.cpp
+++ b/clang/test/CXX/drs/cwg16xx.cpp
@@ -536,3 +536,12 @@ namespace cwg1696 { // cwg1696: 7
   };
 #endif
 }
+
+// cwg1698: yes
+// This file intentionally does not end in a ne

[clang] [Clang] Warn on backslash-newline-EOF (PR #97585)

2024-07-04 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/97585

>From 8af656659b79d76c971b01f1f4c14dc7315565b8 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Fri, 21 Jun 2024 18:55:38 +0100
Subject: [PATCH 1/4] [Clang] Warn on backslash-newline-EOF

---
 clang/docs/ReleaseNotes.rst   |  2 +
 .../include/clang/Basic/DiagnosticLexKinds.td |  1 +
 clang/lib/Lex/Lexer.cpp   | 39 +--
 clang/test/CXX/drs/cwg16xx.cpp|  9 +
 clang/test/CXX/drs/cwg2747.cpp| 11 ++
 clang/test/CXX/drs/cwg27xx.cpp|  2 +
 .../test/Preprocessor/backslash_newline_eof.c | 12 ++
 .../Preprocessor/backslash_without_newline.c  |  8 
 .../Preprocessor/backslash_without_newline.h  |  4 ++
 clang/www/cxx_dr_status.html  |  4 +-
 10 files changed, 87 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/CXX/drs/cwg2747.cpp
 create mode 100644 clang/test/Preprocessor/backslash_newline_eof.c
 create mode 100644 clang/test/Preprocessor/backslash_without_newline.c
 create mode 100644 clang/test/Preprocessor/backslash_without_newline.h

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f40fd1cd145bb0..7c0ac3a504f982 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -647,6 +647,8 @@ Improvements to Clang's diagnostics
 
 - Clang now shows implicit deduction guides when diagnosing overload 
resolution failure. #GH92393.
 
+- Clang now emits ``-Wnewline-eof`` when the last newline is deleted by a 
preceding backslash.
+
 Improvements to Clang's time-trace
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td 
b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 12d7b8c0205ee9..e6b2c1385944c7 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -56,6 +56,7 @@ def ext_no_newline_eof : Extension<"no newline at end of 
file">,
   InGroup;
 def warn_no_newline_eof : Warning<"no newline at end of file">,
   InGroup, DefaultIgnore;
+def note_backslash_newline_eof : Note<"last newline deleted by splice here">;
 
 def warn_cxx98_compat_no_newline_eof : Warning<
   "C++98 requires newline at end of file">,
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index e59c7805b38623..0e540834b473ba 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -3165,7 +3165,17 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
 
   // C99 5.1.1.2p2: If the file is non-empty and didn't end in a newline, issue
   // a pedwarn.
-  if (CurPtr != BufferStart && (CurPtr[-1] != '\n' && CurPtr[-1] != '\r')) {
+  if (CurPtr != BufferStart) {
+StringRef LastNewline;
+if (CurPtr[-1] == '\r' || CurPtr[-1] == '\n') {
+  LastNewline = StringRef(CurPtr - 1, 1);
+  if (CurPtr - 1 != BufferStart && CurPtr[-2] != CurPtr[-1] &&
+  (CurPtr[-2] == '\r' || CurPtr[-2] == '\n')) {
+// \r\n or \n\r is one newline
+LastNewline = StringRef(CurPtr - 2, 2);
+  }
+}
+
 DiagnosticsEngine &Diags = PP->getDiagnostics();
 SourceLocation EndLoc = getSourceLocation(BufferEnd);
 unsigned DiagID;
@@ -3183,8 +3193,31 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
   DiagID = diag::ext_no_newline_eof;
 }
 
-Diag(BufferEnd, DiagID)
-  << FixItHint::CreateInsertion(EndLoc, "\n");
+if (LastNewline.empty()) {
+  Diag(BufferEnd, DiagID) << FixItHint::CreateInsertion(EndLoc, "\n");
+} else {
+  // While the file physically ends in a newline, the previous
+  // line might have ended in a splice, so it would be deleted
+  const char *LastSpliceLocation = LastNewline.data();
+  while (LastSpliceLocation != BufferStart &&
+ isHorizontalWhitespace(*--LastSpliceLocation))
+;
+
+  bool LastIsSplice = *LastSpliceLocation == '\\';
+  if (*LastSpliceLocation == '/' && LangOpts.Trigraphs)
+// Check for "??/" trigraph for "\"
+LastIsSplice =
+LastSpliceLocation != BufferStart && *--LastSpliceLocation == '?' 
&&
+LastSpliceLocation != BufferStart && *--LastSpliceLocation == '?';
+
+  if (LastIsSplice) {
+PP->Diag(getSourceLocation(LastNewline.data(), LastNewline.size()),
+ DiagID);
+Diag(LastSpliceLocation, diag::note_backslash_newline_eof)
+<< FixItHint::CreateRemoval(getSourceLocation(
+   LastSpliceLocation, *LastSpliceLocation == '\\' ? 1 : 3));
+  }
+}
   }
 
   BufferPtr = CurPtr;
diff --git a/clang/test/CXX/drs/cwg16xx.cpp b/clang/test/CXX/drs/cwg16xx.cpp
index cf6b45ceabf2cc..dca941fa30624f 100644
--- a/clang/test/CXX/drs/cwg16xx.cpp
+++ b/clang/test/CXX/drs/cwg16xx.cpp
@@ -536,3 +536,12 @@ namespace cwg1696 { // cwg1696: 7
   };
 #endif
 }
+
+// cwg1698: yes
+// This file intentionally does not end

[clang] [Clang] Warn on backslash-newline-EOF (PR #97585)

2024-07-04 Thread Mital Ashok via cfe-commits

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


[clang] [Clang] Warn on backslash-newline-EOF (PR #97585)

2024-07-04 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/97585

>From 8af656659b79d76c971b01f1f4c14dc7315565b8 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Fri, 21 Jun 2024 18:55:38 +0100
Subject: [PATCH 1/5] [Clang] Warn on backslash-newline-EOF

---
 clang/docs/ReleaseNotes.rst   |  2 +
 .../include/clang/Basic/DiagnosticLexKinds.td |  1 +
 clang/lib/Lex/Lexer.cpp   | 39 +--
 clang/test/CXX/drs/cwg16xx.cpp|  9 +
 clang/test/CXX/drs/cwg2747.cpp| 11 ++
 clang/test/CXX/drs/cwg27xx.cpp|  2 +
 .../test/Preprocessor/backslash_newline_eof.c | 12 ++
 .../Preprocessor/backslash_without_newline.c  |  8 
 .../Preprocessor/backslash_without_newline.h  |  4 ++
 clang/www/cxx_dr_status.html  |  4 +-
 10 files changed, 87 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/CXX/drs/cwg2747.cpp
 create mode 100644 clang/test/Preprocessor/backslash_newline_eof.c
 create mode 100644 clang/test/Preprocessor/backslash_without_newline.c
 create mode 100644 clang/test/Preprocessor/backslash_without_newline.h

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f40fd1cd145bb..7c0ac3a504f98 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -647,6 +647,8 @@ Improvements to Clang's diagnostics
 
 - Clang now shows implicit deduction guides when diagnosing overload 
resolution failure. #GH92393.
 
+- Clang now emits ``-Wnewline-eof`` when the last newline is deleted by a 
preceding backslash.
+
 Improvements to Clang's time-trace
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td 
b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 12d7b8c0205ee..e6b2c1385944c 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -56,6 +56,7 @@ def ext_no_newline_eof : Extension<"no newline at end of 
file">,
   InGroup;
 def warn_no_newline_eof : Warning<"no newline at end of file">,
   InGroup, DefaultIgnore;
+def note_backslash_newline_eof : Note<"last newline deleted by splice here">;
 
 def warn_cxx98_compat_no_newline_eof : Warning<
   "C++98 requires newline at end of file">,
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index e59c7805b3862..0e540834b473b 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -3165,7 +3165,17 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
 
   // C99 5.1.1.2p2: If the file is non-empty and didn't end in a newline, issue
   // a pedwarn.
-  if (CurPtr != BufferStart && (CurPtr[-1] != '\n' && CurPtr[-1] != '\r')) {
+  if (CurPtr != BufferStart) {
+StringRef LastNewline;
+if (CurPtr[-1] == '\r' || CurPtr[-1] == '\n') {
+  LastNewline = StringRef(CurPtr - 1, 1);
+  if (CurPtr - 1 != BufferStart && CurPtr[-2] != CurPtr[-1] &&
+  (CurPtr[-2] == '\r' || CurPtr[-2] == '\n')) {
+// \r\n or \n\r is one newline
+LastNewline = StringRef(CurPtr - 2, 2);
+  }
+}
+
 DiagnosticsEngine &Diags = PP->getDiagnostics();
 SourceLocation EndLoc = getSourceLocation(BufferEnd);
 unsigned DiagID;
@@ -3183,8 +3193,31 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
   DiagID = diag::ext_no_newline_eof;
 }
 
-Diag(BufferEnd, DiagID)
-  << FixItHint::CreateInsertion(EndLoc, "\n");
+if (LastNewline.empty()) {
+  Diag(BufferEnd, DiagID) << FixItHint::CreateInsertion(EndLoc, "\n");
+} else {
+  // While the file physically ends in a newline, the previous
+  // line might have ended in a splice, so it would be deleted
+  const char *LastSpliceLocation = LastNewline.data();
+  while (LastSpliceLocation != BufferStart &&
+ isHorizontalWhitespace(*--LastSpliceLocation))
+;
+
+  bool LastIsSplice = *LastSpliceLocation == '\\';
+  if (*LastSpliceLocation == '/' && LangOpts.Trigraphs)
+// Check for "??/" trigraph for "\"
+LastIsSplice =
+LastSpliceLocation != BufferStart && *--LastSpliceLocation == '?' 
&&
+LastSpliceLocation != BufferStart && *--LastSpliceLocation == '?';
+
+  if (LastIsSplice) {
+PP->Diag(getSourceLocation(LastNewline.data(), LastNewline.size()),
+ DiagID);
+Diag(LastSpliceLocation, diag::note_backslash_newline_eof)
+<< FixItHint::CreateRemoval(getSourceLocation(
+   LastSpliceLocation, *LastSpliceLocation == '\\' ? 1 : 3));
+  }
+}
   }
 
   BufferPtr = CurPtr;
diff --git a/clang/test/CXX/drs/cwg16xx.cpp b/clang/test/CXX/drs/cwg16xx.cpp
index cf6b45ceabf2c..dca941fa30624 100644
--- a/clang/test/CXX/drs/cwg16xx.cpp
+++ b/clang/test/CXX/drs/cwg16xx.cpp
@@ -536,3 +536,12 @@ namespace cwg1696 { // cwg1696: 7
   };
 #endif
 }
+
+// cwg1698: yes
+// This file intentionally does not end in a ne

[clang] [Clang] Warn on backslash-newline-EOF (PR #97585)

2024-07-05 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/97585

>From 8af656659b79d76c971b01f1f4c14dc7315565b8 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Fri, 21 Jun 2024 18:55:38 +0100
Subject: [PATCH 1/6] [Clang] Warn on backslash-newline-EOF

---
 clang/docs/ReleaseNotes.rst   |  2 +
 .../include/clang/Basic/DiagnosticLexKinds.td |  1 +
 clang/lib/Lex/Lexer.cpp   | 39 +--
 clang/test/CXX/drs/cwg16xx.cpp|  9 +
 clang/test/CXX/drs/cwg2747.cpp| 11 ++
 clang/test/CXX/drs/cwg27xx.cpp|  2 +
 .../test/Preprocessor/backslash_newline_eof.c | 12 ++
 .../Preprocessor/backslash_without_newline.c  |  8 
 .../Preprocessor/backslash_without_newline.h  |  4 ++
 clang/www/cxx_dr_status.html  |  4 +-
 10 files changed, 87 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/CXX/drs/cwg2747.cpp
 create mode 100644 clang/test/Preprocessor/backslash_newline_eof.c
 create mode 100644 clang/test/Preprocessor/backslash_without_newline.c
 create mode 100644 clang/test/Preprocessor/backslash_without_newline.h

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f40fd1cd145bb0..7c0ac3a504f982 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -647,6 +647,8 @@ Improvements to Clang's diagnostics
 
 - Clang now shows implicit deduction guides when diagnosing overload 
resolution failure. #GH92393.
 
+- Clang now emits ``-Wnewline-eof`` when the last newline is deleted by a 
preceding backslash.
+
 Improvements to Clang's time-trace
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td 
b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 12d7b8c0205ee9..e6b2c1385944c7 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -56,6 +56,7 @@ def ext_no_newline_eof : Extension<"no newline at end of 
file">,
   InGroup;
 def warn_no_newline_eof : Warning<"no newline at end of file">,
   InGroup, DefaultIgnore;
+def note_backslash_newline_eof : Note<"last newline deleted by splice here">;
 
 def warn_cxx98_compat_no_newline_eof : Warning<
   "C++98 requires newline at end of file">,
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index e59c7805b38623..0e540834b473ba 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -3165,7 +3165,17 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
 
   // C99 5.1.1.2p2: If the file is non-empty and didn't end in a newline, issue
   // a pedwarn.
-  if (CurPtr != BufferStart && (CurPtr[-1] != '\n' && CurPtr[-1] != '\r')) {
+  if (CurPtr != BufferStart) {
+StringRef LastNewline;
+if (CurPtr[-1] == '\r' || CurPtr[-1] == '\n') {
+  LastNewline = StringRef(CurPtr - 1, 1);
+  if (CurPtr - 1 != BufferStart && CurPtr[-2] != CurPtr[-1] &&
+  (CurPtr[-2] == '\r' || CurPtr[-2] == '\n')) {
+// \r\n or \n\r is one newline
+LastNewline = StringRef(CurPtr - 2, 2);
+  }
+}
+
 DiagnosticsEngine &Diags = PP->getDiagnostics();
 SourceLocation EndLoc = getSourceLocation(BufferEnd);
 unsigned DiagID;
@@ -3183,8 +3193,31 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
   DiagID = diag::ext_no_newline_eof;
 }
 
-Diag(BufferEnd, DiagID)
-  << FixItHint::CreateInsertion(EndLoc, "\n");
+if (LastNewline.empty()) {
+  Diag(BufferEnd, DiagID) << FixItHint::CreateInsertion(EndLoc, "\n");
+} else {
+  // While the file physically ends in a newline, the previous
+  // line might have ended in a splice, so it would be deleted
+  const char *LastSpliceLocation = LastNewline.data();
+  while (LastSpliceLocation != BufferStart &&
+ isHorizontalWhitespace(*--LastSpliceLocation))
+;
+
+  bool LastIsSplice = *LastSpliceLocation == '\\';
+  if (*LastSpliceLocation == '/' && LangOpts.Trigraphs)
+// Check for "??/" trigraph for "\"
+LastIsSplice =
+LastSpliceLocation != BufferStart && *--LastSpliceLocation == '?' 
&&
+LastSpliceLocation != BufferStart && *--LastSpliceLocation == '?';
+
+  if (LastIsSplice) {
+PP->Diag(getSourceLocation(LastNewline.data(), LastNewline.size()),
+ DiagID);
+Diag(LastSpliceLocation, diag::note_backslash_newline_eof)
+<< FixItHint::CreateRemoval(getSourceLocation(
+   LastSpliceLocation, *LastSpliceLocation == '\\' ? 1 : 3));
+  }
+}
   }
 
   BufferPtr = CurPtr;
diff --git a/clang/test/CXX/drs/cwg16xx.cpp b/clang/test/CXX/drs/cwg16xx.cpp
index cf6b45ceabf2cc..dca941fa30624f 100644
--- a/clang/test/CXX/drs/cwg16xx.cpp
+++ b/clang/test/CXX/drs/cwg16xx.cpp
@@ -536,3 +536,12 @@ namespace cwg1696 { // cwg1696: 7
   };
 #endif
 }
+
+// cwg1698: yes
+// This file intentionally does not end

[clang] [Clang] Warn on backslash-newline-EOF (PR #97585)

2024-07-05 Thread Mital Ashok via cfe-commits


@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -std=c++11 -pedantic-errors -verify=expected %s -E | 
FileCheck %s --strict-whitespace --allow-empty

MitalAshok wrote:

Fixed now, thanks

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


[clang] [Clang] [C23] Fix typeof_unqual for qualified array types (PR #92767)

2024-07-05 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/92767

>From f87cb4c754a477515746e2ac2f8906b93ccd1fe3 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Mon, 20 May 2024 15:58:58 +0100
Subject: [PATCH 1/5] [Clang] [C23] Fix typeof_unqual for qualified array types

Properly remove qualifiers for both the element type and the array type

Fixes #92667
---
 clang/include/clang/AST/ASTContext.h |  6 -
 clang/include/clang/AST/Type.h   | 37 +--
 clang/lib/AST/ASTContext.cpp | 14 +-
 clang/lib/AST/Type.cpp   | 38 ++--
 clang/test/Sema/c2x-typeof.c | 25 ++
 5 files changed, 84 insertions(+), 36 deletions(-)

diff --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index e03b112194786..ff7bdb7e7e1a6 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2611,7 +2611,11 @@ class ASTContext : public RefCountedBase {
   ///
   /// \returns if this is an array type, the completely unqualified array type
   /// that corresponds to it. Otherwise, returns T.getUnqualifiedType().
-  QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals);
+  QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals) const;
+  QualType getUnqualifiedArrayType(QualType T) const {
+Qualifiers Quals;
+return getUnqualifiedArrayType(T, Quals);
+  }
 
   /// Determine whether the given types are equivalent after
   /// cvr-qualifiers have been removed.
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index da3834f19ca04..df7f396bae095 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1605,6 +1605,10 @@ class QualType {
   QualType stripObjCKindOfType(const ASTContext &ctx) const;
 
   /// Remove all qualifiers including _Atomic.
+  ///
+  /// Like getUnqualifiedType(), the type may still be qualified if it is a
+  /// sugared array type.  To strip qualifiers even from within a sugared array
+  /// type, use ASTContext::getUnqualifiedArrayType.
   QualType getAtomicUnqualifiedType() const;
 
 private:
@@ -2092,8 +2096,8 @@ class alignas(TypeAlignment) Type : public 
ExtQualsTypeCommonBase {
 
 LLVM_PREFERRED_TYPE(TypeBitfields)
 unsigned : NumTypeBits;
-LLVM_PREFERRED_TYPE(bool)
-unsigned IsUnqual : 1; // If true: typeof_unqual, else: typeof
+LLVM_PREFERRED_TYPE(TypeOfKind)
+unsigned Kind : 1;
   };
 
   class UsingBitfields {
@@ -5273,19 +5277,20 @@ class MacroQualifiedType : public Type {
 /// extension) or a `typeof_unqual` expression (a C23 feature).
 class TypeOfExprType : public Type {
   Expr *TOExpr;
+  const ASTContext &Context;
 
 protected:
   friend class ASTContext; // ASTContext creates these.
 
-  TypeOfExprType(Expr *E, TypeOfKind Kind, QualType Can = QualType());
+  TypeOfExprType(const ASTContext &Context, Expr *E, TypeOfKind Kind,
+ QualType Can = QualType());
 
 public:
   Expr *getUnderlyingExpr() const { return TOExpr; }
 
   /// Returns the kind of 'typeof' type this is.
   TypeOfKind getKind() const {
-return TypeOfBits.IsUnqual ? TypeOfKind::Unqualified
-   : TypeOfKind::Qualified;
+return static_cast(TypeOfBits.Kind);
   }
 
   /// Remove a single level of sugar.
@@ -5306,7 +5311,8 @@ class TypeOfExprType : public Type {
 class DependentTypeOfExprType : public TypeOfExprType,
 public llvm::FoldingSetNode {
 public:
-  DependentTypeOfExprType(Expr *E, TypeOfKind Kind) : TypeOfExprType(E, Kind) 
{}
+  DependentTypeOfExprType(const ASTContext &Context, Expr *E, TypeOfKind Kind)
+  : TypeOfExprType(Context, E, Kind) {}
 
   void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
 Profile(ID, Context, getUnderlyingExpr(),
@@ -5323,32 +5329,23 @@ class TypeOfType : public Type {
   friend class ASTContext; // ASTContext creates these.
 
   QualType TOType;
+  const ASTContext &Context;
 
-  TypeOfType(QualType T, QualType Can, TypeOfKind Kind)
-  : Type(TypeOf,
- Kind == TypeOfKind::Unqualified ? Can.getAtomicUnqualifiedType()
- : Can,
- T->getDependence()),
-TOType(T) {
-TypeOfBits.IsUnqual = Kind == TypeOfKind::Unqualified;
-  }
+  TypeOfType(const ASTContext &Context, QualType T, QualType Can,
+ TypeOfKind Kind);
 
 public:
   QualType getUnmodifiedType() const { return TOType; }
 
   /// Remove a single level of sugar.
-  QualType desugar() const {
-QualType QT = getUnmodifiedType();
-return TypeOfBits.IsUnqual ? QT.getAtomicUnqualifiedType() : QT;
-  }
+  QualType desugar() const;
 
   /// Returns whether this type directly provides sugar.
   bool isSugared() const { return true; }
 
   /// Returns the kind of 'typeof' type this is.
   TypeOfKind getKind() const {
-return TypeOfBits.IsUnqual ? 

[clang] [Clang] Warn on backslash-newline-EOF (PR #97585)

2024-07-05 Thread Mital Ashok via cfe-commits


@@ -3183,8 +3193,35 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
   DiagID = diag::ext_no_newline_eof;
 }
 
-Diag(BufferEnd, DiagID)
-  << FixItHint::CreateInsertion(EndLoc, "\n");
+if (LastNewline.empty()) {
+  Diag(BufferEnd, DiagID) << FixItHint::CreateInsertion(EndLoc, "\n");
+} else {
+  // While the file physically ends in a newline, the previous
+  // line might have ended in a splice, so it would be deleted
+  StringRef WithoutLastNewline =
+  StringRef(BufferStart, LastNewline.data() - BufferStart);
+  while (!WithoutLastNewline.empty()) {
+if (isHorizontalWhitespace(WithoutLastNewline.back())) {
+  WithoutLastNewline = WithoutLastNewline.drop_back();
+} else {
+  break;
+}
+  }
+
+  if (WithoutLastNewline.ends_with('\\') ||
+  (LangOpts.Trigraphs && WithoutLastNewline.ends_with("??"
+  "/"))) {

MitalAshok wrote:

That gives a "warning: trigraph ignored [-Wtrigraphs]" warning when compiling 
this

clang-format refuses to put concatenated string literals on the same line.

I've changed this and added a comment, but let me know if this could be done in 
a cleaner way

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


[clang] [Clang] Warn on backslash-newline-EOF (PR #97585)

2024-07-05 Thread Mital Ashok via cfe-commits


@@ -647,6 +647,8 @@ Improvements to Clang's diagnostics
 
 - Clang now shows implicit deduction guides when diagnosing overload 
resolution failure. #GH92393.
 
+- Clang now emits ``-Wnewline-eof`` when the last newline is deleted by a 
preceding backslash. #GH41571.

MitalAshok wrote:

Is the space before the full stop intentional?

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


[clang] [Clang] Warn on backslash-newline-EOF (PR #97585)

2024-07-05 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/97585

>From 8af656659b79d76c971b01f1f4c14dc7315565b8 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Fri, 21 Jun 2024 18:55:38 +0100
Subject: [PATCH 1/8] [Clang] Warn on backslash-newline-EOF

---
 clang/docs/ReleaseNotes.rst   |  2 +
 .../include/clang/Basic/DiagnosticLexKinds.td |  1 +
 clang/lib/Lex/Lexer.cpp   | 39 +--
 clang/test/CXX/drs/cwg16xx.cpp|  9 +
 clang/test/CXX/drs/cwg2747.cpp| 11 ++
 clang/test/CXX/drs/cwg27xx.cpp|  2 +
 .../test/Preprocessor/backslash_newline_eof.c | 12 ++
 .../Preprocessor/backslash_without_newline.c  |  8 
 .../Preprocessor/backslash_without_newline.h  |  4 ++
 clang/www/cxx_dr_status.html  |  4 +-
 10 files changed, 87 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/CXX/drs/cwg2747.cpp
 create mode 100644 clang/test/Preprocessor/backslash_newline_eof.c
 create mode 100644 clang/test/Preprocessor/backslash_without_newline.c
 create mode 100644 clang/test/Preprocessor/backslash_without_newline.h

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f40fd1cd145bb..7c0ac3a504f98 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -647,6 +647,8 @@ Improvements to Clang's diagnostics
 
 - Clang now shows implicit deduction guides when diagnosing overload 
resolution failure. #GH92393.
 
+- Clang now emits ``-Wnewline-eof`` when the last newline is deleted by a 
preceding backslash.
+
 Improvements to Clang's time-trace
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td 
b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 12d7b8c0205ee..e6b2c1385944c 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -56,6 +56,7 @@ def ext_no_newline_eof : Extension<"no newline at end of 
file">,
   InGroup;
 def warn_no_newline_eof : Warning<"no newline at end of file">,
   InGroup, DefaultIgnore;
+def note_backslash_newline_eof : Note<"last newline deleted by splice here">;
 
 def warn_cxx98_compat_no_newline_eof : Warning<
   "C++98 requires newline at end of file">,
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index e59c7805b3862..0e540834b473b 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -3165,7 +3165,17 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
 
   // C99 5.1.1.2p2: If the file is non-empty and didn't end in a newline, issue
   // a pedwarn.
-  if (CurPtr != BufferStart && (CurPtr[-1] != '\n' && CurPtr[-1] != '\r')) {
+  if (CurPtr != BufferStart) {
+StringRef LastNewline;
+if (CurPtr[-1] == '\r' || CurPtr[-1] == '\n') {
+  LastNewline = StringRef(CurPtr - 1, 1);
+  if (CurPtr - 1 != BufferStart && CurPtr[-2] != CurPtr[-1] &&
+  (CurPtr[-2] == '\r' || CurPtr[-2] == '\n')) {
+// \r\n or \n\r is one newline
+LastNewline = StringRef(CurPtr - 2, 2);
+  }
+}
+
 DiagnosticsEngine &Diags = PP->getDiagnostics();
 SourceLocation EndLoc = getSourceLocation(BufferEnd);
 unsigned DiagID;
@@ -3183,8 +3193,31 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
   DiagID = diag::ext_no_newline_eof;
 }
 
-Diag(BufferEnd, DiagID)
-  << FixItHint::CreateInsertion(EndLoc, "\n");
+if (LastNewline.empty()) {
+  Diag(BufferEnd, DiagID) << FixItHint::CreateInsertion(EndLoc, "\n");
+} else {
+  // While the file physically ends in a newline, the previous
+  // line might have ended in a splice, so it would be deleted
+  const char *LastSpliceLocation = LastNewline.data();
+  while (LastSpliceLocation != BufferStart &&
+ isHorizontalWhitespace(*--LastSpliceLocation))
+;
+
+  bool LastIsSplice = *LastSpliceLocation == '\\';
+  if (*LastSpliceLocation == '/' && LangOpts.Trigraphs)
+// Check for "??/" trigraph for "\"
+LastIsSplice =
+LastSpliceLocation != BufferStart && *--LastSpliceLocation == '?' 
&&
+LastSpliceLocation != BufferStart && *--LastSpliceLocation == '?';
+
+  if (LastIsSplice) {
+PP->Diag(getSourceLocation(LastNewline.data(), LastNewline.size()),
+ DiagID);
+Diag(LastSpliceLocation, diag::note_backslash_newline_eof)
+<< FixItHint::CreateRemoval(getSourceLocation(
+   LastSpliceLocation, *LastSpliceLocation == '\\' ? 1 : 3));
+  }
+}
   }
 
   BufferPtr = CurPtr;
diff --git a/clang/test/CXX/drs/cwg16xx.cpp b/clang/test/CXX/drs/cwg16xx.cpp
index cf6b45ceabf2c..dca941fa30624 100644
--- a/clang/test/CXX/drs/cwg16xx.cpp
+++ b/clang/test/CXX/drs/cwg16xx.cpp
@@ -536,3 +536,12 @@ namespace cwg1696 { // cwg1696: 7
   };
 #endif
 }
+
+// cwg1698: yes
+// This file intentionally does not end in a ne

[clang] [Clang] Warn on backslash-newline-EOF (PR #97585)

2024-07-05 Thread Mital Ashok via cfe-commits


@@ -3183,8 +3193,35 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
   DiagID = diag::ext_no_newline_eof;
 }
 
-Diag(BufferEnd, DiagID)
-  << FixItHint::CreateInsertion(EndLoc, "\n");
+if (LastNewline.empty()) {
+  Diag(BufferEnd, DiagID) << FixItHint::CreateInsertion(EndLoc, "\n");
+} else {
+  // While the file physically ends in a newline, the previous
+  // line might have ended in a splice, so it would be deleted
+  StringRef WithoutLastNewline =
+  StringRef(BufferStart, LastNewline.data() - BufferStart);
+  while (!WithoutLastNewline.empty()) {
+if (isHorizontalWhitespace(WithoutLastNewline.back())) {
+  WithoutLastNewline = WithoutLastNewline.drop_back();
+} else {
+  break;
+}
+  }
+
+  if (WithoutLastNewline.ends_with('\\') ||
+  (LangOpts.Trigraphs && WithoutLastNewline.ends_with("??"
+  "/"))) {

MitalAshok wrote:

Clang-format doesn't mind `"??/"`, but it's the compiler that complains.

I had no idea `\?` was a valid escape sequence, but apparently it is: 
https://eel.is/c++draft/lex.ccon#note-1

I'll be using that thanks!

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


[clang] [Clang] Warn on backslash-newline-EOF (PR #97585)

2024-07-05 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/97585

>From 8af656659b79d76c971b01f1f4c14dc7315565b8 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Fri, 21 Jun 2024 18:55:38 +0100
Subject: [PATCH 1/9] [Clang] Warn on backslash-newline-EOF

---
 clang/docs/ReleaseNotes.rst   |  2 +
 .../include/clang/Basic/DiagnosticLexKinds.td |  1 +
 clang/lib/Lex/Lexer.cpp   | 39 +--
 clang/test/CXX/drs/cwg16xx.cpp|  9 +
 clang/test/CXX/drs/cwg2747.cpp| 11 ++
 clang/test/CXX/drs/cwg27xx.cpp|  2 +
 .../test/Preprocessor/backslash_newline_eof.c | 12 ++
 .../Preprocessor/backslash_without_newline.c  |  8 
 .../Preprocessor/backslash_without_newline.h  |  4 ++
 clang/www/cxx_dr_status.html  |  4 +-
 10 files changed, 87 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/CXX/drs/cwg2747.cpp
 create mode 100644 clang/test/Preprocessor/backslash_newline_eof.c
 create mode 100644 clang/test/Preprocessor/backslash_without_newline.c
 create mode 100644 clang/test/Preprocessor/backslash_without_newline.h

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f40fd1cd145bb..7c0ac3a504f98 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -647,6 +647,8 @@ Improvements to Clang's diagnostics
 
 - Clang now shows implicit deduction guides when diagnosing overload 
resolution failure. #GH92393.
 
+- Clang now emits ``-Wnewline-eof`` when the last newline is deleted by a 
preceding backslash.
+
 Improvements to Clang's time-trace
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td 
b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 12d7b8c0205ee..e6b2c1385944c 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -56,6 +56,7 @@ def ext_no_newline_eof : Extension<"no newline at end of 
file">,
   InGroup;
 def warn_no_newline_eof : Warning<"no newline at end of file">,
   InGroup, DefaultIgnore;
+def note_backslash_newline_eof : Note<"last newline deleted by splice here">;
 
 def warn_cxx98_compat_no_newline_eof : Warning<
   "C++98 requires newline at end of file">,
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index e59c7805b3862..0e540834b473b 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -3165,7 +3165,17 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
 
   // C99 5.1.1.2p2: If the file is non-empty and didn't end in a newline, issue
   // a pedwarn.
-  if (CurPtr != BufferStart && (CurPtr[-1] != '\n' && CurPtr[-1] != '\r')) {
+  if (CurPtr != BufferStart) {
+StringRef LastNewline;
+if (CurPtr[-1] == '\r' || CurPtr[-1] == '\n') {
+  LastNewline = StringRef(CurPtr - 1, 1);
+  if (CurPtr - 1 != BufferStart && CurPtr[-2] != CurPtr[-1] &&
+  (CurPtr[-2] == '\r' || CurPtr[-2] == '\n')) {
+// \r\n or \n\r is one newline
+LastNewline = StringRef(CurPtr - 2, 2);
+  }
+}
+
 DiagnosticsEngine &Diags = PP->getDiagnostics();
 SourceLocation EndLoc = getSourceLocation(BufferEnd);
 unsigned DiagID;
@@ -3183,8 +3193,31 @@ bool Lexer::LexEndOfFile(Token &Result, const char 
*CurPtr) {
   DiagID = diag::ext_no_newline_eof;
 }
 
-Diag(BufferEnd, DiagID)
-  << FixItHint::CreateInsertion(EndLoc, "\n");
+if (LastNewline.empty()) {
+  Diag(BufferEnd, DiagID) << FixItHint::CreateInsertion(EndLoc, "\n");
+} else {
+  // While the file physically ends in a newline, the previous
+  // line might have ended in a splice, so it would be deleted
+  const char *LastSpliceLocation = LastNewline.data();
+  while (LastSpliceLocation != BufferStart &&
+ isHorizontalWhitespace(*--LastSpliceLocation))
+;
+
+  bool LastIsSplice = *LastSpliceLocation == '\\';
+  if (*LastSpliceLocation == '/' && LangOpts.Trigraphs)
+// Check for "??/" trigraph for "\"
+LastIsSplice =
+LastSpliceLocation != BufferStart && *--LastSpliceLocation == '?' 
&&
+LastSpliceLocation != BufferStart && *--LastSpliceLocation == '?';
+
+  if (LastIsSplice) {
+PP->Diag(getSourceLocation(LastNewline.data(), LastNewline.size()),
+ DiagID);
+Diag(LastSpliceLocation, diag::note_backslash_newline_eof)
+<< FixItHint::CreateRemoval(getSourceLocation(
+   LastSpliceLocation, *LastSpliceLocation == '\\' ? 1 : 3));
+  }
+}
   }
 
   BufferPtr = CurPtr;
diff --git a/clang/test/CXX/drs/cwg16xx.cpp b/clang/test/CXX/drs/cwg16xx.cpp
index cf6b45ceabf2c..dca941fa30624 100644
--- a/clang/test/CXX/drs/cwg16xx.cpp
+++ b/clang/test/CXX/drs/cwg16xx.cpp
@@ -536,3 +536,12 @@ namespace cwg1696 { // cwg1696: 7
   };
 #endif
 }
+
+// cwg1698: yes
+// This file intentionally does not end in a ne

[clang] [Clang] Fix Microsoft ABI inheritance model when member pointer is used in a base specifier (PR #91990)

2024-07-06 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/91990

>From 5dc9193af0d98335a87e93ad70d945dbc0ffce79 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Mon, 13 May 2024 16:59:06 +0100
Subject: [PATCH 1/4] [Clang] Fix Microsoft ABI inheritance model when member
 pointer is used in a base specifier

Fix CXXRecordDecl::isParsingBaseSpecifiers so that it is true while parsing 
base specifiers instead of directly after they have been parsed.

-fcomplete-member-pointers now issues a diagnostic when a member pointer is 
used in a base specifier.

-fcomplete-member-pointers has also been relaxed to not issue a diagnostic for 
incomplete classes with an explicit __{single|multiple|virtual}_inheritance 
attribute, whose completeness would not affect the representation of 
pointer-to-member objects.
---
 clang/docs/ReleaseNotes.rst   |  4 +++
 clang/include/clang/AST/DeclCXX.h |  7 +++--
 .../clang/Basic/DiagnosticSemaKinds.td|  2 ++
 clang/lib/AST/DeclCXX.cpp |  6 +
 clang/lib/Parse/ParseDeclCXX.cpp  | 24 +
 clang/lib/Sema/SemaDeclCXX.cpp|  3 ---
 clang/lib/Sema/SemaType.cpp   | 27 ---
 .../test/SemaCXX/complete-member-pointers.cpp | 24 -
 clang/test/SemaCXX/member-pointer-ms.cpp  |  8 ++
 9 files changed, 85 insertions(+), 20 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 4702b8c10cdbb..054332c2cee4e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -79,6 +79,10 @@ ABI Changes in This Version
 - Fixed Microsoft calling convention when returning classes that have a deleted
   copy assignment operator. Such a class should be returned indirectly.
 
+- Fixed Microsoft layout of pointer-to-members of classes when the layout is 
needed
+  directly or indirectly by the base classes of a class. These should use the 
most
+  general unspecified inheritance layout. Also affects 
-fcomplete-member-pointers.
+
 AST Dumping Potentially Breaking Changes
 
 
diff --git a/clang/include/clang/AST/DeclCXX.h 
b/clang/include/clang/AST/DeclCXX.h
index fb52ac804849d..81669b1f606b3 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -297,7 +297,8 @@ class CXXRecordDecl : public RecordDecl {
 LLVM_PREFERRED_TYPE(bool)
 unsigned IsLambda : 1;
 
-/// Whether we are currently parsing base specifiers.
+/// Whether we are currently parsing base specifiers; the
+/// colon has been consumed but the beginning left brace hasn't.
 LLVM_PREFERRED_TYPE(bool)
 unsigned IsParsingBaseSpecifiers : 1;
 
@@ -598,7 +599,9 @@ class CXXRecordDecl : public RecordDecl {
 return !hasDefinition() || !isDynamicClass() || hasAnyDependentBases();
   }
 
-  void setIsParsingBaseSpecifiers() { data().IsParsingBaseSpecifiers = true; }
+  void setIsParsingBaseSpecifiers(bool to = true) {
+data().IsParsingBaseSpecifiers = to;
+  }
 
   bool isParsingBaseSpecifiers() const {
 return data().IsParsingBaseSpecifiers;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 9e82130c93609..a9f9f02651cff 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8003,6 +8003,8 @@ def err_bad_memptr_rhs : Error<
 def err_bad_memptr_lhs : Error<
   "left hand operand to %0 must be a %select{|pointer to }1class "
   "compatible with the right hand operand, but is %2">;
+def note_memptr_incomplete_until_bases : Note<
+  "this will affect the ABI of the member pointer until the bases have been 
specified">;
 def err_memptr_incomplete : Error<
   "member pointer has incomplete base type %0">;
 def warn_exception_caught_by_earlier_handler : Warning<
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 75c441293d62e..7f20a47e6a054 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -474,10 +474,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const 
*Bases,
   if (data().IsStandardLayout && NumBases > 1 && hasRepeatedBaseClass(this))
 data().IsStandardLayout = false;
 
-  if (VBases.empty()) {
-data().IsParsingBaseSpecifiers = false;
+  if (VBases.empty())
 return;
-  }
 
   // Create base specifier for any direct or indirect virtual bases.
   data().VBases = new (C) CXXBaseSpecifier[VBases.size()];
@@ -488,8 +486,6 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const 
*Bases,
   addedClassSubobject(Type->getAsCXXRecordDecl());
 data().getVBases()[I] = *VBases[I];
   }
-
-  data().IsParsingBaseSpecifiers = false;
 }
 
 unsigned CXXRecordDecl::getODRHash() const {
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 65ddebca49bc6..a28503b5b4de4 100644
--- a/clang/lib/Parse/ParseDecl

[clang] [Clang] Fix Microsoft ABI inheritance model when member pointer is used in a base specifier (PR #91990)

2024-07-06 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/91990

>From 5dc9193af0d98335a87e93ad70d945dbc0ffce79 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Mon, 13 May 2024 16:59:06 +0100
Subject: [PATCH 1/5] [Clang] Fix Microsoft ABI inheritance model when member
 pointer is used in a base specifier

Fix CXXRecordDecl::isParsingBaseSpecifiers so that it is true while parsing 
base specifiers instead of directly after they have been parsed.

-fcomplete-member-pointers now issues a diagnostic when a member pointer is 
used in a base specifier.

-fcomplete-member-pointers has also been relaxed to not issue a diagnostic for 
incomplete classes with an explicit __{single|multiple|virtual}_inheritance 
attribute, whose completeness would not affect the representation of 
pointer-to-member objects.
---
 clang/docs/ReleaseNotes.rst   |  4 +++
 clang/include/clang/AST/DeclCXX.h |  7 +++--
 .../clang/Basic/DiagnosticSemaKinds.td|  2 ++
 clang/lib/AST/DeclCXX.cpp |  6 +
 clang/lib/Parse/ParseDeclCXX.cpp  | 24 +
 clang/lib/Sema/SemaDeclCXX.cpp|  3 ---
 clang/lib/Sema/SemaType.cpp   | 27 ---
 .../test/SemaCXX/complete-member-pointers.cpp | 24 -
 clang/test/SemaCXX/member-pointer-ms.cpp  |  8 ++
 9 files changed, 85 insertions(+), 20 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 4702b8c10cdbb..054332c2cee4e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -79,6 +79,10 @@ ABI Changes in This Version
 - Fixed Microsoft calling convention when returning classes that have a deleted
   copy assignment operator. Such a class should be returned indirectly.
 
+- Fixed Microsoft layout of pointer-to-members of classes when the layout is 
needed
+  directly or indirectly by the base classes of a class. These should use the 
most
+  general unspecified inheritance layout. Also affects 
-fcomplete-member-pointers.
+
 AST Dumping Potentially Breaking Changes
 
 
diff --git a/clang/include/clang/AST/DeclCXX.h 
b/clang/include/clang/AST/DeclCXX.h
index fb52ac804849d..81669b1f606b3 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -297,7 +297,8 @@ class CXXRecordDecl : public RecordDecl {
 LLVM_PREFERRED_TYPE(bool)
 unsigned IsLambda : 1;
 
-/// Whether we are currently parsing base specifiers.
+/// Whether we are currently parsing base specifiers; the
+/// colon has been consumed but the beginning left brace hasn't.
 LLVM_PREFERRED_TYPE(bool)
 unsigned IsParsingBaseSpecifiers : 1;
 
@@ -598,7 +599,9 @@ class CXXRecordDecl : public RecordDecl {
 return !hasDefinition() || !isDynamicClass() || hasAnyDependentBases();
   }
 
-  void setIsParsingBaseSpecifiers() { data().IsParsingBaseSpecifiers = true; }
+  void setIsParsingBaseSpecifiers(bool to = true) {
+data().IsParsingBaseSpecifiers = to;
+  }
 
   bool isParsingBaseSpecifiers() const {
 return data().IsParsingBaseSpecifiers;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 9e82130c93609..a9f9f02651cff 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8003,6 +8003,8 @@ def err_bad_memptr_rhs : Error<
 def err_bad_memptr_lhs : Error<
   "left hand operand to %0 must be a %select{|pointer to }1class "
   "compatible with the right hand operand, but is %2">;
+def note_memptr_incomplete_until_bases : Note<
+  "this will affect the ABI of the member pointer until the bases have been 
specified">;
 def err_memptr_incomplete : Error<
   "member pointer has incomplete base type %0">;
 def warn_exception_caught_by_earlier_handler : Warning<
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 75c441293d62e..7f20a47e6a054 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -474,10 +474,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const 
*Bases,
   if (data().IsStandardLayout && NumBases > 1 && hasRepeatedBaseClass(this))
 data().IsStandardLayout = false;
 
-  if (VBases.empty()) {
-data().IsParsingBaseSpecifiers = false;
+  if (VBases.empty())
 return;
-  }
 
   // Create base specifier for any direct or indirect virtual bases.
   data().VBases = new (C) CXXBaseSpecifier[VBases.size()];
@@ -488,8 +486,6 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const 
*Bases,
   addedClassSubobject(Type->getAsCXXRecordDecl());
 data().getVBases()[I] = *VBases[I];
   }
-
-  data().IsParsingBaseSpecifiers = false;
 }
 
 unsigned CXXRecordDecl::getODRHash() const {
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 65ddebca49bc6..a28503b5b4de4 100644
--- a/clang/lib/Parse/ParseDecl

[clang] [Clang] Fix Microsoft ABI inheritance model when member pointer is used in a base specifier (PR #91990)

2024-07-06 Thread Mital Ashok via cfe-commits

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


[clang] [Clang] [C23] Implement N2653: u8 strings are char8_t[] (PR #97208)

2024-07-06 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/97208

>From ef0072d1fc9b14f7ee657fa95f44a686b78b525a Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 30 Jun 2024 12:07:54 +0100
Subject: [PATCH 1/6] [Clang] [C23] Implement N2653: u8 strings are char8_t[]

---
 clang/docs/ReleaseNotes.rst   |  6 
 .../clang/Basic/DiagnosticSemaKinds.td|  5 +++-
 clang/lib/Frontend/InitPreprocessor.cpp   |  6 ++--
 clang/lib/Headers/stdatomic.h |  5 
 clang/lib/Sema/SemaExpr.cpp   | 23 ++-
 clang/test/C/C2x/n2653.c  | 29 +++
 clang/www/c_status.html   |  2 +-
 7 files changed, 65 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/C/C2x/n2653.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c720e47dbe35b..e51be81d8b11a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -337,6 +337,12 @@ C23 Feature Support
 - Properly promote bit-fields of bit-precise integer types to the field's type
   rather than to ``int``. #GH87641
 
+- Compiler support for `N2653 char8_t: A type for UTF-8 characters and strings`
+  `_: ``u8`` string
+  literals are now of type ``char8_t[N]`` in C23 and expose
+  ``__CLANG_ATOMIC_CHAR8_T_LOCK_FREE``/``__GCC_ATOMIC_CHAR8_T_LOCK_FREE`` to
+  implement the corresponding macro in .
+
 Non-comprehensive list of changes in this release
 -
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5dc36c594bcb7..6a00b92df1c36 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7252,7 +7252,10 @@ def err_array_init_utf8_string_into_char : Error<
 def warn_cxx20_compat_utf8_string : Warning<
   "type of UTF-8 string literal will change from array of const char to "
   "array of const char8_t in C++20">, InGroup, DefaultIgnore;
-def note_cxx20_compat_utf8_string_remove_u8 : Note<
+def warn_c23_compat_utf8_string : Warning<
+  "type of UTF-8 string literal will change from array of char to "
+  "array of char8_t in C23">, InGroup, DefaultIgnore;
+def note_cxx20_c23_compat_utf8_string_remove_u8 : Note<
   "remove 'u8' prefix to avoid a change of behavior; "
   "Clang encodes unprefixed narrow string literals as UTF-8">;
 def err_array_init_different_type : Error<
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp 
b/clang/lib/Frontend/InitPreprocessor.cpp
index 55ec460064830..6270c37342bcf 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -1342,8 +1342,10 @@ static void InitializePredefinedMacros(const TargetInfo 
&TI,
   getLockFreeValue(TI.get##Type##Width(), TI));
 DEFINE_LOCK_FREE_MACRO(BOOL, Bool);
 DEFINE_LOCK_FREE_MACRO(CHAR, Char);
-if (LangOpts.Char8)
-  DEFINE_LOCK_FREE_MACRO(CHAR8_T, Char); // Treat char8_t like char.
+// char8_t has the same representation / width as unsigned
+// char in C++ and is a typedef for unsigned char in C23
+if (LangOpts.Char8 || LangOpts.C23)
+  DEFINE_LOCK_FREE_MACRO(CHAR8_T, Char);
 DEFINE_LOCK_FREE_MACRO(CHAR16_T, Char16);
 DEFINE_LOCK_FREE_MACRO(CHAR32_T, Char32);
 DEFINE_LOCK_FREE_MACRO(WCHAR_T, WChar);
diff --git a/clang/lib/Headers/stdatomic.h b/clang/lib/Headers/stdatomic.h
index 9c103d98af8c5..c33cd8083525c 100644
--- a/clang/lib/Headers/stdatomic.h
+++ b/clang/lib/Headers/stdatomic.h
@@ -35,6 +35,10 @@ extern "C" {
 
 #define ATOMIC_BOOL_LOCK_FREE   __CLANG_ATOMIC_BOOL_LOCK_FREE
 #define ATOMIC_CHAR_LOCK_FREE   __CLANG_ATOMIC_CHAR_LOCK_FREE
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) ||  
\
+defined(__cplusplus)
+#define ATOMIC_CHAR8_T_LOCK_FREE__CLANG_ATOMIC_CHAR8_T_LOCK_FREE
+#endif
 #define ATOMIC_CHAR16_T_LOCK_FREE   __CLANG_ATOMIC_CHAR16_T_LOCK_FREE
 #define ATOMIC_CHAR32_T_LOCK_FREE   __CLANG_ATOMIC_CHAR32_T_LOCK_FREE
 #define ATOMIC_WCHAR_T_LOCK_FREE__CLANG_ATOMIC_WCHAR_T_LOCK_FREE
@@ -104,6 +108,7 @@ typedef _Atomic(long)   atomic_long;
 typedef _Atomic(unsigned long)  atomic_ulong;
 typedef _Atomic(long long)  atomic_llong;
 typedef _Atomic(unsigned long long) atomic_ullong;
+typedef _Atomic(unsigned char)  atomic_char8_t;
 typedef _Atomic(uint_least16_t) atomic_char16_t;
 typedef _Atomic(uint_least32_t) atomic_char32_t;
 typedef _Atomic(wchar_t)atomic_wchar_t;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index db44cfe1288b6..a1b060f7f1510 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2082,6 +2082,8 @@ Sema::ActOnStringLiteral(ArrayRef StringToks, 
Scope *UDLScope) {
   } else if (Literal.isUTF8()) {
 if

[clang] [libcxx] [Clang] Implement CWG2137 (list-initialization from objects of the same type) (PR #94355)

2024-07-07 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/94355

>From ac803f979f2779da35a006988d2d42cdabbad252 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sat, 22 Jul 2023 20:07:00 +0100
Subject: [PATCH 1/6] [SemaCXX] Implement CWG2137 (list-initialization from
 objects of the same type)

Differential Revision: https://reviews.llvm.org/D156032

---

This is a cherry-pick from 
https://github.com/llvm/llvm-project/pull/77768/commits/644ec10fc357f70ca8af94ae6544e9631021eb5e
---
 clang/docs/ReleaseNotes.rst   |  3 ++
 clang/lib/Sema/SemaInit.cpp   | 14 +++---
 clang/lib/Sema/SemaOverload.cpp   | 38 +++-
 clang/test/CXX/drs/cwg14xx.cpp| 10 -
 clang/test/CXX/drs/cwg21xx.cpp| 45 +++
 clang/www/cxx_dr_status.html  |  2 +-
 .../pairs.pair/ctor.pair_U_V_move.pass.cpp| 21 -
 7 files changed, 104 insertions(+), 29 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 99580c0d28a4fd..818fa160ef9848 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -254,6 +254,9 @@ Resolutions to C++ Defect Reports
 - Clang now requires a template argument list after a template keyword.
   (`CWG96: Syntactic disambiguation using the template keyword 
`_).
 
+- Implemented `CWG2137 `_ which allows
+  list-initialization from objects of the same type.
+
 C Language Changes
 --
 
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 79bdc8e9f87838..6aa0ebeeaa11fc 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -4231,7 +4231,7 @@ static OverloadingResult ResolveConstructorOverload(
 /// \param IsListInit Is this list-initialization?
 /// \param IsInitListCopy Is this non-list-initialization resulting from a
 ///   list-initialization from {x} where x is the same
-///   type as the entity?
+///   aggregate type as the entity?
 static void TryConstructorInitialization(Sema &S,
  const InitializedEntity &Entity,
  const InitializationKind &Kind,
@@ -4271,8 +4271,8 @@ static void TryConstructorInitialization(Sema &S,
   // ObjC++: Lambda captured by the block in the lambda to block conversion
   // should avoid copy elision.
   if (S.getLangOpts().CPlusPlus17 && !RequireActualConstructor &&
-  UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isPRValue() &&
-  S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) 
{
+  Args.size() == 1 && Args[0]->isPRValue() &&
+  S.Context.hasSameUnqualifiedType(Args[0]->getType(), DestType)) {
 // Convert qualifications if necessary.
 Sequence.AddQualificationConversionStep(DestType, VK_PRValue);
 if (ILE)
@@ -4603,9 +4603,9 @@ static void TryListInitialization(Sema &S,
 return;
   }
 
-  // C++11 [dcl.init.list]p3, per DR1467:
-  // - If T is a class type and the initializer list has a single element of
-  //   type cv U, where U is T or a class derived from T, the object is
+  // C++11 [dcl.init.list]p3, per DR1467 and DR2137:
+  // - If T is an aggregate class and the initializer list has a single element
+  //   of type cv U, where U is T or a class derived from T, the object is
   //   initialized from that element (by copy-initialization for
   //   copy-list-initialization, or by direct-initialization for
   //   direct-list-initialization).
@@ -4616,7 +4616,7 @@ static void TryListInitialization(Sema &S,
   // - Otherwise, if T is an aggregate, [...] (continue below).
   if (S.getLangOpts().CPlusPlus11 && InitList->getNumInits() == 1 &&
   !IsDesignatedInit) {
-if (DestType->isRecordType()) {
+if (DestType->isRecordType() && DestType->isAggregateType()) {
   QualType InitType = InitList->getInit(0)->getType();
   if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
   S.IsDerivedFrom(InitList->getBeginLoc(), InitType, DestType)) {
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 6c4ce1022ae274..b6d6d9d1ef3af3 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1628,19 +1628,37 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType 
ToType,
 //   called for those cases.
 if (CXXConstructorDecl *Constructor
   = dyn_cast(ICS.UserDefined.ConversionFunction)) {
-  QualType FromCanon
-= S.Context.getCanonicalType(From->getType().getUnqualifiedType());
+  QualType FromType;
+  SourceLocation FromLoc;
+  // C++11 [over.ics.list]p6, per DR2137:
+  // C++17 [over.ics.list]p6:
+  //   If C is not an initializer-list constructor and the initializer list
+  //   has a single element of type cv U,

[clang] [Clang] Make -fcomplete-member-pointers the same as using the Microsoft C++ ABI (PR #98010)

2024-07-08 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok created 
https://github.com/llvm/llvm-project/pull/98010

This essentially adds a new language mode `CompleteMemberPointers`. With the 
Microsoft C++ ABI, this will always be true. Otherwise, it can be enabled with 
`-fcomplete-member-pointers`, and will work the same as if the Microsoft C++ 
ABI was being used for member pointers (only during sema, not codegen).

Previously `-fcomplete-member-pointers` was also being used for 
`-fsanitize=cfi-mfcall`. It can still be used for this, but the new 
`-Wincomplete-member-pointer` will warn in a similar way without enabling a 
non-standard language mode.

Before, an MSVC triple with `-fc++-abi=itanium` would still complete base types 
of member pointers even though it wasn't needed for codegen. It can still be 
completed with `-fc++-abi=itanium -fcomplete-member-pointers`.

Also adds a new warning `-Wmicrosoft-incomplete-member-pointers`, which will 
warn if a member pointer's base type is given an unspecified inheritance. This 
only warns with `CompleteMemberPointers`. It is enabled by `-Wmost`/`-Wall`. A 
similar warning 
[C5243](https://learn.microsoft.com/en-gb/cpp/error-messages/compiler-warnings/c5243?view=msvc-170)
 exists in MSVC.


>From 0de7bd39af61eb47ee33ff991e6de18f83e005dd Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Mon, 8 Jul 2024 10:36:35 +0100
Subject: [PATCH] [Clang] Make -fcomplete-member-pointers the same as using the
 Microsoft C++ ABI

---
 clang/docs/ControlFlowIntegrity.rst   |  6 +-
 clang/include/clang/Basic/DiagnosticGroups.td |  5 +-
 .../clang/Basic/DiagnosticSemaKinds.td|  9 +-
 clang/include/clang/Basic/TargetCXXABI.h  |  5 +
 clang/include/clang/Sema/Sema.h   | 14 +++
 clang/lib/AST/Type.cpp|  2 +-
 clang/lib/Driver/ToolChains/Clang.cpp |  7 +-
 clang/lib/Frontend/CompilerInvocation.cpp |  9 +-
 clang/lib/Sema/SemaCast.cpp   | 14 +--
 clang/lib/Sema/SemaExpr.cpp   | 10 +-
 clang/lib/Sema/SemaExprCXX.cpp|  6 +-
 clang/lib/Sema/SemaOverload.cpp   |  3 +-
 clang/lib/Sema/SemaType.cpp   | 99 ++-
 clang/test/Misc/warning-wall.c|  1 +
 .../test/SemaCXX/complete-member-pointers.cpp | 39 +++-
 15 files changed, 149 insertions(+), 80 deletions(-)

diff --git a/clang/docs/ControlFlowIntegrity.rst 
b/clang/docs/ControlFlowIntegrity.rst
index 7de805e2154db..9b1086f4bbb8d 100644
--- a/clang/docs/ControlFlowIntegrity.rst
+++ b/clang/docs/ControlFlowIntegrity.rst
@@ -351,9 +351,9 @@ The compiler will only emit a full CFI check if the member 
function pointer's
 base type is complete. This is because the complete definition of the base
 type contains information that is necessary to correctly compile the CFI
 check. To ensure that the compiler always emits a full CFI check, it is
-recommended to also pass the flag ``-fcomplete-member-pointers``, which
-enables a non-conforming language extension that requires member pointer
-base types to be complete if they may be used for a call.
+recommended to enable the ``-Wincomplete-member-pointer`` warning, which
+warns if a member pointer does not have a complete base types when the
+member pointer type is specified.
 
 For this scheme to work, all translation units containing the definition
 of a virtual member function (whether inline or not), other than members
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 2241f8481484e..16ede9e2a59ac 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1040,6 +1040,8 @@ def VoidPointerDeref : DiagGroup<"void-ptr-dereference">;
 
 def FUseLdPath : DiagGroup<"fuse-ld-path">;
 
+def MicrosoftIncompleteMemberPointer : 
DiagGroup<"microsoft-incomplete-member-pointer">;
+
 def Move : DiagGroup<"move", [
 PessimizingMove,
 RedundantMove,
@@ -1102,7 +1104,8 @@ def Most : DiagGroup<"most", [
 PrivateExtern,
 SelTypeCast,
 ExternCCompat,
-UserDefinedWarnings
+UserDefinedWarnings,
+MicrosoftIncompleteMemberPointer
  ]>;
 
 // Thread Safety warnings
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 44fd51ec9abc9..79dc6b15fb704 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8082,8 +8082,13 @@ def err_bad_memptr_rhs : Error<
 def err_bad_memptr_lhs : Error<
   "left hand operand to %0 must be a %select{|pointer to }1class "
   "compatible with the right hand operand, but is %2">;
-def err_memptr_incomplete : Error<
-  "member pointer has incomplete base type %0">;
+def warn_memptr_incomplete : Warning<
+  "member pointer has incomplete base type %0">, 
InGroup>, DefaultIgnore;
+def warn_memptr_incomplete_ms : Warning<
+  "this usage of a member pointer with an incompl

[clang] [Clang] Make -fcomplete-member-pointers the same as using the Microsoft C++ ABI (PR #98010)

2024-07-08 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

TODO:

 - Tests for `-Wincomplete-member-pointer`
 - Possibly do something else about `-fsanitize=cfi-mfcall`. 
`-Wincomplete-member-pointer` is too broad, for the sanitizer we only care 
about a call to a pointer to member function. The warning could also be emitted 
here: 
https://github.com/llvm/llvm-project/blob/1b8ab2f08998d3220e5d95003d47bb3d7cac966b/clang/lib/CodeGen/ItaniumCXXABI.cpp#L800
 - It's weird that `-fcomplete-member-pointers` enables an error. Possibly 
deprecate `-fcomplete-member-pointers` and have it be an alias for 
`-fmicrosoft-complete-member-pointers 
-Werror=microsoft-incomplete-member-pointer` (where 
`-fmicrosoft-complete-member-pointers` is a new option).
 - Release note
 - Maybe reword the warning with `-fcomplete-member-pointers` is used with a 
non-Microsoft ABI. It's not actually an ODR violation then, and the 
`__single_inheritance` etc. keywords might not be available.

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


[clang] [Clang] Make -fcomplete-member-pointers the same as using the Microsoft C++ ABI (PR #98010)

2024-07-08 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/98010

>From 7cc8f4c8c4e39db82ff8f7cb7164a94abf6b2029 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Mon, 8 Jul 2024 10:36:35 +0100
Subject: [PATCH] [Clang] Make -fcomplete-member-pointers the same as using the
 Microsoft C++ ABI

---
 clang/docs/ControlFlowIntegrity.rst   |   6 +-
 clang/include/clang/Basic/DiagnosticGroups.td |   5 +-
 .../clang/Basic/DiagnosticSemaKinds.td|   9 +-
 clang/include/clang/Basic/TargetCXXABI.h  |   5 +
 clang/include/clang/Sema/Sema.h   |  17 +++
 clang/lib/AST/Type.cpp|   2 +-
 clang/lib/Driver/ToolChains/Clang.cpp |   8 +-
 clang/lib/Frontend/CompilerInvocation.cpp |   9 +-
 clang/lib/Sema/SemaCast.cpp   |  14 +--
 clang/lib/Sema/SemaExpr.cpp   |  10 +-
 clang/lib/Sema/SemaExprCXX.cpp|   6 +-
 clang/lib/Sema/SemaOverload.cpp   |   3 +-
 clang/lib/Sema/SemaType.cpp   | 108 +++---
 clang/test/Misc/warning-wall.c|   1 +
 .../test/SemaCXX/complete-member-pointers.cpp |  39 ++-
 15 files changed, 162 insertions(+), 80 deletions(-)

diff --git a/clang/docs/ControlFlowIntegrity.rst 
b/clang/docs/ControlFlowIntegrity.rst
index 7de805e2154db..9b1086f4bbb8d 100644
--- a/clang/docs/ControlFlowIntegrity.rst
+++ b/clang/docs/ControlFlowIntegrity.rst
@@ -351,9 +351,9 @@ The compiler will only emit a full CFI check if the member 
function pointer's
 base type is complete. This is because the complete definition of the base
 type contains information that is necessary to correctly compile the CFI
 check. To ensure that the compiler always emits a full CFI check, it is
-recommended to also pass the flag ``-fcomplete-member-pointers``, which
-enables a non-conforming language extension that requires member pointer
-base types to be complete if they may be used for a call.
+recommended to enable the ``-Wincomplete-member-pointer`` warning, which
+warns if a member pointer does not have a complete base types when the
+member pointer type is specified.
 
 For this scheme to work, all translation units containing the definition
 of a virtual member function (whether inline or not), other than members
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 2241f8481484e..16ede9e2a59ac 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1040,6 +1040,8 @@ def VoidPointerDeref : DiagGroup<"void-ptr-dereference">;
 
 def FUseLdPath : DiagGroup<"fuse-ld-path">;
 
+def MicrosoftIncompleteMemberPointer : 
DiagGroup<"microsoft-incomplete-member-pointer">;
+
 def Move : DiagGroup<"move", [
 PessimizingMove,
 RedundantMove,
@@ -1102,7 +1104,8 @@ def Most : DiagGroup<"most", [
 PrivateExtern,
 SelTypeCast,
 ExternCCompat,
-UserDefinedWarnings
+UserDefinedWarnings,
+MicrosoftIncompleteMemberPointer
  ]>;
 
 // Thread Safety warnings
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 44fd51ec9abc9..79dc6b15fb704 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8082,8 +8082,13 @@ def err_bad_memptr_rhs : Error<
 def err_bad_memptr_lhs : Error<
   "left hand operand to %0 must be a %select{|pointer to }1class "
   "compatible with the right hand operand, but is %2">;
-def err_memptr_incomplete : Error<
-  "member pointer has incomplete base type %0">;
+def warn_memptr_incomplete : Warning<
+  "member pointer has incomplete base type %0">, 
InGroup>, DefaultIgnore;
+def warn_memptr_incomplete_ms : Warning<
+  "this usage of a member pointer with an incomplete base type %0 may cause 
ODR violations">, InGroup, DefaultIgnore;
+def note_memptr_incomplete_specify_inheritance : Note<"consider specifying the 
inheritance model">;
+def note_memptr_incomplete_until_bases : Note<
+  "this will affect the ABI of the member pointer until the bases have been 
specified">;
 def warn_exception_caught_by_earlier_handler : Warning<
   "exception of type %0 will be caught by earlier handler">,
   InGroup;
diff --git a/clang/include/clang/Basic/TargetCXXABI.h 
b/clang/include/clang/Basic/TargetCXXABI.h
index d204452afbf4b..d88846839b20c 100644
--- a/clang/include/clang/Basic/TargetCXXABI.h
+++ b/clang/include/clang/Basic/TargetCXXABI.h
@@ -68,6 +68,11 @@ class TargetCXXABI {
 return T.isOSFuchsia();
   }
 
+  // Return true if this target uses the Microsoft C++ ABI by default.
+  static bool defaultABIIsMicrosoft(const llvm::Triple &T) {
+return T.isKnownWindowsMSVCEnvironment();
+  }
+
   /// A bogus initialization of the platform ABI.
   TargetCXXABI() : TheKind(GenericItanium) {}
 
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 75a80540

[clang] [Clang] Fix Microsoft ABI inheritance model when member pointer is used in a base specifier (PR #91990)

2024-07-08 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

> Will that include fixing clang incorrectly warning when an inheritance model 
> is explicitly specified?

Yes, I have a WIP of it here #98010 where that doesn't get a warning 
(https://github.com/llvm/llvm-project/pull/98010/files#diff-bec1ae40e5793adbd61e7a9dc41a4715a06e27888a384c0752bb6b4b09a1075fR20-R21)

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


[clang] [clang-tools-extra] [Clang] Make -fcomplete-member-pointers the same as using the Microsoft C++ ABI (PR #98010)

2024-07-08 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/98010

>From 5163153a122f705c6ed25a372bec6868aa42d0b5 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Mon, 8 Jul 2024 10:36:35 +0100
Subject: [PATCH] [Clang] Make -fcomplete-member-pointers the same as using the
 Microsoft C++ ABI

---
 clang-tools-extra/clangd/IncludeFixer.cpp |   3 +-
 clang/docs/ControlFlowIntegrity.rst   |   6 +-
 clang/include/clang/Basic/DiagnosticGroups.td |   5 +-
 .../clang/Basic/DiagnosticSemaKinds.td|   9 +-
 clang/include/clang/Basic/TargetCXXABI.h  |   5 +
 clang/include/clang/Sema/Sema.h   |  17 +++
 clang/lib/AST/Type.cpp|   2 +-
 clang/lib/Driver/ToolChains/Clang.cpp |   8 +-
 clang/lib/Frontend/CompilerInvocation.cpp |   9 +-
 clang/lib/Sema/SemaCast.cpp   |  14 +--
 clang/lib/Sema/SemaExpr.cpp   |  10 +-
 clang/lib/Sema/SemaExprCXX.cpp|   6 +-
 clang/lib/Sema/SemaOverload.cpp   |   3 +-
 clang/lib/Sema/SemaType.cpp   | 108 +++---
 clang/test/Misc/warning-wall.c|   1 +
 .../test/SemaCXX/complete-member-pointers.cpp |  39 ++-
 16 files changed, 164 insertions(+), 81 deletions(-)

diff --git a/clang-tools-extra/clangd/IncludeFixer.cpp 
b/clang-tools-extra/clangd/IncludeFixer.cpp
index fadd1105691fc..ec2a744b9800b 100644
--- a/clang-tools-extra/clangd/IncludeFixer.cpp
+++ b/clang-tools-extra/clangd/IncludeFixer.cpp
@@ -122,7 +122,8 @@ std::vector IncludeFixer::fix(DiagnosticsEngine::Level 
DiagLevel,
   case diag::err_lambda_incomplete_result:
   //case diag::err_matrix_incomplete_index:
   //case diag::err_matrix_separate_incomplete_index:
-  case diag::err_memptr_incomplete:
+  case diag::warn_memptr_incomplete:
+  case diag::warn_memptr_incomplete_ms:
   case diag::err_new_incomplete_or_sizeless_type:
   case diag::err_objc_incomplete_boxed_expression_type:
   case diag::err_objc_index_incomplete_class_type:
diff --git a/clang/docs/ControlFlowIntegrity.rst 
b/clang/docs/ControlFlowIntegrity.rst
index 7de805e2154db..9b1086f4bbb8d 100644
--- a/clang/docs/ControlFlowIntegrity.rst
+++ b/clang/docs/ControlFlowIntegrity.rst
@@ -351,9 +351,9 @@ The compiler will only emit a full CFI check if the member 
function pointer's
 base type is complete. This is because the complete definition of the base
 type contains information that is necessary to correctly compile the CFI
 check. To ensure that the compiler always emits a full CFI check, it is
-recommended to also pass the flag ``-fcomplete-member-pointers``, which
-enables a non-conforming language extension that requires member pointer
-base types to be complete if they may be used for a call.
+recommended to enable the ``-Wincomplete-member-pointer`` warning, which
+warns if a member pointer does not have a complete base types when the
+member pointer type is specified.
 
 For this scheme to work, all translation units containing the definition
 of a virtual member function (whether inline or not), other than members
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 2241f8481484e..16ede9e2a59ac 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1040,6 +1040,8 @@ def VoidPointerDeref : DiagGroup<"void-ptr-dereference">;
 
 def FUseLdPath : DiagGroup<"fuse-ld-path">;
 
+def MicrosoftIncompleteMemberPointer : 
DiagGroup<"microsoft-incomplete-member-pointer">;
+
 def Move : DiagGroup<"move", [
 PessimizingMove,
 RedundantMove,
@@ -1102,7 +1104,8 @@ def Most : DiagGroup<"most", [
 PrivateExtern,
 SelTypeCast,
 ExternCCompat,
-UserDefinedWarnings
+UserDefinedWarnings,
+MicrosoftIncompleteMemberPointer
  ]>;
 
 // Thread Safety warnings
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 44fd51ec9abc9..79dc6b15fb704 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8082,8 +8082,13 @@ def err_bad_memptr_rhs : Error<
 def err_bad_memptr_lhs : Error<
   "left hand operand to %0 must be a %select{|pointer to }1class "
   "compatible with the right hand operand, but is %2">;
-def err_memptr_incomplete : Error<
-  "member pointer has incomplete base type %0">;
+def warn_memptr_incomplete : Warning<
+  "member pointer has incomplete base type %0">, 
InGroup>, DefaultIgnore;
+def warn_memptr_incomplete_ms : Warning<
+  "this usage of a member pointer with an incomplete base type %0 may cause 
ODR violations">, InGroup, DefaultIgnore;
+def note_memptr_incomplete_specify_inheritance : Note<"consider specifying the 
inheritance model">;
+def note_memptr_incomplete_until_bases : Note<
+  "this will affect the ABI of the member pointer until the bases have been 
specified">;
 def warn_exception_ca

[clang] [llvm] [Clang] Fix definition of layout-compatible to ignore empty classes (PR #92103)

2024-07-08 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

Ping

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


[clang] [Clang] CWG2749: relational operators involving pointers to void (PR #93046)

2024-09-05 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/93046

>From e1172958f43af7490b5b6e3752a9070265ad17ca Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Wed, 22 May 2024 16:01:13 +0100
Subject: [PATCH 1/4] [Clang] CWG2749: relational operators involving pointers
 to void

https://cplusplus.github.io/CWG/issues/2749.html

This DR's effects are backported to C++98.

Does not affect C where integral constant expressions cannot involve pointers.
---
 clang/docs/ReleaseNotes.rst   |  4 ++
 .../include/clang/Basic/DiagnosticASTKinds.td |  2 -
 clang/lib/AST/ExprConstant.cpp| 10 
 clang/test/AST/Interp/literals.cpp|  8 +---
 clang/test/CXX/drs/cwg27xx.cpp| 46 ++-
 clang/test/CXX/expr/expr.const/p2-0x.cpp  | 11 +++--
 clang/www/cxx_dr_status.html  |  2 +-
 7 files changed, 58 insertions(+), 25 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2899bc5ed35ad0..4d9313f4c7ca57 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -237,6 +237,10 @@ Resolutions to C++ Defect Reports
 - P0522 implementation is enabled by default in all language versions, and
   provisional wording for CWG2398 is implemented.
 
+- Clang now allows comparing unequal object pointers that have been cast to 
``void *``
+  in constant expressions. These comparisons always worked in non-constant 
expressions.
+  (`CWG2749: Treatment of "pointer to void" for relational comparisons 
`_).
+
 C Language Changes
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td 
b/clang/include/clang/Basic/DiagnosticASTKinds.td
index a024f9b2a9f8c0..b7aae9395e6357 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -148,8 +148,6 @@ def note_constexpr_var_init_weak : Note<
 def note_constexpr_typeid_polymorphic : Note<
   "typeid applied to expression of polymorphic type %0 is "
   "not allowed in a constant expression in C++ standards before C++20">;
-def note_constexpr_void_comparison : Note<
-  "comparison between unequal pointers to void has unspecified result">;
 def note_constexpr_temporary_here : Note<"temporary created here">;
 def note_constexpr_dynamic_alloc_here : Note<"heap allocation performed here">;
 def note_constexpr_conditional_never_const : Note<
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f1aa19e4409e15..d5a47a071e2cd7 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -13627,16 +13627,6 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const 
BinaryOperator *E,
 SubobjectDesignator &LHSDesignator = LHSValue.getLValueDesignator();
 SubobjectDesignator &RHSDesignator = RHSValue.getLValueDesignator();
 
-// C++11 [expr.rel]p3:
-//   Pointers to void (after pointer conversions) can be compared, with a
-//   result defined as follows: If both pointers represent the same
-//   address or are both the null pointer value, the result is true if the
-//   operator is <= or >= and false otherwise; otherwise the result is
-//   unspecified.
-// We interpret this as applying to pointers to *cv* void.
-if (LHSTy->isVoidPointerType() && LHSOffset != RHSOffset && IsRelational)
-  Info.CCEDiag(E, diag::note_constexpr_void_comparison);
-
 // C++11 [expr.rel]p2:
 // - If two pointers point to non-static data members of the same object,
 //   or to subobjects or array elements fo such members, recursively, the
diff --git a/clang/test/AST/Interp/literals.cpp 
b/clang/test/AST/Interp/literals.cpp
index c160be06dd241c..ae7942aca39e63 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -191,12 +191,8 @@ namespace PointerComparison {
   constexpr bool v3 = null == pv; // ok
   constexpr bool v4 = qv == pv; // ok
 
-  /// FIXME: These two are rejected by the current interpreter, but
-  ///   accepted by GCC.
-  constexpr bool v5 = qv >= pv; // ref-error {{constant expression}} \
-// ref-note {{unequal pointers to void}}
-  constexpr bool v8 = qv > (void*)&s.a; // ref-error {{constant expression}} \
-// ref-note {{unequal pointers to 
void}}
+  constexpr bool v5 = qv >= pv;
+  constexpr bool v8 = qv > (void*)&s.a;
   constexpr bool v6 = qv > null; // both-error {{must be initialized by a 
constant expression}} \
  // both-note {{comparison between '&s.b' and 
'nullptr' has unspecified value}}
 
diff --git a/clang/test/CXX/drs/cwg27xx.cpp b/clang/test/CXX/drs/cwg27xx.cpp
index 53ddd566b7dbf9..f0c3c6dbdf97b0 100644
--- a/clang/test/CXX/drs/cwg27xx.cpp
+++ b/clang/test/CXX/drs/cwg27xx.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++98 -verify

[clang] [Clang] CWG2749: relational operators involving pointers to void (PR #93046)

2024-09-05 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

@cor3ntin Done!

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


[clang] [Clang] CWG2749: relational operators involving pointers to void (PR #93046)

2024-09-05 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/93046

>From e1172958f43af7490b5b6e3752a9070265ad17ca Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Wed, 22 May 2024 16:01:13 +0100
Subject: [PATCH 1/5] [Clang] CWG2749: relational operators involving pointers
 to void

https://cplusplus.github.io/CWG/issues/2749.html

This DR's effects are backported to C++98.

Does not affect C where integral constant expressions cannot involve pointers.
---
 clang/docs/ReleaseNotes.rst   |  4 ++
 .../include/clang/Basic/DiagnosticASTKinds.td |  2 -
 clang/lib/AST/ExprConstant.cpp| 10 
 clang/test/AST/Interp/literals.cpp|  8 +---
 clang/test/CXX/drs/cwg27xx.cpp| 46 ++-
 clang/test/CXX/expr/expr.const/p2-0x.cpp  | 11 +++--
 clang/www/cxx_dr_status.html  |  2 +-
 7 files changed, 58 insertions(+), 25 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2899bc5ed35ad0..4d9313f4c7ca57 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -237,6 +237,10 @@ Resolutions to C++ Defect Reports
 - P0522 implementation is enabled by default in all language versions, and
   provisional wording for CWG2398 is implemented.
 
+- Clang now allows comparing unequal object pointers that have been cast to 
``void *``
+  in constant expressions. These comparisons always worked in non-constant 
expressions.
+  (`CWG2749: Treatment of "pointer to void" for relational comparisons 
`_).
+
 C Language Changes
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td 
b/clang/include/clang/Basic/DiagnosticASTKinds.td
index a024f9b2a9f8c0..b7aae9395e6357 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -148,8 +148,6 @@ def note_constexpr_var_init_weak : Note<
 def note_constexpr_typeid_polymorphic : Note<
   "typeid applied to expression of polymorphic type %0 is "
   "not allowed in a constant expression in C++ standards before C++20">;
-def note_constexpr_void_comparison : Note<
-  "comparison between unequal pointers to void has unspecified result">;
 def note_constexpr_temporary_here : Note<"temporary created here">;
 def note_constexpr_dynamic_alloc_here : Note<"heap allocation performed here">;
 def note_constexpr_conditional_never_const : Note<
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f1aa19e4409e15..d5a47a071e2cd7 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -13627,16 +13627,6 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const 
BinaryOperator *E,
 SubobjectDesignator &LHSDesignator = LHSValue.getLValueDesignator();
 SubobjectDesignator &RHSDesignator = RHSValue.getLValueDesignator();
 
-// C++11 [expr.rel]p3:
-//   Pointers to void (after pointer conversions) can be compared, with a
-//   result defined as follows: If both pointers represent the same
-//   address or are both the null pointer value, the result is true if the
-//   operator is <= or >= and false otherwise; otherwise the result is
-//   unspecified.
-// We interpret this as applying to pointers to *cv* void.
-if (LHSTy->isVoidPointerType() && LHSOffset != RHSOffset && IsRelational)
-  Info.CCEDiag(E, diag::note_constexpr_void_comparison);
-
 // C++11 [expr.rel]p2:
 // - If two pointers point to non-static data members of the same object,
 //   or to subobjects or array elements fo such members, recursively, the
diff --git a/clang/test/AST/Interp/literals.cpp 
b/clang/test/AST/Interp/literals.cpp
index c160be06dd241c..ae7942aca39e63 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -191,12 +191,8 @@ namespace PointerComparison {
   constexpr bool v3 = null == pv; // ok
   constexpr bool v4 = qv == pv; // ok
 
-  /// FIXME: These two are rejected by the current interpreter, but
-  ///   accepted by GCC.
-  constexpr bool v5 = qv >= pv; // ref-error {{constant expression}} \
-// ref-note {{unequal pointers to void}}
-  constexpr bool v8 = qv > (void*)&s.a; // ref-error {{constant expression}} \
-// ref-note {{unequal pointers to 
void}}
+  constexpr bool v5 = qv >= pv;
+  constexpr bool v8 = qv > (void*)&s.a;
   constexpr bool v6 = qv > null; // both-error {{must be initialized by a 
constant expression}} \
  // both-note {{comparison between '&s.b' and 
'nullptr' has unspecified value}}
 
diff --git a/clang/test/CXX/drs/cwg27xx.cpp b/clang/test/CXX/drs/cwg27xx.cpp
index 53ddd566b7dbf9..f0c3c6dbdf97b0 100644
--- a/clang/test/CXX/drs/cwg27xx.cpp
+++ b/clang/test/CXX/drs/cwg27xx.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++98 -verify

[clang] [Clang] Fix Microsoft ABI inheritance model when member pointer is used in a base specifier (PR #91990)

2024-09-06 Thread Mital Ashok via cfe-commits


@@ -13,3 +15,18 @@ template 
 struct S3 {
   int T::*foo;
 };
+
+template struct Base {};
+struct
+S5 // #S5
+:
+Base
+// expected-error@-1 {{member pointer has incomplete base type 'S5'}}

MitalAshok wrote:

Yes, that's just how `-fcomplete-member-pointers` works currently. It's more 
like a `-Werror=...` diagnostic

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


[clang] [Clang] Fix Microsoft ABI inheritance model when member pointer is used in a base specifier (PR #91990)

2024-09-06 Thread Mital Ashok via cfe-commits


@@ -215,6 +215,14 @@ struct NewUnspecified;
 SingleTemplate tmpl_single;
 UnspecTemplate tmpl_unspec;
 
+// Member pointers used in base specifiers force an unspecified inheritance 
model
+struct MemPtrInBase : UnspecTemplate {};

MitalAshok wrote:

I see what you mean.  
If there were two bases `struct MemPtrInBase : UnspecTemplate, SomeOtherClass {`, `UnspecTemplate` would be instantiated and completed before the token for 
`SomeOtherClass` is seen. So this is the case for Clang, but I don't see why a 
different compiler couldn't parse all the bases at once then instantiated them.

However, they need to be instantiated at least before the body of the struct is 
parsed (because the bases affect name lookup), and this is essentially the same 
time as when you are "parsing the base specifiers".  
And of course it needs to match Microsoft behaviour and assign the unspecified 
inheritance model during this time.

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


[clang] [Clang][SemaCXX] Preserve qualifiers in derived-to-base cast in defaulted comparison operators (PR #102619)

2024-08-09 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok created 
https://github.com/llvm/llvm-project/pull/102619

Fixes #102588

>From f47340974464dccae08980a1f8e78f0982169a58 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Fri, 9 Aug 2024 15:03:38 +0100
Subject: [PATCH] [Clang][SemaCXX] Preserve qualifiers in derived-to-base cast
 in defaulted comparison operators

---
 clang/docs/ReleaseNotes.rst  |  1 +
 clang/lib/Sema/SemaDeclCXX.cpp   |  9 ++--
 clang/test/SemaCXX/cxx20-default-compare.cpp | 50 
 3 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7a05ccf3184111..30bc36bd0d6cd7 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -216,6 +216,7 @@ Bug Fixes to C++ Support
 - Clang now preserves the unexpanded flag in a lambda transform used for pack 
expansion. (#GH56852), (#GH85667),
   (#GH99877).
 - Fixed a bug when diagnosing ambiguous explicit specializations of 
constrained member functions.
+- Fixed a bug where defaulted comparison operators would remove ``const`` from 
base classes. (#GH102588)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index b07e555afcaccf..a478bdb46faa05 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -8414,10 +8414,11 @@ class DefaultedComparisonSynthesizer
 if (Obj.first.isInvalid() || Obj.second.isInvalid())
   return {ExprError(), ExprError()};
 CXXCastPath Path = {Base};
-return {S.ImpCastExprToType(Obj.first.get(), Base->getType(),
-CK_DerivedToBase, VK_LValue, &Path),
-S.ImpCastExprToType(Obj.second.get(), Base->getType(),
-CK_DerivedToBase, VK_LValue, &Path)};
+const auto CastToBase = [&](Expr *E) {
+  QualType ToType = S.Context.getQualifiedType(Base->getType(), 
E->getType().getQualifiers());
+  return S.ImpCastExprToType(E, ToType, CK_DerivedToBase, VK_LValue, 
&Path);
+};
+return {CastToBase(Obj.first.get()), CastToBase(Obj.second.get())};
   }
 
   ExprPair getField(FieldDecl *Field) {
diff --git a/clang/test/SemaCXX/cxx20-default-compare.cpp 
b/clang/test/SemaCXX/cxx20-default-compare.cpp
index 7074ee885ac4a2..3e4673c31e4890 100644
--- a/clang/test/SemaCXX/cxx20-default-compare.cpp
+++ b/clang/test/SemaCXX/cxx20-default-compare.cpp
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 %s -std=c++23 -verify -Wfloat-equal
 
+#include "Inputs/std-compare.h"
+
 struct Foo {
   float val;
   bool operator==(const Foo &) const;
@@ -15,3 +17,51 @@ bool operator==(const Foo &, const Foo &) = default;  // 
expected-warning {{comp
 
 // Declare the defaulted comparison function as a non-member function. 
Arguments are passed by value.
 bool operator==(Foo, Foo) = default;  // expected-warning {{comparing floating 
point with == or != is unsafe}} expected-note {{in defaulted equality 
comparison operator for 'Foo' first required here}}
+
+namespace GH102588 {
+struct A {
+  int i = 0;
+  constexpr operator int() const { return i; }
+  constexpr operator int&() { return ++i; }
+};
+
+struct B : A {
+  bool operator==(const B &) const = default;
+};
+
+constexpr bool f() {
+  B x;
+  return x == x;
+}
+
+static_assert(f());
+
+struct ConstOnly {
+  std::strong_ordering operator<=>(const ConstOnly&) const;
+  std::strong_ordering operator<=>(ConstOnly&) = delete;
+  friend bool operator==(const ConstOnly&, const ConstOnly&);
+  friend bool operator==(ConstOnly&, ConstOnly&) = delete;
+};
+
+struct MutOnly {
+  std::strong_ordering operator<=>(const MutOnly&) const = delete;;
+  std::strong_ordering operator<=>(MutOnly&);
+  friend bool operator==(const MutOnly&, const MutOnly&) = delete;;
+  friend bool operator==(MutOnly&, MutOnly&);
+};
+
+struct ConstCheck : ConstOnly {
+  friend std::strong_ordering operator<=>(const ConstCheck&, const 
ConstCheck&) = default;
+  std::strong_ordering operator<=>(ConstCheck const& __restrict) const 
__restrict = default;
+  friend bool operator==(const ConstCheck&, const ConstCheck&) = default;
+  bool operator==(this const ConstCheck&, const ConstCheck&) = default;
+};
+
+// FIXME: Non-reference explicit object parameter are rejected
+struct MutCheck : MutOnly {
+  friend bool operator==(MutCheck, MutCheck) = default;
+  // std::strong_ordering operator<=>(this MutCheck, MutCheck) = default;
+  friend std::strong_ordering operator<=>(MutCheck, MutCheck) = default;
+  // bool operator==(this MutCheck, MutCheck) = default;
+};
+}

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Check explicit object parameter for defaulted operators properly (PR #100419)

2024-08-09 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/100419

>From 5d2b3fa876c00869a3964081a57ae23563d18175 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Wed, 24 Jul 2024 16:58:56 +0100
Subject: [PATCH 1/4] [Clang] Check explicit object param for defaulted
 relational operator has correct type

---
 clang/docs/ReleaseNotes.rst   |  3 +
 .../clang/Basic/DiagnosticSemaKinds.td|  2 +-
 clang/lib/Sema/SemaDeclCXX.cpp| 49 +
 .../class.compare.default/p1.cpp  |  2 +
 clang/test/CXX/drs/cwg25xx.cpp| 55 +++
 clang/test/SemaCXX/cxx2b-deducing-this.cpp| 12 +++-
 clang/www/cxx_dr_status.html  |  4 +-
 7 files changed, 100 insertions(+), 27 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 65de90f69e1981..550414ae82fdd5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -149,6 +149,9 @@ Bug Fixes to C++ Support
 
 - Fixed a crash when an expression with a dependent ``__typeof__`` type is 
used as the operand of a unary operator. (#GH97646)
 
+- Properly reject defaulted relational operators with invalid types for 
explicit object parameters,
+  e.g., ``bool operator==(this int, const Foo&)`` (#GH100329), and rvalue 
reference parameters.
+
 Bug Fixes to AST Handling
 ^
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 810abe4f23e31e..d147992bca18d9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9741,7 +9741,7 @@ def err_defaulted_special_member_quals : Error<
   "have 'const'%select{, 'constexpr'|}1 or 'volatile' qualifiers">;
 def err_defaulted_special_member_explicit_object_mismatch : Error<
   "the type of the explicit object parameter of an explicitly-defaulted "
-  "%select{copy|move}0 assignment operator should match the type of the class 
%1">;
+  "%select{copy|move}0 assignment operator should be reference to %1">;
 def err_defaulted_special_member_volatile_param : Error<
   "the parameter for an explicitly-defaulted %sub{select_special_member_kind}0 
"
   "may not be volatile">;
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 04b8d88cae217b..273e83748d1fec 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7617,9 +7617,13 @@ bool 
Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
 // parameter is of (possibly different) type “reference to C”,
 // in which case the type of F1 would differ from the type of F2
 // in that the type of F1 has an additional parameter;
-if (!Context.hasSameType(
-ThisType.getNonReferenceType().getUnqualifiedType(),
-Context.getRecordType(RD))) {
+QualType ExplicitObjectParameter = MD->isExplicitObjectMemberFunction()
+   ? MD->getParamDecl(0)->getType()
+   : QualType();
+if (!ExplicitObjectParameter.isNull() &&
+(!ExplicitObjectParameter->isReferenceType() ||
+ !Context.hasSameType(ExplicitObjectParameter.getNonReferenceType(),
+  Context.getRecordType(RD {
   if (DeleteOnTypeMismatch)
 ShouldDeleteForTypeMismatch = true;
   else {
@@ -8704,7 +8708,8 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, 
FunctionDecl *FD,
 if (!RD)
   RD = MD->getParent();
 QualType T = MD->getFunctionObjectParameterType();
-if (!T.isConstQualified()) {
+if (!T.getNonReferenceType().isConstQualified() &&
+(MD->isImplicitObjectMemberFunction() || T->isLValueReferenceType())) {
   SourceLocation Loc, InsertLoc;
   if (MD->isExplicitObjectMemberFunction()) {
 Loc = MD->getParamDecl(0)->getBeginLoc();
@@ -8723,11 +8728,17 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, 
FunctionDecl *FD,
   }
 
   // Add the 'const' to the type to recover.
-  const auto *FPT = MD->getType()->castAs();
-  FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
-  EPI.TypeQuals.addConst();
-  MD->setType(Context.getFunctionType(FPT->getReturnType(),
-  FPT->getParamTypes(), EPI));
+  if (MD->isExplicitObjectMemberFunction()) {
+assert(T->isLValueReferenceType());
+MD->getParamDecl(0)->setType(Context.getLValueReferenceType(
+T.getNonReferenceType().withConst()));
+  } else {
+const auto *FPT = MD->getType()->castAs();
+FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+EPI.TypeQuals.addConst();
+MD->setType(Context.getFunctionType(FPT->getReturnType(),
+FPT->getParamTypes(), EPI));
+  }
 }
 
 if (MD->isVolat

[clang] [Clang][SemaCXX] Preserve qualifiers in derived-to-base cast in defaulted comparison operators (PR #102619)

2024-08-09 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/102619

>From fc436186e37ff9852269599c750f8e836aee5e99 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Fri, 9 Aug 2024 15:03:38 +0100
Subject: [PATCH] [Clang][SemaCXX] Preserve qualifiers in derived-to-base cast
 in defaulted comparison operators

---
 clang/docs/ReleaseNotes.rst  |  1 +
 clang/lib/Sema/SemaDeclCXX.cpp   | 10 ++--
 clang/test/SemaCXX/cxx20-default-compare.cpp | 50 
 3 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7a05ccf3184111..30bc36bd0d6cd7 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -216,6 +216,7 @@ Bug Fixes to C++ Support
 - Clang now preserves the unexpanded flag in a lambda transform used for pack 
expansion. (#GH56852), (#GH85667),
   (#GH99877).
 - Fixed a bug when diagnosing ambiguous explicit specializations of 
constrained member functions.
+- Fixed a bug where defaulted comparison operators would remove ``const`` from 
base classes. (#GH102588)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index b07e555afcaccf..08c4cb8e144f6d 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -8414,10 +8414,12 @@ class DefaultedComparisonSynthesizer
 if (Obj.first.isInvalid() || Obj.second.isInvalid())
   return {ExprError(), ExprError()};
 CXXCastPath Path = {Base};
-return {S.ImpCastExprToType(Obj.first.get(), Base->getType(),
-CK_DerivedToBase, VK_LValue, &Path),
-S.ImpCastExprToType(Obj.second.get(), Base->getType(),
-CK_DerivedToBase, VK_LValue, &Path)};
+const auto CastToBase = [&](Expr *E) {
+  QualType ToType = S.Context.getQualifiedType(
+  Base->getType(), E->getType().getQualifiers());
+  return S.ImpCastExprToType(E, ToType, CK_DerivedToBase, VK_LValue, 
&Path);
+};
+return {CastToBase(Obj.first.get()), CastToBase(Obj.second.get())};
   }
 
   ExprPair getField(FieldDecl *Field) {
diff --git a/clang/test/SemaCXX/cxx20-default-compare.cpp 
b/clang/test/SemaCXX/cxx20-default-compare.cpp
index 7074ee885ac4a2..3e4673c31e4890 100644
--- a/clang/test/SemaCXX/cxx20-default-compare.cpp
+++ b/clang/test/SemaCXX/cxx20-default-compare.cpp
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 %s -std=c++23 -verify -Wfloat-equal
 
+#include "Inputs/std-compare.h"
+
 struct Foo {
   float val;
   bool operator==(const Foo &) const;
@@ -15,3 +17,51 @@ bool operator==(const Foo &, const Foo &) = default;  // 
expected-warning {{comp
 
 // Declare the defaulted comparison function as a non-member function. 
Arguments are passed by value.
 bool operator==(Foo, Foo) = default;  // expected-warning {{comparing floating 
point with == or != is unsafe}} expected-note {{in defaulted equality 
comparison operator for 'Foo' first required here}}
+
+namespace GH102588 {
+struct A {
+  int i = 0;
+  constexpr operator int() const { return i; }
+  constexpr operator int&() { return ++i; }
+};
+
+struct B : A {
+  bool operator==(const B &) const = default;
+};
+
+constexpr bool f() {
+  B x;
+  return x == x;
+}
+
+static_assert(f());
+
+struct ConstOnly {
+  std::strong_ordering operator<=>(const ConstOnly&) const;
+  std::strong_ordering operator<=>(ConstOnly&) = delete;
+  friend bool operator==(const ConstOnly&, const ConstOnly&);
+  friend bool operator==(ConstOnly&, ConstOnly&) = delete;
+};
+
+struct MutOnly {
+  std::strong_ordering operator<=>(const MutOnly&) const = delete;;
+  std::strong_ordering operator<=>(MutOnly&);
+  friend bool operator==(const MutOnly&, const MutOnly&) = delete;;
+  friend bool operator==(MutOnly&, MutOnly&);
+};
+
+struct ConstCheck : ConstOnly {
+  friend std::strong_ordering operator<=>(const ConstCheck&, const 
ConstCheck&) = default;
+  std::strong_ordering operator<=>(ConstCheck const& __restrict) const 
__restrict = default;
+  friend bool operator==(const ConstCheck&, const ConstCheck&) = default;
+  bool operator==(this const ConstCheck&, const ConstCheck&) = default;
+};
+
+// FIXME: Non-reference explicit object parameter are rejected
+struct MutCheck : MutOnly {
+  friend bool operator==(MutCheck, MutCheck) = default;
+  // std::strong_ordering operator<=>(this MutCheck, MutCheck) = default;
+  friend std::strong_ordering operator<=>(MutCheck, MutCheck) = default;
+  // bool operator==(this MutCheck, MutCheck) = default;
+};
+}

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Check explicit object parameter for defaulted operators properly (PR #100419)

2024-08-09 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

@cor3ntin If everything is still good with this could you commit this for me? 
Thanks!

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


[clang] [clang] Avoid triggering vtable instantiation for C++23 constexpr dtor (PR #102605)

2024-08-09 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

Does this also fix #92486?

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


[clang] [Clang] Add [[clang::diagnose_specializations]] (PR #101469)

2024-08-10 Thread Mital Ashok via cfe-commits


@@ -5408,7 +5408,10 @@ def note_dependent_function_template_spec_discard_reason 
: Note<
   "not a member of the enclosing %select{class template|"
   "namespace; did you mean to explicitly qualify the specialization?}1}0">;
 def warn_invalid_specialization : Warning<
-  "%0 should not be specialized">,
+  "%0 cannot be specialized">,

MitalAshok wrote:

```suggestion
  "%0 cannot be specialized%select{|: %2}1">,
```

And then change the diagnostics to `Diag(Loc, 
diag::warn_invalid_specialization) << VarOrClassTemplate << !Message.empty() << 
Message;`

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


[clang] [Clang] Add __builtin_is_within_lifetime to implement P2641R4's std::is_within_lifetime (PR #91895)

2024-08-11 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

@cor3ntin A `void*` can be a pointer to an object but `void*` is not a 
pointer-to-object type. `is_object_v` -> `is_object_v || is_void_v` or 
`!is_function_v`

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


[clang] [clang] Implement `__builtin_is_implicit_lifetime()` (PR #101807)

2024-08-11 Thread Mital Ashok via cfe-commits


@@ -5637,6 +5638,27 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait 
UTT,
 return false;
   case UTT_IsTriviallyEqualityComparable:
 return isTriviallyEqualityComparableType(Self, T, KeyLoc);
+  case UTT_IsImplicitLifetime: {
+DiagnoseVLAInCXXTypeTrait(Self, TInfo,
+  tok::kw___builtin_is_implicit_lifetime);
+QualType UnqualT = T->getCanonicalTypeUnqualified();
+if (UnqualT->isScalarType())
+  return true;
+if (UnqualT->isArrayType())
+  return true;
+
+const CXXRecordDecl *RD = UnqualT->getAsCXXRecordDecl();
+if (!RD)
+  return false;
+if (UnqualT->isAggregateType())
+  if (!RD->getDestructor()->isUserProvided())
+return true;
+if (RD->hasTrivialDestructor())

MitalAshok wrote:

@Endilll That's correct for `Z` but `X` and `Y` are not aggregates because they 
have user-declared constructors, so they need a non-deleted destructor

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


[clang] [clang] Implement `__builtin_is_implicit_lifetime()` (PR #101807)

2024-08-12 Thread Mital Ashok via cfe-commits

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


[clang] [clang] Implement `__builtin_is_implicit_lifetime()` (PR #101807)

2024-08-12 Thread Mital Ashok via cfe-commits

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


[clang] [Clang] Add __builtin_is_within_lifetime to implement P2641R4's std::is_within_lifetime (PR #91895)

2024-08-12 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

The feature test macro (`__cpp_lib_is_within_lifetime`) should be defined by 
the standard library in ``/`` (so libc++ or libstdc++).  
All that changes for Clang with this patch is 
`__has_builtin(__builtin_is_within_lifetime)`. P2641R4 doesn't appear to be in 
[cxx_status](https://clang.llvm.org/cxx_status.html). It's on the [libc++ C++26 
status page](https://libcxx.llvm.org/Status/Cxx2c.html), which can be updated 
when this is exposed as `std::is_within_lifetime`.

I'll add VLA tests. I'm surprised they are available at all during constant 
evaluation. I will make it just error on VLA types, since those can't be passed 
to the template function `is_within_lifetime(const auto*)`. VLA objects will 
still be supported the same as any other object if they are used after being 
cast to `void*`.

I also don't think the current behaviour before/during constructors and 
during/after destructors is correct, and I have to add more tests (for 
basically every scenario in [basic.life]).


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


[clang] [NFC] Replace bool <= bool comparison (PR #102948)

2024-08-12 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok created 
https://github.com/llvm/llvm-project/pull/102948

Closes #102912

>From fea4def3e66e7934718bab9d288094f7cbc5e4b7 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Mon, 12 Aug 2024 19:03:53 +0100
Subject: [PATCH] [NFC] Replace bool <= bool

---
 clang/lib/Sema/SemaOverload.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 52f640eb96b73b..1ce0fa091938d7 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -509,7 +509,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
 constexpr auto CanRepresentAll = [](bool FromSigned, unsigned FromWidth,
 bool ToSigned, unsigned ToWidth) {
   return (FromWidth < ToWidth + (FromSigned == ToSigned)) &&
- (FromSigned <= ToSigned);
+ !(FromSigned && !ToSigned);
 };
 
 if (CanRepresentAll(FromSigned, FromWidth, ToSigned, ToWidth))
@@ -542,7 +542,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
   // If the bit-field width was dependent, it might end up being small
   // enough to fit in the target type (unless the target type is unsigned
   // and the source type is signed, in which case it will never fit)
-  if (DependentBitField && (FromSigned <= ToSigned))
+  if (DependentBitField && !(FromSigned && !ToSigned))
 return NK_Dependent_Narrowing;
 
   // Otherwise, such a conversion is always narrowing

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [NFC] Replace bool <= bool comparison (PR #102948)

2024-08-12 Thread Mital Ashok via cfe-commits


@@ -542,7 +542,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
   // If the bit-field width was dependent, it might end up being small
   // enough to fit in the target type (unless the target type is unsigned
   // and the source type is signed, in which case it will never fit)
-  if (DependentBitField && (FromSigned <= ToSigned))
+  if (DependentBitField && !(FromSigned && !ToSigned))

MitalAshok wrote:

This could be

```suggestion
  if (DependentBitField && (!FromSigned || ToSigned))
```

But the way written follows the comment exactly and should optimise the same

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


[clang] [NFC] Deduplicate clang::AccessKinds to diagnostic strings (PR #102030)

2024-08-12 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

@cor3ntin Could you please merge this for me? Thanks

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


[clang] [Clang] Add __builtin_is_within_lifetime to implement P2641R4's std::is_within_lifetime (PR #91895)

2024-08-12 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/91895

>From 56aed689dc5825fc5bacc6dfdff58ee0eaf71f82 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 12 May 2024 19:48:24 +0100
Subject: [PATCH 01/11] [Clang] Add attribute for consteval builtins; Declare
 constexpr builtins as constexpr in C++

Also support redeclaring now-constexpr builtins without constexpr
---
 clang/include/clang/Basic/Builtins.h  |  5 +
 clang/include/clang/Basic/BuiltinsBase.td |  2 ++
 clang/lib/Sema/SemaDecl.cpp   | 15 +++
 clang/lib/Sema/SemaDeclCXX.cpp| 18 +-
 clang/lib/Sema/SemaExpr.cpp   |  8 ++--
 clang/test/Sema/builtin-redecl.cpp| 15 ++-
 6 files changed, 47 insertions(+), 16 deletions(-)

diff --git a/clang/include/clang/Basic/Builtins.h 
b/clang/include/clang/Basic/Builtins.h
index f955d21169556a..e85ec5b2dca14e 100644
--- a/clang/include/clang/Basic/Builtins.h
+++ b/clang/include/clang/Basic/Builtins.h
@@ -280,6 +280,11 @@ class Context {
 return strchr(getRecord(ID).Attributes, 'E') != nullptr;
   }
 
+  /// Returns true if this is an immediate (consteval) function
+  bool isImmediate(unsigned ID) const {
+return strchr(getRecord(ID).Attributes, 'G') != nullptr;
+  }
+
 private:
   const Info &getRecord(unsigned ID) const;
 
diff --git a/clang/include/clang/Basic/BuiltinsBase.td 
b/clang/include/clang/Basic/BuiltinsBase.td
index 724747ec76d732..1196b9e15c10dc 100644
--- a/clang/include/clang/Basic/BuiltinsBase.td
+++ b/clang/include/clang/Basic/BuiltinsBase.td
@@ -70,6 +70,8 @@ class VScanfFormat : IndexedAttribute<"S", I>;
 
 // Builtin can be constant evaluated
 def Constexpr : Attribute<"E">;
+// Builtin is immediate and must be constant evaluated. Implies Constexpr.
+def Consteval : Attribute<"EG">;
 
 // Builtin kinds
 // =
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index fb913034bd8360..6b0a04585928a5 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2409,10 +2409,17 @@ FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, 
QualType Type,
 Parent = CLinkageDecl;
   }
 
-  FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, Type,
-   /*TInfo=*/nullptr, SC_Extern,
-   
getCurFPFeatures().isFPConstrained(),
-   false, Type->isFunctionProtoType());
+  ConstexprSpecKind ConstexprKind = ConstexprSpecKind::Unspecified;
+  if (getLangOpts().CPlusPlus && Context.BuiltinInfo.isConstantEvaluated(ID)) {
+ConstexprKind = ConstexprSpecKind::Constexpr;
+if (Context.BuiltinInfo.isImmediate(ID))
+  ConstexprKind = ConstexprSpecKind::Consteval;
+  }
+
+  FunctionDecl *New = FunctionDecl::Create(
+  Context, Parent, Loc, Loc, II, Type, /*TInfo=*/nullptr, SC_Extern,
+  getCurFPFeatures().isFPConstrained(), /*isInlineSpecified=*/false,
+  Type->isFunctionProtoType(), ConstexprKind);
   New->setImplicit();
   New->addAttr(BuiltinAttr::CreateImplicit(Context, ID));
 
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 53238d355ea091..1b558d70f9b487 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -676,11 +676,19 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, 
FunctionDecl *Old,
   // template has a constexpr specifier then all its declarations shall
   // contain the constexpr specifier.
   if (New->getConstexprKind() != Old->getConstexprKind()) {
-Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch)
-<< New << static_cast(New->getConstexprKind())
-<< static_cast(Old->getConstexprKind());
-Diag(Old->getLocation(), diag::note_previous_declaration);
-Invalid = true;
+if (Old->getBuiltinID() &&
+Old->getConstexprKind() == ConstexprSpecKind::Constexpr &&
+New->getConstexprKind() == ConstexprSpecKind::Unspecified) {
+  // Except allow redeclaring a builtin as non-constexpr to match C
+  // redeclarations which will not be constexpr
+  New->setConstexprKind(ConstexprSpecKind::Constexpr);
+} else {
+  Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch)
+  << New << static_cast(New->getConstexprKind())
+  << static_cast(Old->getConstexprKind());
+  Diag(Old->getLocation(), diag::note_previous_declaration);
+  Invalid = true;
+}
   } else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() &&
  Old->isDefined(Def) &&
  // If a friend function is inlined but does not have 'inline'
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index bb4b116fd73ca6..39aa32526d2b1c 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7095,8 +7095,12 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, 
NamedDecl *NDecl,
   }

[clang] [Clang] Add __builtin_is_within_lifetime to implement P2641R4's std::is_within_lifetime (PR #91895)

2024-08-12 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

Hmm. On reading https://eel.is/c++draft/meta.const.eval#4 again, it says:

> *Remarks*: During the evaluation of an expression `E` as a core constant 
> expression, a call to this function is ill-formed unless `p` points to an 
> object that is usable in constant expressions or whose complete object's 
> lifetime began within `E`.

So calling it inside constructors before the complete-object's lifetime has 
began () should be ill-formed (instead 
of the current behaviour of `false`)

But I'm unsure about dangling pointers. The complete object's lifetime had 
begun, but it also ended. And https://cplusplus.github.io/CWG/issues/2822.html 
seems to make it implementation defined to use the pointer

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


[clang] [Clang] Add __builtin_is_within_lifetime to implement P2641R4's std::is_within_lifetime (PR #91895)

2024-08-12 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/91895

>From 56aed689dc5825fc5bacc6dfdff58ee0eaf71f82 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 12 May 2024 19:48:24 +0100
Subject: [PATCH 01/12] [Clang] Add attribute for consteval builtins; Declare
 constexpr builtins as constexpr in C++

Also support redeclaring now-constexpr builtins without constexpr
---
 clang/include/clang/Basic/Builtins.h  |  5 +
 clang/include/clang/Basic/BuiltinsBase.td |  2 ++
 clang/lib/Sema/SemaDecl.cpp   | 15 +++
 clang/lib/Sema/SemaDeclCXX.cpp| 18 +-
 clang/lib/Sema/SemaExpr.cpp   |  8 ++--
 clang/test/Sema/builtin-redecl.cpp| 15 ++-
 6 files changed, 47 insertions(+), 16 deletions(-)

diff --git a/clang/include/clang/Basic/Builtins.h 
b/clang/include/clang/Basic/Builtins.h
index f955d21169556a..e85ec5b2dca14e 100644
--- a/clang/include/clang/Basic/Builtins.h
+++ b/clang/include/clang/Basic/Builtins.h
@@ -280,6 +280,11 @@ class Context {
 return strchr(getRecord(ID).Attributes, 'E') != nullptr;
   }
 
+  /// Returns true if this is an immediate (consteval) function
+  bool isImmediate(unsigned ID) const {
+return strchr(getRecord(ID).Attributes, 'G') != nullptr;
+  }
+
 private:
   const Info &getRecord(unsigned ID) const;
 
diff --git a/clang/include/clang/Basic/BuiltinsBase.td 
b/clang/include/clang/Basic/BuiltinsBase.td
index 724747ec76d732..1196b9e15c10dc 100644
--- a/clang/include/clang/Basic/BuiltinsBase.td
+++ b/clang/include/clang/Basic/BuiltinsBase.td
@@ -70,6 +70,8 @@ class VScanfFormat : IndexedAttribute<"S", I>;
 
 // Builtin can be constant evaluated
 def Constexpr : Attribute<"E">;
+// Builtin is immediate and must be constant evaluated. Implies Constexpr.
+def Consteval : Attribute<"EG">;
 
 // Builtin kinds
 // =
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index fb913034bd8360..6b0a04585928a5 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2409,10 +2409,17 @@ FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, 
QualType Type,
 Parent = CLinkageDecl;
   }
 
-  FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, Type,
-   /*TInfo=*/nullptr, SC_Extern,
-   
getCurFPFeatures().isFPConstrained(),
-   false, Type->isFunctionProtoType());
+  ConstexprSpecKind ConstexprKind = ConstexprSpecKind::Unspecified;
+  if (getLangOpts().CPlusPlus && Context.BuiltinInfo.isConstantEvaluated(ID)) {
+ConstexprKind = ConstexprSpecKind::Constexpr;
+if (Context.BuiltinInfo.isImmediate(ID))
+  ConstexprKind = ConstexprSpecKind::Consteval;
+  }
+
+  FunctionDecl *New = FunctionDecl::Create(
+  Context, Parent, Loc, Loc, II, Type, /*TInfo=*/nullptr, SC_Extern,
+  getCurFPFeatures().isFPConstrained(), /*isInlineSpecified=*/false,
+  Type->isFunctionProtoType(), ConstexprKind);
   New->setImplicit();
   New->addAttr(BuiltinAttr::CreateImplicit(Context, ID));
 
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 53238d355ea091..1b558d70f9b487 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -676,11 +676,19 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, 
FunctionDecl *Old,
   // template has a constexpr specifier then all its declarations shall
   // contain the constexpr specifier.
   if (New->getConstexprKind() != Old->getConstexprKind()) {
-Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch)
-<< New << static_cast(New->getConstexprKind())
-<< static_cast(Old->getConstexprKind());
-Diag(Old->getLocation(), diag::note_previous_declaration);
-Invalid = true;
+if (Old->getBuiltinID() &&
+Old->getConstexprKind() == ConstexprSpecKind::Constexpr &&
+New->getConstexprKind() == ConstexprSpecKind::Unspecified) {
+  // Except allow redeclaring a builtin as non-constexpr to match C
+  // redeclarations which will not be constexpr
+  New->setConstexprKind(ConstexprSpecKind::Constexpr);
+} else {
+  Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch)
+  << New << static_cast(New->getConstexprKind())
+  << static_cast(Old->getConstexprKind());
+  Diag(Old->getLocation(), diag::note_previous_declaration);
+  Invalid = true;
+}
   } else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() &&
  Old->isDefined(Def) &&
  // If a friend function is inlined but does not have 'inline'
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index bb4b116fd73ca6..39aa32526d2b1c 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7095,8 +7095,12 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, 
NamedDecl *NDecl,
   }

[clang] [Clang] Add __builtin_is_within_lifetime to implement P2641R4's std::is_within_lifetime (PR #91895)

2024-08-12 Thread Mital Ashok via cfe-commits


@@ -17160,3 +17184,72 @@ bool Expr::tryEvaluateStrLen(uint64_t &Result, 
ASTContext &Ctx) const {
   EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold);
   return EvaluateBuiltinStrLen(this, Result, Info);
 }
+
+namespace {
+struct IsWithinLifetimeHandler {
+  EvalInfo &Info;
+  static constexpr AccessKinds AccessKind = AccessKinds::AK_IsWithinLifetime;
+  using result_type = std::optional;
+  std::optional failed() { return std::nullopt; }
+  template 
+  std::optional found(T &Subobj, QualType SubobjType) {
+return true;
+  }
+};
+
+std::optional EvaluateBuiltinIsWithinLifetime(IntExprEvaluator &IEE,
+const CallExpr *E) {
+  EvalInfo &Info = IEE.Info;
+  // assert(Info.InConstantContext && "Call to consteval builtin not in 
constant
+  // context?");
+  assert(E->getBuiltinCallee() == Builtin::BI__builtin_is_within_lifetime);

MitalAshok wrote:

It was being called from here: 
https://github.com/llvm/llvm-project/blob/b368404dee8c341dc022a9e9a868f5a268e92033/clang/lib/Sema/SemaChecking.cpp#L12702

I've now made it so it explicitly does not work in those sorts of cases

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


  1   2   3   4   5   >