[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] 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

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] [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 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 

[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  = *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 = 

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

[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 , SourceLocation OpLoc);
+  QualType CheckAddressOfOperand(ExprResult , 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 , 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 , SourceLocation OpLoc) 
{
+/// If IsBuiltinAddressof is true, this is spelt __builtin_addressof(E)
+/// instead of 
+QualType Sema::CheckAddressOfOperand(ExprResult , 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 
, 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 
, 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 
, 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 ::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 
, SourceLocation OpLoc) {
 } else if (isa(dcl)) {
   AddressOfError = 

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

[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] [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] [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  = *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 (ConvertedValue != 

[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

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 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] [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 ,
  const InitializedEntity ,
  const InitializationKind ,
@@ -4239,8 +4239,8 @@ static void TryConstructorInitialization(Sema ,
   // 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 ,
 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 ,
   // - 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 , 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 

[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 ,
  const InitializedEntity ,
  const InitializationKind ,
@@ -4239,8 +4239,8 @@ static void TryConstructorInitialization(Sema ,
   // 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 ,
 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 ,
   // - 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 , 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->getNumInits() == 1 &&
+  

[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 `` 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 , SourceLocation OpLoc);
+  QualType CheckAddressOfOperand(ExprResult , 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 , 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 , SourceLocation OpLoc) 
{
+/// If IsBuiltinAddressof is true, this is spelt __builtin_addressof(E)
+/// instead of 
+QualType Sema::CheckAddressOfOperand(ExprResult , 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 
, 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 
, SourceLocation OpLoc) {
   unsigned AddressOfError = AO_No_Error;
 
   if (lval == Expr::LV_ClassTemporary || lval == Expr::LV_ArrayTemporary) {
-bool sfinae = (bool)isSFINAEContext();
-Diag(OpLoc, isSFINAEContext() 

[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 ,
  const InitializedEntity ,
  const InitializationKind ,
@@ -4239,8 +4239,8 @@ static void TryConstructorInitialization(Sema ,
   // 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 ,
 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 ,
   // - 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 , 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->getNumInits() == 1 &&
+   

[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 ,
  const InitializedEntity ,
  const InitializationKind ,
@@ -4239,8 +4239,8 @@ static void TryConstructorInitialization(Sema ,
   // 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 ,
 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 ,
   // - 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 , 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->getNumInits() == 1 &&
+   

[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


[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 ,
  const InitializedEntity ,
  const InitializationKind ,
@@ -4240,8 +4240,8 @@ static void TryConstructorInitialization(Sema ,
   // 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 ,
 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 ,
   // - 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 , 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 

[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


[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


[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


[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] 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  = 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] [SemaCXX] Implement CWG2627 Bit-fields and narrowing conversions (PR #78112)

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

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

>From 92f8720e3d21521b589d5291f086a2f32b87bfe0 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   |   5 +
 .../clang/Basic/DiagnosticSemaKinds.td|   3 +
 clang/include/clang/Sema/Overload.h   |   7 +-
 clang/lib/Sema/SemaExpr.cpp   |  10 +-
 clang/lib/Sema/SemaInit.cpp   |  20 ++-
 clang/lib/Sema/SemaOverload.cpp   | 119 +--
 .../dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp |  24 
 clang/test/CXX/drs/dr26xx.cpp | 136 ++
 clang/www/cxx_dr_status.html  |   2 +-
 9 files changed, 278 insertions(+), 48 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 92563262cc6737..28202fc604e298 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -157,6 +157,11 @@ Resolutions to C++ Defect Reports
 - Clang now diagnoses declarative nested-name-specifiers with 
pack-index-specifiers.
   (`CWG2858: Declarative nested-name-specifiers and pack-index-specifiers 
`_).
 
+- 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.
+  (`CWG2627. Bit-fields and narrowing conversions  
`_).
+
 C Language Changes
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index fdca82934cb4dc..6cdb439be30ae5 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6253,6 +6253,9 @@ def ext_init_list_variable_narrowing_const_reference : 
ExtWarn<
 def ext_init_list_constant_narrowing : ExtWarn<
   "constant expression evaluates to %0 which cannot be narrowed to type %1">,
   InGroup, DefaultError, SFINAEFailure;
+def ext_bit_field_narrowing : Extension<
+  "narrowing non-constant-expression from %0 bit-field of width %2 to %1 is a 
C++23 extension">,
+  InGroup, SFINAEFailure;
 def ext_init_list_constant_narrowing_const_reference : ExtWarn<
   ext_init_list_constant_narrowing.Summary>,
   InGroup, DefaultError, SFINAEFailure;
diff --git a/clang/include/clang/Sema/Overload.h 
b/clang/include/clang/Sema/Overload.h
index 76311b00d2fc58..0d94045cc13f79 100644
--- a/clang/include/clang/Sema/Overload.h
+++ b/clang/include/clang/Sema/Overload.h
@@ -244,7 +244,11 @@ class Sema;
 /// Not a narrowing conversion.
 NK_Not_Narrowing,
 
-/// A narrowing conversion by virtue of the source and destination types.
+/// Not a narrowing conversion in C++23 because the source is a bit-field
+/// whose range can fit in the target type
+NK_BitField_Not_Narrowing,
+
+/// A narrowing conversion by virtue of the source and target types.
 NK_Type_Narrowing,
 
 /// A narrowing conversion, because a constant expression got narrowed.
@@ -387,6 +391,7 @@ class Sema;
 NarrowingKind
 getNarrowingKind(ASTContext , const Expr *Converted,
  APValue , QualType ,
+ unsigned ,
  bool IgnoreFloatToIntegralConversion = false) const;
 bool isPointerConversionToBool() const;
 bool isPointerConversionToVoidPointer(ASTContext& Context) const;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 50f92c496a539a..4c16fcc60fc771 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -12361,8 +12361,9 @@ static bool checkThreeWayNarrowingConversion(Sema , 
QualType ToType, Expr *E,
 
   APValue PreNarrowingValue;
   QualType PreNarrowingType;
+  unsigned BitFieldWidth;
   switch (SCS.getNarrowingKind(S.Context, E, PreNarrowingValue,
-   PreNarrowingType,
+   PreNarrowingType, BitFieldWidth,
/*IgnoreFloatToIntegralConversion*/ true)) {
   case NK_Dependent_Narrowing:
 // Implicit conversion to a narrower type, but the expression is
@@ -12370,6 +12371,13 @@ static bool checkThreeWayNarrowingConversion(Sema , 
QualType ToType, Expr *E,
   case NK_Not_Narrowing:
 return false;
 
+  case NK_BitField_Not_Narrowing:
+if (!S.getLangOpts().CPlusPlus23) {
+  return S.Diag(E->getBeginLoc(), diag::ext_bit_field_narrowing)
+ << FromType << ToType << BitFieldWidth;
+}
+return false;
+
   case NK_Constant_Narrowing:
 // Implicit conversion to a narrower type, and the value is not a constant
 // expression.
diff --git a/clang/lib/Sema/SemaInit.cpp 

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

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

MitalAshok wrote:

New version gives a pedantic warning if this is used before C++23 (and it is a 
substitution failure before C++23)

https://github.com/llvm/llvm-project/pull/78112
___
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-04-26 Thread Mital Ashok via cfe-commits

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

>From 6ed7cad5d4993603221c3d9a777463675d69643b 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|  3 ++
 clang/include/clang/AST/ExprCXX.h  |  5 +--
 clang/lib/Sema/SemaExprCXX.cpp | 23 
 clang/lib/Sema/SemaInit.cpp|  1 +
 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 +-
 9 files changed, 75 insertions(+), 14 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 92563262cc6737..28cd1a8abd4c65 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -157,6 +157,9 @@ Resolutions to C++ Defect Reports
 - Clang now diagnoses declarative nested-name-specifiers with 
pack-index-specifiers.
   (`CWG2858: Declarative nested-name-specifiers and pack-index-specifiers 
`_).
 
+- 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 a915745d2d7322..8fa5c0c79f6a02 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -2170,8 +2170,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 a non-class type T.
+/// 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 779a41620033dc..269aedb59ca8f1 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1660,12 +1660,23 @@ 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) {
+  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/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 003a157990d307..3bb8407c893d9d 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -5344,6 +5344,7 @@ static void TryValueInitialization(Sema ,
   //
   //   To value-initialize an object of type T means:
   QualType T = Entity.getType();
+  assert(!T->isVoidType() && "Cannot value-init void");
 
   // -- if T is an array type, then each element is value-initialized;
   T = S.Context.getBaseElementType(T);
diff --git a/clang/test/CXX/drs/dr23xx.cpp b/clang/test/CXX/drs/dr23xx.cpp
index db5b7c3cd3c9a2..cd21af0daf3d0f 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 

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

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


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

MitalAshok wrote:

[[expr.type.conv]p2](https://wg21.link/expr.type.conv#2) reads 
"`T(expression-list)` or `T braced-init-list` is a cast expression, a prvalue 
`void`, or direct-initialized from the initializer". So when we encounter 
`void()` or `void{}`, we shouldn't actually use initialization semantics.

Previously, `void()` worked because 
https://github.com/llvm/llvm-project/blob/2d09ac4037415ab0044ad508aae2ff8b2559a9d8/clang/lib/Sema/SemaInit.cpp#L6255-L6260
 made it a value initialization by accident, and we allowed value initializing 
void

I've now added an assertion for `void` in `TryValueInitialization` because you 
shouldn't actually be able to get there, since there's no standard way to call 
for the value-intialization of `void`

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] Recognise initializer_list injected-class-name types as initializer_lists (PR #90210)

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

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

This allows the implicitly-generated deduction guide for the copy constructor 
to be recognised as an initializer-list constructor, allowing CTAD for 
std::initializer_list

>From ff65636895e8bceb5b4d6497a0e9ccda0c5fa22a Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Fri, 26 Apr 2024 13:44:17 +0100
Subject: [PATCH] [SemaCXX] Recognise initializer_list injected-class-name
 types as initializer_lists

This allows the implicitly-generated deduction guide for the copy constructor 
to be recognised as an initializer-list constructor, allowing CTAD for 
std::initializer_list
---
 clang/docs/ReleaseNotes.rst  |  2 ++
 clang/lib/Sema/SemaDeclCXX.cpp   | 16 +++-
 clang/lib/Sema/SemaInit.cpp  |  2 --
 .../cxx1z-class-template-argument-deduction.cpp  | 11 ---
 4 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 92563262cc6737..4065de5745aae6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -581,6 +581,8 @@ Bug Fixes to C++ Support
 - Fixed a use-after-free bug in parsing of type constraints with default 
arguments that involve lambdas. (#GH67235)
 - Fixed bug in which the body of a consteval lambda within a template was not 
parsed as within an
   immediate function context.
+- Fix CTAD for ``std::initializer_list``. This allows 
``std::initializer_list{1, 2, 3}`` to be deduced as
+  ``std::initializer_list`` as intended.
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index abdbc9d8830c03..8d98f593817bda 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -12052,11 +12052,17 @@ bool Sema::isStdInitializerList(QualType Ty, QualType 
*Element) {
 
 Template = Specialization->getSpecializedTemplate();
 Arguments = Specialization->getTemplateArgs().data();
-  } else if (const TemplateSpecializationType *TST =
- Ty->getAs()) {
-Template = dyn_cast_or_null(
-TST->getTemplateName().getAsTemplateDecl());
-Arguments = TST->template_arguments().begin();
+  } else {
+const TemplateSpecializationType *TST = nullptr;
+if (auto *ICN = Ty->getAs())
+  TST = ICN->getInjectedTST();
+else
+  TST = Ty->getAs();
+if (TST) {
+  Template = dyn_cast_or_null(
+  TST->getTemplateName().getAsTemplateDecl());
+  Arguments = TST->template_arguments().begin();
+}
   }
   if (!Template)
 return false;
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 003a157990d307..842d165c60d94c 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -10790,8 +10790,6 @@ QualType 
Sema::DeduceTemplateSpecializationFromInitializer(
   // FIXME: Perform "exact type" matching first, per CWG discussion?
   //Or implement this via an implied 'T(T) -> T' deduction guide?
 
-  // FIXME: Do we need/want a std::initializer_list special case?
-
   // Look up deduction guides, including those synthesized from constructors.
   //
   // C++1z [over.match.class.deduct]p1:
diff --git a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp 
b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
index 2f067ea53a5029..90404f115c75f7 100644
--- a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -12,14 +12,19 @@ namespace std {
 size_t n;
 initializer_list();
   };
-  // FIXME: This should probably not be necessary.
-  template initializer_list(initializer_list) -> 
initializer_list;
 }
 
 template constexpr bool has_type(...) { return false; }
 template constexpr bool has_type(T&) { return true; }
 
-std::initializer_list il = {1, 2, 3, 4, 5};
+std::initializer_list il1 = {1, 2, 3, 4, 5};
+auto il2 = std::initializer_list{1, 2, 3, 4};
+auto il3 = std::initializer_list{il1};
+auto il4 = std::initializer_list{il1, il1, il1};
+static_assert(has_type>(il1));
+static_assert(has_type>(il2));
+static_assert(has_type>(il3));
+static_assert(has_type>>(il4));
 
 template struct vector {
   template vector(Iter, Iter);

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


[clang] [SemaCXX] Recognise initializer_list injected-class-name types as initializer_lists (PR #90210)

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

MitalAshok wrote:

Original Differential revision: https://reviews.llvm.org/D156064

Doesn't appear that anything has changed since, just rebased the changes.

https://github.com/llvm/llvm-project/pull/90210
___
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-04-26 Thread Mital Ashok via cfe-commits

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


[clang] [SemaCXX] Qualified functions can't decay into pointers (PR #90353)

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

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

Fixes #27059

Dependent function parameters, template parameters and exception declarations 
that have qualified function types now error instead of silently decaying into 
an invalid pointer type.

Also fix __decay and __add_pointer for these types which previously just 
ignored the qualifiers

>From 9319c295d96550dfd703559f7c7fc980a68fb286 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sat, 27 Apr 2024 19:15:00 +0100
Subject: [PATCH] [SemaCXX] Qualified functions can't decay into pointers

Fixes #27059

Dependent function parameters, template parameters and exception
declarations that have qualified function types now error instead of
silently decaying into an invalid pointer type.

Also fix __decay and __add_pointer for these types which previously
just ignored the qualifiers
---
 clang/include/clang/AST/Type.h|  4 +-
 clang/lib/AST/TypePrinter.cpp | 23 ++
 clang/lib/Sema/SemaDecl.cpp   |  7 +++
 clang/lib/Sema/SemaDeclCXX.cpp| 16 +--
 clang/lib/Sema/SemaTemplate.cpp   | 24 +-
 clang/lib/Sema/SemaType.cpp   | 46 +++
 .../dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp|  5 +-
 .../CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp   |  5 +-
 clang/test/SemaCXX/function-type-qual.cpp | 36 ++-
 clang/test/SemaCXX/type-traits.cpp| 12 +
 10 files changed, 135 insertions(+), 43 deletions(-)

diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index dff02d4861b3db..bf8187385f062c 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -5035,6 +5035,8 @@ class FunctionProtoType final
 return static_cast(FunctionTypeBits.RefQualifier);
   }
 
+  std::string getFunctionQualifiersAsString() const;
+
   using param_type_iterator = const QualType *;
 
   ArrayRef param_types() const {
@@ -7370,7 +7372,7 @@ inline bool QualType::isReferenceable() const {
   if (const auto *F = Self.getAs())
 return F->getMethodQuals().empty() && F->getRefQualifier() == RQ_None;
 
-  return false;
+  return Self.isFunctionType();
 }
 
 inline SplitQualType QualType::split() const {
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 9602f448e94279..720ac254539f11 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -2571,3 +2571,26 @@ raw_ostream ::operator<<(raw_ostream , QualType 
QT) {
   TypePrinter(LangOptions()).print(S.Ty, S.Quals, OS, /*PlaceHolder=*/"");
   return OS;
 }
+
+std::string FunctionProtoType::getFunctionQualifiersAsString() const {
+  std::string Quals = getMethodQuals().getAsString();
+
+  switch (getRefQualifier()) {
+  case RQ_None:
+break;
+
+  case RQ_LValue:
+if (!Quals.empty())
+  Quals += ' ';
+Quals += '&';
+break;
+
+  case RQ_RValue:
+if (!Quals.empty())
+  Quals += ' ';
+Quals += "&&";
+break;
+  }
+
+  return Quals;
+}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e0745fe9a45367..66748fd9ca17f6 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15392,6 +15392,13 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, 
SourceLocation StartLoc,
 T = Context.getLifetimeQualifiedType(T, lifetime);
   }
 
+  if (T->isFunctionType() && !T.isReferenceable()) {
+Diag(NameLoc, diag::err_compound_qualified_function_type)
+<< 1 << true << T
+<< T->castAs()->getFunctionQualifiersAsString();
+return nullptr;
+  }
+
   ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name,
  Context.getAdjustedParameterType(T),
  TSInfo, SC, nullptr);
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index abdbc9d8830c03..d5630b609cabc4 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -11323,7 +11323,8 @@ void Sema::CheckConversionDeclarator(Declarator , 
QualType ,
 D.setInvalidType();
   } else if (ConvType->isFunctionType()) {
 Diag(D.getIdentifierLoc(), diag::err_conv_function_to_function);
-ConvType = Context.getPointerType(ConvType);
+if (ConvType.isReferenceable())
+  ConvType = Context.getPointerType(ConvType);
 D.setInvalidType();
   }
 
@@ -16974,8 +16975,17 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, 
TypeSourceInfo *TInfo,
   // Arrays and functions decay.
   if (ExDeclType->isArrayType())
 ExDeclType = Context.getArrayDecayedType(ExDeclType);
-  else if (ExDeclType->isFunctionType())
-ExDeclType = Context.getPointerType(ExDeclType);
+  else if (ExDeclType->isFunctionType()) {
+if (ExDeclType.isReferenceable())
+  ExDeclType = Context.getPointerType(ExDeclType);
+else {
+  Diag(Loc, diag::err_compound_qualified_function_type)
+

[clang] [clang] Implement CWG2851: floating-point conversions in converted constant expressions (PR #90387)

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


@@ -67,6 +68,69 @@ void B::g() requires true;
 
 } // namespace cwg2847
 
+namespace cwg2851 { // cwg2851: 19
+
+#if __cplusplus >= 202002L
+template struct Val { static constexpr T value = v; };
+
+
+// Floating-point promotions
+
+static_assert(Val::value == 0.0L);
+static_assert(Val::value == 0.0L);
+static_assert(Val::value == 0.0);
+static_assert(Val::value == -0.0L);
+
+static_assert(!__is_same(Val, Val));
+static_assert(__is_same(Val, Val));
+
+static_assert(__is_same(Val, Val));
+
+static_assert(__is_same(Val, Val(__builtin_nanf(""))>));
+static_assert(__is_same(Val, Val(__builtin_nansf(""))>));
+static_assert(__is_same(Val, Val(__builtin_nanf("0x1"))>));
+static_assert(__is_same(Val, Val(__builtin_nansf("0x1"))>));
+
+
+// Floating-point conversions where the source value can be represented 
exactly in the destination type
+
+static_assert(Val::value == 0.0L);
+static_assert(__is_same(Val, Val));
+static_assert(__is_same(Val, Val));
+static_assert(!__is_same(Val, Val));
+static_assert(__is_same(Val, Val));
+static_assert(__is_same(Val, Val));
+
+static_assert(__is_same(Val, Val));
+Val _1;
+// since-cxx20-error-re@-1 {{non-type template argument evaluates to {{.+}} 
which cannot be exactly represented in type 'float'}}
+Val(__FLT_DENORM_MIN__) / 2.0L> _2;
+// since-cxx20-error-re@-1 {{non-type template argument evaluates to {{.+}} 
which cannot be exactly represented in type 'float'}}
+Val _3;
+// since-cxx20-error-re@-1 {{non-type template argument evaluates to {{.+}} 
which cannot be exactly represented in type 'float'}}
+
+static_assert(__is_same(Val, Val));
+
+static_assert(__is_same(Val, Val(__builtin_nanl(""))>));
+static_assert(__is_same(Val, Val(__builtin_nansl(""))>));
+#if __SIZEOF_LONG_DOUBLE__ > 8
+// since-cxx20-error@-2 {{non-type template argument evaluates to nan which 
cannot be exactly represented in type 'float'}}
+#endif
+// Payload is shifted right so these payloads will be preserved
+static_assert(__is_same(Val, Val(__builtin_nan("0xFF"))>));
+static_assert(__is_same(Val, Val(__builtin_nans("0xFF"))>));
+static_assert(__is_same(Val, Val(__builtin_nanl("0x1"))>));

MitalAshok wrote:

I'm not sure how exactly we plan to deal with `NaN`. How `APFloat::convert` 
seems to work is that when converting to a smaller type, only the most 
significant bits of the payload are used, so that 1 is cut off (thus lossy).

This has the side effect that `Val` and `Val` always work, because `(long double) 
__builtin_nanf(payload)` is like `__builtin_nanl(payload << (difference in 
number of fraction bits between long double and float))`, and anything with the 
lower bits set counts as "lossy". Anything implicitly converted to a larger 
type can be converted back in a converted constant expression. See also: 
IEEE754 6.2.3 "NaN propagation"

CWG2864 is about narrowing conversions. For sure `float{__builtin_nanl("0x1")}` 
isn't a narrowing conversion because it's not finite, but it does lose the 
payload entirely (`float{__builtin_nanl("0x1")}` and 
`float{__builtin_nanl("0x0")}` have the same bit pattern, even though the 
source long doubles don't). But maybe we should consider all NaNs to have the 
same "value" and this should work?

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


[clang] [clang] Implement CWG2851: floating-point conversions in converted constant expressions (PR #90387)

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

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

>From a87399f8a41bb7d9a61c2d44c75836d86c6b4c38 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 28 Apr 2024 09:48:47 +0100
Subject: [PATCH] [clang] Implement CWG2851: floating-point conversions in
 converted constant expressions

---
 clang/docs/ReleaseNotes.rst   |  3 +
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/lib/Sema/SemaOverload.cpp   | 37 ++-
 clang/test/CXX/drs/dr28xx.cpp | 64 +++
 4 files changed, 105 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a1390d6536b28c..7c8d83bd73613b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -164,6 +164,9 @@ Resolutions to C++ Defect Reports
 - Clang now diagnoses declarative nested-name-specifiers with 
pack-index-specifiers.
   (`CWG2858: Declarative nested-name-specifiers and pack-index-specifiers 
`_).
 
+- Allow floating-point promotions and conversions in converted constant 
expressions.
+  (`CWG2851 Allow floating-point conversions in converted constant expressions 
`_).
+
 C Language Changes
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index fdca82934cb4dc..cb248f2ea6374b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -85,6 +85,10 @@ def err_expr_not_cce : Error<
   "%select{case value|enumerator value|non-type template argument|"
   "array size|explicit specifier argument|noexcept specifier argument|"
   "call to 'size()'|call to 'data()'}0 is not a constant expression">;
+def err_float_conv_cant_represent : Error<
+  "non-type template argument evaluates to %0 which cannot be "
+  "exactly represented in type %1"
+>;
 def ext_cce_narrowing : ExtWarn<
   "%select{case value|enumerator value|non-type template argument|"
   "array size|explicit specifier argument|noexcept specifier argument|"
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 04cd9e78739d20..474a8a4b5654cb 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6072,6 +6072,10 @@ static bool CheckConvertedConstantConversions(Sema ,
   case ICK_Integral_Promotion:
   case ICK_Integral_Conversion: // Narrowing conversions are checked elsewhere.
   case ICK_Zero_Queue_Conversion:
+  // Per CWG2851, floating-point promotions and conversions are allowed.
+  // The value of a conversion is checked afterwards.
+  case ICK_Floating_Promotion:
+  case ICK_Floating_Conversion:
 return true;
 
   case ICK_Boolean_Conversion:
@@ -6091,9 +6095,7 @@ static bool CheckConvertedConstantConversions(Sema ,
 // only permitted if the source type is std::nullptr_t.
 return SCS.getFromType()->isNullPtrType();
 
-  case ICK_Floating_Promotion:
   case ICK_Complex_Promotion:
-  case ICK_Floating_Conversion:
   case ICK_Complex_Conversion:
   case ICK_Floating_Integral:
   case ICK_Compatible_Conversion:
@@ -6229,7 +6231,36 @@ static ExprResult BuildConvertedConstantExpression(Sema 
, Expr *From,
   if (Result.isInvalid())
 return Result;
 
-  // Check for a narrowing implicit conversion.
+  if (SCS->Second == ICK_Floating_Conversion) {
+// Unlike with narrowing conversions, the value must fit
+// exactly even if it is in range
+assert(CCE == Sema::CCEKind::CCEK_TemplateArg &&
+   "Only non-type template args should use floating-point 
conversions");
+
+// Initializer is From, except it is a full-expression
+const Expr *Initializer =
+IgnoreNarrowingConversion(S.Context, Result.get());
+
+// If it's value-dependent, we can't tell whether it will fit
+if (Initializer->isValueDependent())
+  return Result;
+
+// Not-constant diagnosed afterwards
+if (!Initializer->isCXX11ConstantExpr(S.Context, ))
+  return Result;
+
+llvm::APFloat PostNarrowingValue = PreNarrowingValue.getFloat();
+bool LosesInfo = true;
+PostNarrowingValue.convert(S.Context.getFloatTypeSemantics(T), 
llvm::APFloat::rmNearestTiesToEven, );
+
+if (LosesInfo)
+  S.Diag(From->getBeginLoc(), diag::err_float_conv_cant_represent)
+  << PreNarrowingValue.getAsString(S.Context, From->getType()) << T;
+
+return Result;
+  }
+
+  // Check for a narrowing integer conversion.
   bool ReturnPreNarrowingValue = false;
   QualType PreNarrowingType;
   switch (SCS->getNarrowingKind(S.Context, Result.get(), PreNarrowingValue,
diff --git a/clang/test/CXX/drs/dr28xx.cpp b/clang/test/CXX/drs/dr28xx.cpp
index 4d9b0c76758d53..1626b1a9bf7b5b 100644
--- a/clang/test/CXX/drs/dr28xx.cpp
+++ b/clang/test/CXX/drs/dr28xx.cpp
@@ -3,6 +3,7 @@
 // RUN: %clang_cc1 -std=c++14 

[clang] [clang] Implement CWG2851: floating-point conversions in converted constant expressions (PR #90387)

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

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

>From 13e2943dea677daf8976ab55a673d43982ac8a4c Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 28 Apr 2024 09:48:47 +0100
Subject: [PATCH] [clang] Implement CWG2851: floating-point conversions in
 converted constant expressions

---
 clang/docs/ReleaseNotes.rst   |  3 +
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/lib/Sema/SemaOverload.cpp   | 38 ++-
 clang/test/CXX/drs/dr28xx.cpp | 64 +++
 4 files changed, 106 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a1390d6536b28c..7c8d83bd73613b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -164,6 +164,9 @@ Resolutions to C++ Defect Reports
 - Clang now diagnoses declarative nested-name-specifiers with 
pack-index-specifiers.
   (`CWG2858: Declarative nested-name-specifiers and pack-index-specifiers 
`_).
 
+- Allow floating-point promotions and conversions in converted constant 
expressions.
+  (`CWG2851 Allow floating-point conversions in converted constant expressions 
`_).
+
 C Language Changes
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index fdca82934cb4dc..cb248f2ea6374b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -85,6 +85,10 @@ def err_expr_not_cce : Error<
   "%select{case value|enumerator value|non-type template argument|"
   "array size|explicit specifier argument|noexcept specifier argument|"
   "call to 'size()'|call to 'data()'}0 is not a constant expression">;
+def err_float_conv_cant_represent : Error<
+  "non-type template argument evaluates to %0 which cannot be "
+  "exactly represented in type %1"
+>;
 def ext_cce_narrowing : ExtWarn<
   "%select{case value|enumerator value|non-type template argument|"
   "array size|explicit specifier argument|noexcept specifier argument|"
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 04cd9e78739d20..40d65638e3afc1 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6072,6 +6072,10 @@ static bool CheckConvertedConstantConversions(Sema ,
   case ICK_Integral_Promotion:
   case ICK_Integral_Conversion: // Narrowing conversions are checked elsewhere.
   case ICK_Zero_Queue_Conversion:
+  // Per CWG2851, floating-point promotions and conversions are allowed.
+  // The value of a conversion is checked afterwards.
+  case ICK_Floating_Promotion:
+  case ICK_Floating_Conversion:
 return true;
 
   case ICK_Boolean_Conversion:
@@ -6091,9 +6095,7 @@ static bool CheckConvertedConstantConversions(Sema ,
 // only permitted if the source type is std::nullptr_t.
 return SCS.getFromType()->isNullPtrType();
 
-  case ICK_Floating_Promotion:
   case ICK_Complex_Promotion:
-  case ICK_Floating_Conversion:
   case ICK_Complex_Conversion:
   case ICK_Floating_Integral:
   case ICK_Compatible_Conversion:
@@ -6229,7 +6231,37 @@ static ExprResult BuildConvertedConstantExpression(Sema 
, Expr *From,
   if (Result.isInvalid())
 return Result;
 
-  // Check for a narrowing implicit conversion.
+  if (SCS->Second == ICK_Floating_Conversion) {
+// Unlike with narrowing conversions, the value must fit
+// exactly even if it is in range
+assert(CCE == Sema::CCEKind::CCEK_TemplateArg &&
+   "Only non-type template args should use floating-point 
conversions");
+
+// Initializer is From, except it is a full-expression
+const Expr *Initializer =
+IgnoreNarrowingConversion(S.Context, Result.get());
+
+// If it's value-dependent, we can't tell whether it will fit
+if (Initializer->isValueDependent())
+  return Result;
+
+// Not-constant diagnosed afterwards
+if (!Initializer->isCXX11ConstantExpr(S.Context, ))
+  return Result;
+
+llvm::APFloat PostNarrowingValue = PreNarrowingValue.getFloat();
+bool LosesInfo = true;
+PostNarrowingValue.convert(S.Context.getFloatTypeSemantics(T),
+   llvm::APFloat::rmNearestTiesToEven, );
+
+if (LosesInfo)
+  S.Diag(From->getBeginLoc(), diag::err_float_conv_cant_represent)
+  << PreNarrowingValue.getAsString(S.Context, From->getType()) << T;
+
+return Result;
+  }
+
+  // Check for a narrowing integer conversion.
   bool ReturnPreNarrowingValue = false;
   QualType PreNarrowingType;
   switch (SCS->getNarrowingKind(S.Context, Result.get(), PreNarrowingValue,
diff --git a/clang/test/CXX/drs/dr28xx.cpp b/clang/test/CXX/drs/dr28xx.cpp
index 4d9b0c76758d53..1626b1a9bf7b5b 100644
--- a/clang/test/CXX/drs/dr28xx.cpp
+++ b/clang/test/CXX/drs/dr28xx.cpp
@@ -3,6 +3,7 @@
 // RUN: 

[clang] [clang] Implement CWG2851: floating-point conversions in converted constant expressions (PR #90387)

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

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

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

The only time the target type for a converted constant expression is a 
floating-point type is in a NTTP, so this only affects C++20+.

>From 3d56657f03ab6824bf6717a89b4b2f757770aad5 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 28 Apr 2024 09:48:47 +0100
Subject: [PATCH] [clang] Implement CWG2851: floating-point conversions in
 converted constant expressions

---
 clang/docs/ReleaseNotes.rst   |  3 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/lib/Sema/SemaOverload.cpp   | 38 +--
 clang/test/CXX/drs/dr28xx.cpp | 35 +
 4 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a1390d6536b28c..7c8d83bd73613b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -164,6 +164,9 @@ Resolutions to C++ Defect Reports
 - Clang now diagnoses declarative nested-name-specifiers with 
pack-index-specifiers.
   (`CWG2858: Declarative nested-name-specifiers and pack-index-specifiers 
`_).
 
+- Allow floating-point promotions and conversions in converted constant 
expressions.
+  (`CWG2851 Allow floating-point conversions in converted constant expressions 
`_).
+
 C Language Changes
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index fdca82934cb4dc..08ebb28ff17b25 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -85,6 +85,10 @@ def err_expr_not_cce : Error<
   "%select{case value|enumerator value|non-type template argument|"
   "array size|explicit specifier argument|noexcept specifier argument|"
   "call to 'size()'|call to 'data()'}0 is not a constant expression">;
+def err_float_conv_cant_represent : Error<
+  "non-type template argument evaluates to %0 which can not be "
+  "represented in type %1"
+>;
 def ext_cce_narrowing : ExtWarn<
   "%select{case value|enumerator value|non-type template argument|"
   "array size|explicit specifier argument|noexcept specifier argument|"
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 04cd9e78739d20..c35517db946b1c 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6072,6 +6072,10 @@ static bool CheckConvertedConstantConversions(Sema ,
   case ICK_Integral_Promotion:
   case ICK_Integral_Conversion: // Narrowing conversions are checked elsewhere.
   case ICK_Zero_Queue_Conversion:
+  // Per CWG2851, floating-point promotions and conversions are allowed.
+  // The value of a conversion is checked afterwards.
+  case ICK_Floating_Promotion:
+  case ICK_Floating_Conversion:
 return true;
 
   case ICK_Boolean_Conversion:
@@ -6091,9 +6095,7 @@ static bool CheckConvertedConstantConversions(Sema ,
 // only permitted if the source type is std::nullptr_t.
 return SCS.getFromType()->isNullPtrType();
 
-  case ICK_Floating_Promotion:
   case ICK_Complex_Promotion:
-  case ICK_Floating_Conversion:
   case ICK_Complex_Conversion:
   case ICK_Floating_Integral:
   case ICK_Compatible_Conversion:
@@ -6229,7 +6231,37 @@ static ExprResult BuildConvertedConstantExpression(Sema 
, Expr *From,
   if (Result.isInvalid())
 return Result;
 
-  // Check for a narrowing implicit conversion.
+  if (SCS->Second == ICK_Floating_Conversion) {
+// Unlike with narrowing conversions, the value must fit
+// exactly even if it is in range
+assert(CCE == Sema::CCEKind::CCEK_TemplateArg &&
+   "Only non-type template args should use floating-point 
conversions");
+
+// Initializer is From, except it is a full-expression
+const Expr *Initializer =
+IgnoreNarrowingConversion(S.Context, Result.get());
+
+// If it's value-dependent, we can't tell whether it will fit
+if (Initializer->isValueDependent())
+  return Result;
+
+if (!Initializer->isCXX11ConstantExpr(S.Context, )) {
+  S.Diag(Initializer->getBeginLoc(), diag::err_expr_not_cce) << CCE;
+  return Result;
+}
+
+llvm::APFloat PostNarrowingValue = PreNarrowingValue.getFloat();
+bool LosesInfo = true;
+PostNarrowingValue.convert(S.Context.getFloatTypeSemantics(T),
+   llvm::APFloat::rmNearestTiesToEven, );
+if (LosesInfo)
+  S.Diag(From->getBeginLoc(), diag::err_float_conv_cant_represent)
+  << PreNarrowingValue.getAsString(S.Context, From->getType()) << T;
+
+return Result;
+  }
+
+  // Check for a narrowing integer conversion.
   bool ReturnPreNarrowingValue = false;
   QualType PreNarrowingType;
   switch (SCS->getNarrowingKind(S.Context, Result.get(), 

[clang] [clang] Implement CWG2851: floating-point conversions in converted constant expressions (PR #90387)

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

MitalAshok wrote:

Waiting on #90352 because it's not on the cxx_dr_status page yet 
(`make_dr_status` doesn't do anything)

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


[clang] [clang] Implement CWG2851: floating-point conversions in converted constant expressions (PR #90387)

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


@@ -6229,7 +6231,37 @@ static ExprResult BuildConvertedConstantExpression(Sema 
, Expr *From,
   if (Result.isInvalid())
 return Result;
 
-  // Check for a narrowing implicit conversion.
+  if (SCS->Second == ICK_Floating_Conversion) {

MitalAshok wrote:

Because it has a different specification from narrowing conversions 
( vs ), 
so we need stuff specific for converted constant expressions. E.g., 
`float{__FLT_DENORM_MIN__ / 4.0}` is not a narrowing conversion even though it 
rounds the double value to `0.0f`, but it shouldn't be a converted constant 
expression.

Theoretically we should only be calling `getNarrowingKind` when `SCS->Second == 
ICK_Integral_Conversion` (I think we also use it for boolean conversions 
[CWG1407](https://cplusplus.github.io/CWG/issues/1407.html)).

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


[clang] [Clang] Reuse tail-padding for more types that are not POD for the purpose of layout (PR #90462)

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

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

This will be done for types with over-large bitfields and 
potentially-overlapping ([[no_unique_address]]) members

Compatible with old Clang 18 semantics with -fclang-abi-compat

Fixes #50766

>From 96ff21d5126ebb4b9a538b8eef11f8ac9e2194c5 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Mon, 29 Apr 2024 12:27:04 +0100
Subject: [PATCH] [Clang] Reuse tail-padding for more types that are not POD
 for the purpose of layout

This will be done for types with over-large bitfields and 
potentially-overlapping ([[no_unique_address]]) members

Compatible with old Clang 18 semantics with -fclang-abi-compat

Fixes #50766
---
 clang/docs/ReleaseNotes.rst |   3 +
 clang/include/clang/Basic/LangOptions.h |   4 +-
 clang/include/clang/Basic/TargetCXXABI.h|  51 
 clang/lib/AST/RecordLayoutBuilder.cpp   | 134 +++-
 clang/test/CodeGenCXX/bitfield-layout.cpp   |  20 ++-
 clang/test/CodeGenCXX/no-unique-address.cpp |   9 +-
 clang/test/Layout/no-unique-address.cpp |  20 ++-
 7 files changed, 138 insertions(+), 103 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 604782ca43dd54..b5d76c95a24bd1 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -63,6 +63,9 @@ ABI Changes in This Version
   MSVC uses a different mangling for these objects, compatibility is not 
affected.
   (#GH85423).
 
+- Fixed tail padding not being reused on types with oversized bit-fields and
+  potentially-overlapping members (#GH50766).
+
 AST Dumping Potentially Breaking Changes
 
 
diff --git a/clang/include/clang/Basic/LangOptions.h 
b/clang/include/clang/Basic/LangOptions.h
index e2a2aa71b880b3..3fe1362a2d767e 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -233,7 +233,9 @@ class LangOptionsBase {
 
 /// Attempt to be ABI-compatible with code generated by Clang 18.0.x.
 /// This causes clang to revert some fixes to the mangling of lambdas
-/// in the initializers of members of local classes.
+/// in the initializers of members of local classes and will not reuse
+/// tail padding on structs with potentially-overlapping members or
+/// oversized bit-fields under Itanium and some derived ABIs.
 Ver18,
 
 /// Conform to the underlying platform's C and C++ ABIs as closely
diff --git a/clang/include/clang/Basic/TargetCXXABI.h 
b/clang/include/clang/Basic/TargetCXXABI.h
index c113a6a048ad44..45d9dcc8f1b8a8 100644
--- a/clang/include/clang/Basic/TargetCXXABI.h
+++ b/clang/include/clang/Basic/TargetCXXABI.h
@@ -255,57 +255,6 @@ class TargetCXXABI {
 llvm_unreachable("bad ABI kind");
   }
 
-  /// When is record layout allowed to allocate objects in the tail
-  /// padding of a base class?
-  ///
-  /// This decision cannot be changed without breaking platform ABI
-  /// compatibility. In ISO C++98, tail padding reuse was only permitted for
-  /// non-POD base classes, but that restriction was removed retroactively by
-  /// DR 43, and tail padding reuse is always permitted in all de facto C++
-  /// language modes. However, many platforms use a variant of the old C++98
-  /// rule for compatibility.
-  enum TailPaddingUseRules {
-/// The tail-padding of a base class is always theoretically
-/// available, even if it's POD.
-AlwaysUseTailPadding,
-
-/// Only allocate objects in the tail padding of a base class if
-/// the base class is not POD according to the rules of C++ TR1.
-UseTailPaddingUnlessPOD03,
-
-/// Only allocate objects in the tail padding of a base class if
-/// the base class is not POD according to the rules of C++11.
-UseTailPaddingUnlessPOD11
-  };
-  TailPaddingUseRules getTailPaddingUseRules() const {
-switch (getKind()) {
-// To preserve binary compatibility, the generic Itanium ABI has
-// permanently locked the definition of POD to the rules of C++ TR1,
-// and that trickles down to derived ABIs.
-case GenericItanium:
-case GenericAArch64:
-case GenericARM:
-case iOS:
-case GenericMIPS:
-case XL:
-  return UseTailPaddingUnlessPOD03;
-
-// AppleARM64 and WebAssembly use the C++11 POD rules.  They do not honor
-// the Itanium exception about classes with over-large bitfields.
-case AppleARM64:
-case Fuchsia:
-case WebAssembly:
-case WatchOS:
-  return UseTailPaddingUnlessPOD11;
-
-// MSVC always allocates fields in the tail-padding of a base class
-// subobject, even if they're POD.
-case Microsoft:
-  return AlwaysUseTailPadding;
-}
-llvm_unreachable("bad ABI kind");
-  }
-
   friend bool operator==(const TargetCXXABI , const TargetCXXABI ) {
 return left.getKind() == right.getKind();
   }
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp 

[clang] [clang] Implement CWG2851: floating-point conversions in converted constant expressions (PR #90387)

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

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

>From 77cb28e6faf95f5beb3fadc225cb5f0525b3dfe6 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 28 Apr 2024 09:48:47 +0100
Subject: [PATCH] [clang] Implement CWG2851: floating-point conversions in
 converted constant expressions

---
 clang/docs/ReleaseNotes.rst   |  3 +
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/lib/Sema/SemaOverload.cpp   | 38 ++-
 clang/test/CXX/drs/dr28xx.cpp | 64 +++
 clang/www/cxx_dr_status.html  |  2 +-
 5 files changed, 107 insertions(+), 4 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 604782ca43dd54..6fb0b2d1030be8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -166,6 +166,9 @@ Resolutions to C++ Defect Reports
 - Clang now diagnoses declarative nested-name-specifiers with 
pack-index-specifiers.
   (`CWG2858: Declarative nested-name-specifiers and pack-index-specifiers 
`_).
 
+- Allow floating-point promotions and conversions in converted constant 
expressions.
+  (`CWG2851 Allow floating-point conversions in converted constant expressions 
`_).
+
 C Language Changes
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index fdca82934cb4dc..cb248f2ea6374b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -85,6 +85,10 @@ def err_expr_not_cce : Error<
   "%select{case value|enumerator value|non-type template argument|"
   "array size|explicit specifier argument|noexcept specifier argument|"
   "call to 'size()'|call to 'data()'}0 is not a constant expression">;
+def err_float_conv_cant_represent : Error<
+  "non-type template argument evaluates to %0 which cannot be "
+  "exactly represented in type %1"
+>;
 def ext_cce_narrowing : ExtWarn<
   "%select{case value|enumerator value|non-type template argument|"
   "array size|explicit specifier argument|noexcept specifier argument|"
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 04cd9e78739d20..40d65638e3afc1 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6072,6 +6072,10 @@ static bool CheckConvertedConstantConversions(Sema ,
   case ICK_Integral_Promotion:
   case ICK_Integral_Conversion: // Narrowing conversions are checked elsewhere.
   case ICK_Zero_Queue_Conversion:
+  // Per CWG2851, floating-point promotions and conversions are allowed.
+  // The value of a conversion is checked afterwards.
+  case ICK_Floating_Promotion:
+  case ICK_Floating_Conversion:
 return true;
 
   case ICK_Boolean_Conversion:
@@ -6091,9 +6095,7 @@ static bool CheckConvertedConstantConversions(Sema ,
 // only permitted if the source type is std::nullptr_t.
 return SCS.getFromType()->isNullPtrType();
 
-  case ICK_Floating_Promotion:
   case ICK_Complex_Promotion:
-  case ICK_Floating_Conversion:
   case ICK_Complex_Conversion:
   case ICK_Floating_Integral:
   case ICK_Compatible_Conversion:
@@ -6229,7 +6231,37 @@ static ExprResult BuildConvertedConstantExpression(Sema 
, Expr *From,
   if (Result.isInvalid())
 return Result;
 
-  // Check for a narrowing implicit conversion.
+  if (SCS->Second == ICK_Floating_Conversion) {
+// Unlike with narrowing conversions, the value must fit
+// exactly even if it is in range
+assert(CCE == Sema::CCEKind::CCEK_TemplateArg &&
+   "Only non-type template args should use floating-point 
conversions");
+
+// Initializer is From, except it is a full-expression
+const Expr *Initializer =
+IgnoreNarrowingConversion(S.Context, Result.get());
+
+// If it's value-dependent, we can't tell whether it will fit
+if (Initializer->isValueDependent())
+  return Result;
+
+// Not-constant diagnosed afterwards
+if (!Initializer->isCXX11ConstantExpr(S.Context, ))
+  return Result;
+
+llvm::APFloat PostNarrowingValue = PreNarrowingValue.getFloat();
+bool LosesInfo = true;
+PostNarrowingValue.convert(S.Context.getFloatTypeSemantics(T),
+   llvm::APFloat::rmNearestTiesToEven, );
+
+if (LosesInfo)
+  S.Diag(From->getBeginLoc(), diag::err_float_conv_cant_represent)
+  << PreNarrowingValue.getAsString(S.Context, From->getType()) << T;
+
+return Result;
+  }
+
+  // Check for a narrowing integer conversion.
   bool ReturnPreNarrowingValue = false;
   QualType PreNarrowingType;
   switch (SCS->getNarrowingKind(S.Context, Result.get(), PreNarrowingValue,
diff --git a/clang/test/CXX/drs/dr28xx.cpp b/clang/test/CXX/drs/dr28xx.cpp
index be35d366bdd614..9076598da14185 100644
--- a/clang/test/CXX/drs/dr28xx.cpp
+++ 

[clang] [Clang] Ensure "=default"ed function can be deleted when used as an extension in C++03 (PR #90725)

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


@@ -9767,7 +9767,9 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD,
 return false;
   CXXRecordDecl *RD = MD->getParent();
   assert(!RD->isDependentType() && "do deletion after instantiation");
-  if (!LangOpts.CPlusPlus || (!LangOpts.CPlusPlus11 && !RD->isLambda()) ||
+  if (!LangOpts.CPlusPlus ||

MitalAshok wrote:

I wouldn't think so since we have a CXXMethodDecl and CXXRecordDecl. It was 
added with #73376 which changed it from`!CPlusPlus11` when adding C++03 lambdas

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


[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

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

MitalAshok wrote:

This is [CWG2084](https://wg21.link/CWG2084). Could you also add some tests to 
CXX/drs/ so that www/cxx_dr_status.html can be updated?

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


[clang] [Clang] Ensure "=default"ed function can be deleted when used as an extension in C++03 (PR #90725)

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

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

>From 0793795ba7d5d5974b1403cd6ead0221fc20c5bb Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Wed, 1 May 2024 12:45:54 +0100
Subject: [PATCH 1/3] [Clang] Ensure "=default"ed function can be deleted when
 used as an extension in C++03

Fixes #90605
---
 clang/lib/Sema/SemaDeclCXX.cpp|  4 ++-
 .../SemaCXX/cxx0x-cursory-default-delete.cpp  | 34 +--
 .../SemaCXX/cxx0x-defaulted-functions.cpp | 13 +++
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 157d42c09cfcd8..e3c90c8ee1d644 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9767,7 +9767,9 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD,
 return false;
   CXXRecordDecl *RD = MD->getParent();
   assert(!RD->isDependentType() && "do deletion after instantiation");
-  if (!LangOpts.CPlusPlus || (!LangOpts.CPlusPlus11 && !RD->isLambda()) ||
+  if (!LangOpts.CPlusPlus ||
+  (!LangOpts.CPlusPlus11 && !RD->isLambda() &&
+   !MD->isExplicitlyDefaulted()) ||
   RD->isInvalidDecl())
 return false;
 
diff --git a/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp 
b/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
index 6ae146f0d08c7d..f884725a234671 100644
--- a/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
+++ b/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
@@ -1,4 +1,11 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++03 -Wno-c++11-extensions -fsyntax-only -verify %s
+
+#if __cplusplus < 201103L
+#define static_assert _Static_assert
+#define nullptr 0
+#define noexcept throw()
+#endif
 
 struct non_copiable {
   non_copiable(const non_copiable&) = delete; // expected-note {{marked 
deleted here}}
@@ -25,10 +32,12 @@ void fn1 () {
   non_const_copy ncc;
   non_const_copy ncc2 = ncc;
   ncc = ncc2;
+#if __cplusplus >= 201103L
   const non_const_copy cncc{};
+#endif
   const non_const_copy cncc1; // expected-error {{default initialization of an 
object of const type 'const non_const_copy' without a user-provided default 
constructor}}
-  non_const_copy ncc3 = cncc; // expected-error {{no matching}}
-  ncc = cncc; // expected-error {{no viable overloaded}}
+  non_const_copy ncc3 = cncc1; // expected-error {{no matching}}
+  ncc = cncc1; // expected-error {{no viable overloaded}}
 };
 
 struct no_fields { };
@@ -196,7 +205,7 @@ struct except_spec_d_match : except_spec_a, except_spec_b {
 struct S { S(); };
 S::S() __attribute((noreturn)) = default;
 
-using size_t = decltype(sizeof(0));
+using size_t = __SIZE_TYPE__;
 void *operator new(size_t) = delete; // expected-error {{deleted definition 
must be first declaration}} expected-note {{implicit}}
 void operator delete(void *) noexcept = delete; // expected-error {{deleted 
definition must be first declaration}} expected-note {{implicit}}
 
@@ -217,3 +226,22 @@ namespace deleted_overrides_deleted {
   template struct B : A { virtual void f() = delete; };
   template struct B;
 }
+
+namespace GH90605 {
+struct Element {
+Element& operator=(const Element&) = delete; // #GH90605-Element-assign
+};
+
+struct S {
+Element i; // #GH90605-i
+
+S& operator=(const S&) = default;
+// expected-warning@-1 {{explicitly defaulted copy assignment operator is 
implicitly deleted}}
+//   expected-note@#GH90605-i {{copy assignment operator of 'S' is implicitly 
deleted because field 'i' has a deleted copy assignment operator}}
+//   expected-note@#GH90605-Element-assign {{'operator=' has been explicitly 
marked deleted here}}
+//   expected-note@-4 {{replace 'default' with 'delete'}}
+};
+
+static_assert(!__is_trivially_assignable(S&, const S&), "");
+static_assert(!__is_assignable(S&, const S&), "");
+}
diff --git a/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp 
b/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
index 0c3dd1ea7aa274..30d54920a1a686 100644
--- a/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
+++ b/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
@@ -1,4 +1,9 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -fcxx-exceptions 
-Wno-deprecated-builtins %s
+// RUN: %clang_cc1 -std=c++03 -Wno-c++11-extensions -fsyntax-only -verify 
-fcxx-exceptions -Wno-deprecated-builtins %s
+
+#if __cplusplus < 201103L
+#define static_assert _Static_assert
+#endif
 
 void fn() = default; // expected-error {{only special member}}
 struct foo {
@@ -43,6 +48,7 @@ void tester() {
   b = c;
 }
 
+#if __cplusplus >= 201103L
 template struct S : T {
   constexpr S() = default; // expected-note {{previous declaration is 
here}}
   constexpr S(const S&) = default; // expected-note {{previous declaration is 
here}}
@@ -118,6 +124,7 @@ namespace DefaultedFnExceptionSpec {
 *p = *p; // expected-note {{instantiation of}}
   }
 }
+#endif
 
 namespace PR13527 {
   struct X {
@@ -135,6 

[clang] [Clang] Ensure "=default"ed function can be deleted when used as an extension in C++03 (PR #90725)

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

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

>From 0793795ba7d5d5974b1403cd6ead0221fc20c5bb Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Wed, 1 May 2024 12:45:54 +0100
Subject: [PATCH 1/2] [Clang] Ensure "=default"ed function can be deleted when
 used as an extension in C++03

Fixes #90605
---
 clang/lib/Sema/SemaDeclCXX.cpp|  4 ++-
 .../SemaCXX/cxx0x-cursory-default-delete.cpp  | 34 +--
 .../SemaCXX/cxx0x-defaulted-functions.cpp | 13 +++
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 157d42c09cfcd8..e3c90c8ee1d644 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9767,7 +9767,9 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD,
 return false;
   CXXRecordDecl *RD = MD->getParent();
   assert(!RD->isDependentType() && "do deletion after instantiation");
-  if (!LangOpts.CPlusPlus || (!LangOpts.CPlusPlus11 && !RD->isLambda()) ||
+  if (!LangOpts.CPlusPlus ||
+  (!LangOpts.CPlusPlus11 && !RD->isLambda() &&
+   !MD->isExplicitlyDefaulted()) ||
   RD->isInvalidDecl())
 return false;
 
diff --git a/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp 
b/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
index 6ae146f0d08c7d..f884725a234671 100644
--- a/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
+++ b/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
@@ -1,4 +1,11 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++03 -Wno-c++11-extensions -fsyntax-only -verify %s
+
+#if __cplusplus < 201103L
+#define static_assert _Static_assert
+#define nullptr 0
+#define noexcept throw()
+#endif
 
 struct non_copiable {
   non_copiable(const non_copiable&) = delete; // expected-note {{marked 
deleted here}}
@@ -25,10 +32,12 @@ void fn1 () {
   non_const_copy ncc;
   non_const_copy ncc2 = ncc;
   ncc = ncc2;
+#if __cplusplus >= 201103L
   const non_const_copy cncc{};
+#endif
   const non_const_copy cncc1; // expected-error {{default initialization of an 
object of const type 'const non_const_copy' without a user-provided default 
constructor}}
-  non_const_copy ncc3 = cncc; // expected-error {{no matching}}
-  ncc = cncc; // expected-error {{no viable overloaded}}
+  non_const_copy ncc3 = cncc1; // expected-error {{no matching}}
+  ncc = cncc1; // expected-error {{no viable overloaded}}
 };
 
 struct no_fields { };
@@ -196,7 +205,7 @@ struct except_spec_d_match : except_spec_a, except_spec_b {
 struct S { S(); };
 S::S() __attribute((noreturn)) = default;
 
-using size_t = decltype(sizeof(0));
+using size_t = __SIZE_TYPE__;
 void *operator new(size_t) = delete; // expected-error {{deleted definition 
must be first declaration}} expected-note {{implicit}}
 void operator delete(void *) noexcept = delete; // expected-error {{deleted 
definition must be first declaration}} expected-note {{implicit}}
 
@@ -217,3 +226,22 @@ namespace deleted_overrides_deleted {
   template struct B : A { virtual void f() = delete; };
   template struct B;
 }
+
+namespace GH90605 {
+struct Element {
+Element& operator=(const Element&) = delete; // #GH90605-Element-assign
+};
+
+struct S {
+Element i; // #GH90605-i
+
+S& operator=(const S&) = default;
+// expected-warning@-1 {{explicitly defaulted copy assignment operator is 
implicitly deleted}}
+//   expected-note@#GH90605-i {{copy assignment operator of 'S' is implicitly 
deleted because field 'i' has a deleted copy assignment operator}}
+//   expected-note@#GH90605-Element-assign {{'operator=' has been explicitly 
marked deleted here}}
+//   expected-note@-4 {{replace 'default' with 'delete'}}
+};
+
+static_assert(!__is_trivially_assignable(S&, const S&), "");
+static_assert(!__is_assignable(S&, const S&), "");
+}
diff --git a/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp 
b/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
index 0c3dd1ea7aa274..30d54920a1a686 100644
--- a/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
+++ b/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
@@ -1,4 +1,9 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -fcxx-exceptions 
-Wno-deprecated-builtins %s
+// RUN: %clang_cc1 -std=c++03 -Wno-c++11-extensions -fsyntax-only -verify 
-fcxx-exceptions -Wno-deprecated-builtins %s
+
+#if __cplusplus < 201103L
+#define static_assert _Static_assert
+#endif
 
 void fn() = default; // expected-error {{only special member}}
 struct foo {
@@ -43,6 +48,7 @@ void tester() {
   b = c;
 }
 
+#if __cplusplus >= 201103L
 template struct S : T {
   constexpr S() = default; // expected-note {{previous declaration is 
here}}
   constexpr S(const S&) = default; // expected-note {{previous declaration is 
here}}
@@ -118,6 +124,7 @@ namespace DefaultedFnExceptionSpec {
 *p = *p; // expected-note {{instantiation of}}
   }
 }
+#endif
 
 namespace PR13527 {
   struct X {
@@ -135,6 

[clang] [Clang] Ensure "=default"ed function can be deleted when used as an extension in C++03 (PR #90725)

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

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


[clang] [Clang][Sema] Fix incorrect rejection default construction of union with nontrivial member (PR #82407)

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


@@ -9442,9 +9442,21 @@ bool 
SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
 
   int DiagKind = -1;
 
-  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
-DiagKind = !Decl ? 0 : 1;
-  else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
+if (CSM == Sema::CXXDefaultConstructor && Field &&
+Field->getParent()->isUnion()) {
+  // [class.default.ctor]p2:
+  //   A defaulted default constructor for class X is defined as deleted if
+  //   - X is a union that has a variant member with a non-trivial default
+  // constructor and no variant member of X has a default member
+  // initializer
+  const auto *RD = cast(Field->getParent());
+  if (!RD->hasInClassInitializer())
+DiagKind = !Decl ? 0 : 1;

MitalAshok wrote:

You can refactor it like this: 
https://github.com/MitalAshok/llvm-project/commit/a119d89788c2c642b5a13ea00b2ea649b04a418e
 and I would suggest changing to an enum for readability: 
https://github.com/MitalAshok/llvm-project/commit/38ca82e1a55012e7d37fd8c6d049d1f00bb50835
 (This can then be extracted out into a static function that returns the enum 
and each `DiagKind = ...` can turn into `return ...`, and the `if`/`else if` 
ladder can be dismantled)

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


[clang] [Clang] Ensure "=default"ed function can be deleted when used as an extension in C++03 (PR #90725)

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

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

>From 0793795ba7d5d5974b1403cd6ead0221fc20c5bb Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Wed, 1 May 2024 12:45:54 +0100
Subject: [PATCH 1/2] [Clang] Ensure "=default"ed function can be deleted when
 used as an extension in C++03

Fixes #90605
---
 clang/lib/Sema/SemaDeclCXX.cpp|  4 ++-
 .../SemaCXX/cxx0x-cursory-default-delete.cpp  | 34 +--
 .../SemaCXX/cxx0x-defaulted-functions.cpp | 13 +++
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 157d42c09cfcd8..e3c90c8ee1d644 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9767,7 +9767,9 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD,
 return false;
   CXXRecordDecl *RD = MD->getParent();
   assert(!RD->isDependentType() && "do deletion after instantiation");
-  if (!LangOpts.CPlusPlus || (!LangOpts.CPlusPlus11 && !RD->isLambda()) ||
+  if (!LangOpts.CPlusPlus ||
+  (!LangOpts.CPlusPlus11 && !RD->isLambda() &&
+   !MD->isExplicitlyDefaulted()) ||
   RD->isInvalidDecl())
 return false;
 
diff --git a/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp 
b/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
index 6ae146f0d08c7d..f884725a234671 100644
--- a/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
+++ b/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
@@ -1,4 +1,11 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++03 -Wno-c++11-extensions -fsyntax-only -verify %s
+
+#if __cplusplus < 201103L
+#define static_assert _Static_assert
+#define nullptr 0
+#define noexcept throw()
+#endif
 
 struct non_copiable {
   non_copiable(const non_copiable&) = delete; // expected-note {{marked 
deleted here}}
@@ -25,10 +32,12 @@ void fn1 () {
   non_const_copy ncc;
   non_const_copy ncc2 = ncc;
   ncc = ncc2;
+#if __cplusplus >= 201103L
   const non_const_copy cncc{};
+#endif
   const non_const_copy cncc1; // expected-error {{default initialization of an 
object of const type 'const non_const_copy' without a user-provided default 
constructor}}
-  non_const_copy ncc3 = cncc; // expected-error {{no matching}}
-  ncc = cncc; // expected-error {{no viable overloaded}}
+  non_const_copy ncc3 = cncc1; // expected-error {{no matching}}
+  ncc = cncc1; // expected-error {{no viable overloaded}}
 };
 
 struct no_fields { };
@@ -196,7 +205,7 @@ struct except_spec_d_match : except_spec_a, except_spec_b {
 struct S { S(); };
 S::S() __attribute((noreturn)) = default;
 
-using size_t = decltype(sizeof(0));
+using size_t = __SIZE_TYPE__;
 void *operator new(size_t) = delete; // expected-error {{deleted definition 
must be first declaration}} expected-note {{implicit}}
 void operator delete(void *) noexcept = delete; // expected-error {{deleted 
definition must be first declaration}} expected-note {{implicit}}
 
@@ -217,3 +226,22 @@ namespace deleted_overrides_deleted {
   template struct B : A { virtual void f() = delete; };
   template struct B;
 }
+
+namespace GH90605 {
+struct Element {
+Element& operator=(const Element&) = delete; // #GH90605-Element-assign
+};
+
+struct S {
+Element i; // #GH90605-i
+
+S& operator=(const S&) = default;
+// expected-warning@-1 {{explicitly defaulted copy assignment operator is 
implicitly deleted}}
+//   expected-note@#GH90605-i {{copy assignment operator of 'S' is implicitly 
deleted because field 'i' has a deleted copy assignment operator}}
+//   expected-note@#GH90605-Element-assign {{'operator=' has been explicitly 
marked deleted here}}
+//   expected-note@-4 {{replace 'default' with 'delete'}}
+};
+
+static_assert(!__is_trivially_assignable(S&, const S&), "");
+static_assert(!__is_assignable(S&, const S&), "");
+}
diff --git a/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp 
b/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
index 0c3dd1ea7aa274..30d54920a1a686 100644
--- a/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
+++ b/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
@@ -1,4 +1,9 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -fcxx-exceptions 
-Wno-deprecated-builtins %s
+// RUN: %clang_cc1 -std=c++03 -Wno-c++11-extensions -fsyntax-only -verify 
-fcxx-exceptions -Wno-deprecated-builtins %s
+
+#if __cplusplus < 201103L
+#define static_assert _Static_assert
+#endif
 
 void fn() = default; // expected-error {{only special member}}
 struct foo {
@@ -43,6 +48,7 @@ void tester() {
   b = c;
 }
 
+#if __cplusplus >= 201103L
 template struct S : T {
   constexpr S() = default; // expected-note {{previous declaration is 
here}}
   constexpr S(const S&) = default; // expected-note {{previous declaration is 
here}}
@@ -118,6 +124,7 @@ namespace DefaultedFnExceptionSpec {
 *p = *p; // expected-note {{instantiation of}}
   }
 }
+#endif
 
 namespace PR13527 {
   struct X {
@@ -135,6 

[clang] [Clang] No longer require complete types with __builtin_launder (PR #91070)

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

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

Incomplete types are assumed to need the llvm.launder.invariant.group intrinsic

Fixes #90949

>From 21d9f27692b2a2fa9ac99f4644109e62e3730133 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sat, 4 May 2024 17:31:31 +0100
Subject: [PATCH] [Clang] No longer require complete types with
 __builtin_launder

Incomplete types are assumed to need the llvm.launder.invariant.group intrinsic

Fixes #90949
---
 clang/docs/ReleaseNotes.rst   |  2 +
 clang/lib/CodeGen/CGBuiltin.cpp   |  5 +-
 clang/lib/Sema/SemaChecking.cpp   | 20 +---
 clang/test/CodeGenCXX/builtin-launder.cpp | 56 +++
 clang/test/SemaCXX/builtins.cpp   | 14 --
 5 files changed, 73 insertions(+), 24 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 54b58b1ae99fbd..e22a80a6f281c9 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -552,6 +552,8 @@ Bug Fixes in This Version
 - Clang will no longer emit a duplicate -Wunused-value warning for an 
expression
   `(A, B)` which evaluates to glvalue `B` that can be converted to non 
ODR-use. (#GH45783)
 
+- `__builtin_launder` no longer requires a pointer to a complete type. 
(#GH90949)
+
 Bug Fixes to Compiler Builtins
 ^^
 
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 8e31652f4dabef..6a544f97cac5e2 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -2487,8 +2487,9 @@ TypeRequiresBuiltinLaunderImp(const ASTContext , 
QualType Ty,
   if (!Seen.insert(Record).second)
 return false;
 
-  assert(Record->hasDefinition() &&
- "Incomplete types should already be diagnosed");
+  // Assume incomplete types need to be laundered
+  if (!Record->hasDefinition())
+return true;
 
   if (Record->isDynamicClass())
 return true;
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 3179d542b1f926..c2eb5b51975c1a 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2164,15 +2164,7 @@ static ExprResult BuiltinLaunder(Sema , CallExpr 
*TheCall) {
   //  * The type of the argument if it's not an array or function type,
   //  Otherwise,
   //  * The decayed argument type.
-  QualType ParamTy = [&]() {
-QualType ArgTy = TheCall->getArg(0)->getType();
-if (const ArrayType *Ty = ArgTy->getAsArrayTypeUnsafe())
-  return S.Context.getPointerType(Ty->getElementType());
-if (ArgTy->isFunctionType()) {
-  return S.Context.getPointerType(ArgTy);
-}
-return ArgTy;
-  }();
+  QualType ParamTy = 
S.Context.getAdjustedParameterType(TheCall->getArg(0)->getType());
 
   TheCall->setType(ParamTy);
 
@@ -2191,16 +2183,6 @@ static ExprResult BuiltinLaunder(Sema , CallExpr 
*TheCall) {
 return ExprError();
   }
 
-  // We either have an incomplete class type, or we have a class template
-  // whose instantiation has not been forced. Example:
-  //
-  //   template  struct Foo { T value; };
-  //   Foo *p = nullptr;
-  //   auto *d = __builtin_launder(p);
-  if (S.RequireCompleteType(TheCall->getBeginLoc(), ParamTy->getPointeeType(),
-diag::err_incomplete_type))
-return ExprError();
-
   assert(ParamTy->getPointeeType()->isObjectType() &&
  "Unhandled non-object pointer case");
 
diff --git a/clang/test/CodeGenCXX/builtin-launder.cpp 
b/clang/test/CodeGenCXX/builtin-launder.cpp
index 06a93d1c441d29..8cfbc3101e30d3 100644
--- a/clang/test/CodeGenCXX/builtin-launder.cpp
+++ b/clang/test/CodeGenCXX/builtin-launder.cpp
@@ -53,10 +53,66 @@ extern "C" void 
test_builtin_launder_virtual_base(TestVirtualBase *p) {
   TestVirtualBase *d = __builtin_launder(p);
 }
 
+struct IncompleteNeedsLaunder;
+
+// CHECK-LABEL: define{{.*}} void 
@test_builtin_launder_incomplete_later_needs_launder
+extern "C" void 
test_builtin_launder_incomplete_later_needs_launder(IncompleteNeedsLaunder *p) {
+  // CHECK-STRICT-NOT: ret void
+  // CHECK-STRICT: @llvm.launder.invariant.group
+
+  // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group
+
+  // CHECK: ret void
+  IncompleteNeedsLaunder *d = __builtin_launder(p);
+}
+
+struct IncompleteNeedsLaunder {
+  virtual void foo() {}
+};
+
+// CHECK-LABEL: define{{.*}} void @test_builtin_launder_completed_needs_launder
+extern "C" void 
test_builtin_launder_completed_needs_launder(IncompleteNeedsLaunder *p) {
+  // CHECK-STRICT-NOT: ret void
+  // CHECK-STRICT: @llvm.launder.invariant.group
+
+  // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group
+
+  // CHECK: ret void
+  IncompleteNeedsLaunder *d = __builtin_launder(p);
+}
+
+struct IncompleteDoesntNeedLaunder;
+
+// CHECK-LABEL: define{{.*}} void 
@test_builtin_launder_incomplete_later_doesnt_needs_launder
+extern "C" void 

[clang] [Clang] No longer require complete types with __builtin_launder (PR #91070)

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

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

>From fe8c0dc5f7beacae7b1494a5987c3674dbd330d3 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sat, 4 May 2024 17:31:31 +0100
Subject: [PATCH] [Clang] No longer require complete types with
 __builtin_launder

Incomplete types are assumed to need the llvm.launder.invariant.group intrinsic

Fixes #90949
---
 clang/docs/ReleaseNotes.rst   |  2 +
 clang/lib/CodeGen/CGBuiltin.cpp   |  5 +-
 clang/lib/Sema/SemaChecking.cpp   | 21 +
 clang/test/CodeGenCXX/builtin-launder.cpp | 56 +++
 clang/test/SemaCXX/builtins.cpp   | 14 --
 5 files changed, 74 insertions(+), 24 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 54b58b1ae99fbd..e22a80a6f281c9 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -552,6 +552,8 @@ Bug Fixes in This Version
 - Clang will no longer emit a duplicate -Wunused-value warning for an 
expression
   `(A, B)` which evaluates to glvalue `B` that can be converted to non 
ODR-use. (#GH45783)
 
+- `__builtin_launder` no longer requires a pointer to a complete type. 
(#GH90949)
+
 Bug Fixes to Compiler Builtins
 ^^
 
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 8e31652f4dabef..6a544f97cac5e2 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -2487,8 +2487,9 @@ TypeRequiresBuiltinLaunderImp(const ASTContext , 
QualType Ty,
   if (!Seen.insert(Record).second)
 return false;
 
-  assert(Record->hasDefinition() &&
- "Incomplete types should already be diagnosed");
+  // Assume incomplete types need to be laundered
+  if (!Record->hasDefinition())
+return true;
 
   if (Record->isDynamicClass())
 return true;
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 3179d542b1f926..9ed404f9e7c936 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2164,15 +2164,8 @@ static ExprResult BuiltinLaunder(Sema , CallExpr 
*TheCall) {
   //  * The type of the argument if it's not an array or function type,
   //  Otherwise,
   //  * The decayed argument type.
-  QualType ParamTy = [&]() {
-QualType ArgTy = TheCall->getArg(0)->getType();
-if (const ArrayType *Ty = ArgTy->getAsArrayTypeUnsafe())
-  return S.Context.getPointerType(Ty->getElementType());
-if (ArgTy->isFunctionType()) {
-  return S.Context.getPointerType(ArgTy);
-}
-return ArgTy;
-  }();
+  QualType ParamTy =
+  S.Context.getAdjustedParameterType(TheCall->getArg(0)->getType());
 
   TheCall->setType(ParamTy);
 
@@ -2191,16 +2184,6 @@ static ExprResult BuiltinLaunder(Sema , CallExpr 
*TheCall) {
 return ExprError();
   }
 
-  // We either have an incomplete class type, or we have a class template
-  // whose instantiation has not been forced. Example:
-  //
-  //   template  struct Foo { T value; };
-  //   Foo *p = nullptr;
-  //   auto *d = __builtin_launder(p);
-  if (S.RequireCompleteType(TheCall->getBeginLoc(), ParamTy->getPointeeType(),
-diag::err_incomplete_type))
-return ExprError();
-
   assert(ParamTy->getPointeeType()->isObjectType() &&
  "Unhandled non-object pointer case");
 
diff --git a/clang/test/CodeGenCXX/builtin-launder.cpp 
b/clang/test/CodeGenCXX/builtin-launder.cpp
index 06a93d1c441d29..8cfbc3101e30d3 100644
--- a/clang/test/CodeGenCXX/builtin-launder.cpp
+++ b/clang/test/CodeGenCXX/builtin-launder.cpp
@@ -53,10 +53,66 @@ extern "C" void 
test_builtin_launder_virtual_base(TestVirtualBase *p) {
   TestVirtualBase *d = __builtin_launder(p);
 }
 
+struct IncompleteNeedsLaunder;
+
+// CHECK-LABEL: define{{.*}} void 
@test_builtin_launder_incomplete_later_needs_launder
+extern "C" void 
test_builtin_launder_incomplete_later_needs_launder(IncompleteNeedsLaunder *p) {
+  // CHECK-STRICT-NOT: ret void
+  // CHECK-STRICT: @llvm.launder.invariant.group
+
+  // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group
+
+  // CHECK: ret void
+  IncompleteNeedsLaunder *d = __builtin_launder(p);
+}
+
+struct IncompleteNeedsLaunder {
+  virtual void foo() {}
+};
+
+// CHECK-LABEL: define{{.*}} void @test_builtin_launder_completed_needs_launder
+extern "C" void 
test_builtin_launder_completed_needs_launder(IncompleteNeedsLaunder *p) {
+  // CHECK-STRICT-NOT: ret void
+  // CHECK-STRICT: @llvm.launder.invariant.group
+
+  // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group
+
+  // CHECK: ret void
+  IncompleteNeedsLaunder *d = __builtin_launder(p);
+}
+
+struct IncompleteDoesntNeedLaunder;
+
+// CHECK-LABEL: define{{.*}} void 
@test_builtin_launder_incomplete_later_doesnt_needs_launder
+extern "C" void 
test_builtin_launder_incomplete_later_doesnt_needs_launder(IncompleteDoesntNeedLaunder
 *p) {
+  // CHECK-STRICT-NOT: ret void
+  // CHECK-STRICT: 

[clang] [Clang] No longer require complete types with __builtin_launder (PR #91070)

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

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

>From 11ad517cede0902945c0b7eba0e7f1ff93f08ea0 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sat, 4 May 2024 17:31:31 +0100
Subject: [PATCH] [Clang] No longer require complete types with
 __builtin_launder

Incomplete types are assumed to need the llvm.launder.invariant.group intrinsic

Fixes #90949
---
 clang/docs/ReleaseNotes.rst |  2 +
 clang/lib/CodeGen/CGBuiltin.cpp |  5 +-
 clang/lib/Sema/SemaChecking.cpp | 21 +---
 clang/test/AST/Interp/builtin-functions.cpp | 14 --
 clang/test/CodeGenCXX/builtin-launder.cpp   | 56 +
 clang/test/SemaCXX/builtins.cpp | 14 --
 6 files changed, 85 insertions(+), 27 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 54b58b1ae99fbd..e22a80a6f281c9 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -552,6 +552,8 @@ Bug Fixes in This Version
 - Clang will no longer emit a duplicate -Wunused-value warning for an 
expression
   `(A, B)` which evaluates to glvalue `B` that can be converted to non 
ODR-use. (#GH45783)
 
+- `__builtin_launder` no longer requires a pointer to a complete type. 
(#GH90949)
+
 Bug Fixes to Compiler Builtins
 ^^
 
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 8e31652f4dabef..6a544f97cac5e2 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -2487,8 +2487,9 @@ TypeRequiresBuiltinLaunderImp(const ASTContext , 
QualType Ty,
   if (!Seen.insert(Record).second)
 return false;
 
-  assert(Record->hasDefinition() &&
- "Incomplete types should already be diagnosed");
+  // Assume incomplete types need to be laundered
+  if (!Record->hasDefinition())
+return true;
 
   if (Record->isDynamicClass())
 return true;
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 3179d542b1f926..9ed404f9e7c936 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2164,15 +2164,8 @@ static ExprResult BuiltinLaunder(Sema , CallExpr 
*TheCall) {
   //  * The type of the argument if it's not an array or function type,
   //  Otherwise,
   //  * The decayed argument type.
-  QualType ParamTy = [&]() {
-QualType ArgTy = TheCall->getArg(0)->getType();
-if (const ArrayType *Ty = ArgTy->getAsArrayTypeUnsafe())
-  return S.Context.getPointerType(Ty->getElementType());
-if (ArgTy->isFunctionType()) {
-  return S.Context.getPointerType(ArgTy);
-}
-return ArgTy;
-  }();
+  QualType ParamTy =
+  S.Context.getAdjustedParameterType(TheCall->getArg(0)->getType());
 
   TheCall->setType(ParamTy);
 
@@ -2191,16 +2184,6 @@ static ExprResult BuiltinLaunder(Sema , CallExpr 
*TheCall) {
 return ExprError();
   }
 
-  // We either have an incomplete class type, or we have a class template
-  // whose instantiation has not been forced. Example:
-  //
-  //   template  struct Foo { T value; };
-  //   Foo *p = nullptr;
-  //   auto *d = __builtin_launder(p);
-  if (S.RequireCompleteType(TheCall->getBeginLoc(), ParamTy->getPointeeType(),
-diag::err_incomplete_type))
-return ExprError();
-
   assert(ParamTy->getPointeeType()->isObjectType() &&
  "Unhandled non-object pointer case");
 
diff --git a/clang/test/AST/Interp/builtin-functions.cpp 
b/clang/test/AST/Interp/builtin-functions.cpp
index 0cbab1fcd91d09..efb2c5f825932e 100644
--- a/clang/test/AST/Interp/builtin-functions.cpp
+++ b/clang/test/AST/Interp/builtin-functions.cpp
@@ -457,16 +457,24 @@ void f() {
   static_assert(test_in_constexpr(i), "");
 }
 
-struct Incomplete; // both-note {{forward declaration}}
+struct Incomplete;
 struct IncompleteMember {
   Incomplete 
 };
 void test_incomplete(Incomplete *i, IncompleteMember *im) {
-  // both-error@+1 {{incomplete type 'Incomplete' where a complete type is 
required}}
-  __builtin_launder(i);
+  __builtin_launder(i); // OK
   __builtin_launder(); // OK
   __builtin_launder(im); // OK
 }
+extern Incomplete incomplete;
+extern IncompleteMember incomplete_member;
+static_assert(test_constexpr_launder() == , "");
+static_assert(test_constexpr_launder(_member) == 
_member, "");
+template struct X { static_assert(false, ""); };
+extern X x;
+static_assert(__builtin_launder(__builtin_addressof(x)) == 
__builtin_addressof(x), "");
+static_assert((test_constexpr_launder)(__builtin_addressof(x)) == 
__builtin_addressof(x), "");
+template<> struct X {};
 
 void test_noexcept(int *i) {
   static_assert(noexcept(__builtin_launder(i)), "");
diff --git a/clang/test/CodeGenCXX/builtin-launder.cpp 
b/clang/test/CodeGenCXX/builtin-launder.cpp
index 06a93d1c441d29..8cfbc3101e30d3 100644
--- a/clang/test/CodeGenCXX/builtin-launder.cpp
+++ b/clang/test/CodeGenCXX/builtin-launder.cpp
@@ -53,10 +53,66 @@ extern "C" void 

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

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

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

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.

>From a5347082aa47a7aa525ece818f91fb6fdd5fdb0c Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Mon, 13 May 2024 16:59:06 +0100
Subject: [PATCH] [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 |  5 ++--
 .../clang/Basic/DiagnosticSemaKinds.td|  2 ++
 clang/lib/AST/DeclCXX.cpp |  6 +
 clang/lib/Parse/ParseDeclCXX.cpp  | 22 +
 clang/lib/Sema/SemaDeclCXX.cpp|  3 ---
 clang/lib/Sema/SemaType.cpp   | 23 +++---
 .../test/SemaCXX/complete-member-pointers.cpp | 24 ++-
 clang/test/SemaCXX/member-pointer-ms.cpp  |  8 +++
 9 files changed, 77 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..45b3b47ed51c5 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,7 @@ 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 

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

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

MitalAshok wrote:

Example of the incompatibility: https://godbolt.org/z/Mn1T57WGb

```c++
struct unspecified_inheritance;
template
struct X {
static_assert(I == sizeof(int unspecified_inheritance::*), "");
};

struct Y : X {};
```

Currently, the `sizeof(int Y::*)` locks down the inheritance model of `Y` as 
single, when MSVC marks it as unspecified.

It was the intent that it should have been unspecified:

https://github.com/llvm/llvm-project/blob/89a080cb79972abae240c226090af9a3094e2269/clang/lib/AST/MicrosoftCXXABI.cpp#L223-L224

But `isParsingBaseSpecifiers()` was set after parsing instead of before.

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-05-13 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] [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
--- 

[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

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

MitalAshok wrote:

You should add a test for mutually recursive functions. I suspect something 
like this doesn't work:

```c++
int non_trivial();
int f(bool b) { return g(!b) + non_trivial(); }
int g(bool b) { return b ? f(b) : 1; }

getFieldTrivial().f(true);  // expected-warning {{...}}
getFieldTrivial().g(true);  // expected-warning {{...}}
```

Since when analyzing `f`, `f` enters the cache as trivial, `g` is analyzed and 
sees `f` in the cache as trivial, so `g` is marked trivial, but then `f` is 
marked as non-trivial (so `g` should have been marked as non-trivial, but is 
marked trivial).

If that is an issue, one way to do this "properly" would be to create a graph, 
and a function is non-trivial if it has a path to a non-trivial function (this 
might be too expensive to implement directly). Or we could special case simple 
recursion only, by changing `TrivialFunctionAnalysisVisitor` to not call 
`isTrivialImpl` for the current function only.

https://github.com/llvm/llvm-project/pull/91876
___
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-05-12 Thread Mital Ashok via cfe-commits

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

None

>From 56aed689dc5825fc5bacc6dfdff58ee0eaf71f82 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 12 May 2024 19:48:24 +0100
Subject: [PATCH 1/2] [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 f955d21169556..e85ec5b2dca14 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 (unsigned ID) const;
 
diff --git a/clang/include/clang/Basic/BuiltinsBase.td 
b/clang/include/clang/Basic/BuiltinsBase.td
index 724747ec76d73..1196b9e15c10d 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 fb913034bd836..6b0a04585928a 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 53238d355ea09..1b558d70f9b48 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 bb4b116fd73ca..39aa32526d2b1 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7095,8 +7095,12 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, 
NamedDecl *NDecl,
   }
 
   // Bail 

[clang] [Clang] Add attribute for consteval builtins; Declare constexpr builtins as constexpr in C++ (PR #91894)

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

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

Also support redeclaring now-constexpr builtins without constexpr

>From 56aed689dc5825fc5bacc6dfdff58ee0eaf71f82 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 12 May 2024 19:48:24 +0100
Subject: [PATCH] [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 f955d21169556..e85ec5b2dca14 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 (unsigned ID) const;
 
diff --git a/clang/include/clang/Basic/BuiltinsBase.td 
b/clang/include/clang/Basic/BuiltinsBase.td
index 724747ec76d73..1196b9e15c10d 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 fb913034bd836..6b0a04585928a 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 53238d355ea09..1b558d70f9b48 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 bb4b116fd73ca..39aa32526d2b1 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7095,8 +7095,12 @@ ExprResult 

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

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

MitalAshok wrote:

This is on top of #91894

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

Currently, this doesn't strictly check "whose complete object's lifetime began 
within `E`". A bunch of the static_asserts I have for objects under 
construction should be ill-formed instead of false, but some of them should be 
true.

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 attribute for consteval builtins; Declare constexpr builtins as constexpr in C++ (PR #91894)

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

MitalAshok wrote:

Currently, GCC's behaviour for builtin function redeclarations is to just 
ignore `constexpr`: . This is slightly 
stricter, allowing non-`constexpr` redeclarations for `constexpr` builtins but 
still disallowing `constexpr` declarations for non-`constexpr` builtins.

[P2641R4 `std::is_within_lifetime`](https://wg21.link/P2641R4) is most likely 
going to be implemented as a `consteval` builtin, which the attribute allows 
implementing easily as a builtin-function with `getConstexprKind() == 
ConstexprSpecKind::Consteval`.

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


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

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

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

Also changes the behaviour of `__builtin_is_layout_compatible`

None of the historic nor the current definition of layout-compatible classes 
mention anything about base classes (other than implicitly through being 
standard-layout) and are defined in terms of members, not direct members.


>From 147f0a7bb7644bd16584f89e02edbdf4abd81855 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Tue, 14 May 2024 08:28:19 +0100
Subject: [PATCH] [Clang] Fix definition of layout-compatible to ignore empty
 classes

Also changes the behaviour of __builtin_is_layout_compatible

None of the historic nor the current definition of layout-compatible classes 
mention anything about base classes (other than implicitly through being 
standard-layout) and are defined in terms of members, not direct members.
---
 clang/include/clang/AST/DeclCXX.h  |  7 
 clang/lib/AST/DeclCXX.cpp  | 36 +
 clang/lib/Sema/SemaChecking.cpp| 63 +-
 clang/test/SemaCXX/type-traits.cpp | 11 ++
 llvm/include/llvm/ADT/STLExtras.h  |  6 +++
 5 files changed, 79 insertions(+), 44 deletions(-)

diff --git a/clang/include/clang/AST/DeclCXX.h 
b/clang/include/clang/AST/DeclCXX.h
index fb52ac804849d..f29592e1e7520 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1229,6 +1229,13 @@ class CXXRecordDecl : public RecordDecl {
   /// C++11 [class]p7, specifically using the C++11 rules without any DRs.
   bool isCXX11StandardLayout() const { return data().IsCXX11StandardLayout; }
 
+  /// If this is a standard-layout class or union per C++11 rules,
+  /// any and all data members will be declared in the same type.
+  ///
+  /// This retrieves the type if this class has any data members,
+  /// or the current class if there is no class with fields.
+  const CXXRecordDecl *getStandardLayoutBaseWithFields() const;
+
   /// Determine whether this class, or any of its class subobjects,
   /// contains a mutable field.
   bool hasMutableFields() const { return data().HasMutableFields; }
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 75c441293d62e..a101b61ad7392 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -561,6 +561,42 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl 
*Subobj) {
 data().StructuralIfLiteral = false;
 }
 
+const CXXRecordDecl *CXXRecordDecl::getStandardLayoutBaseWithFields() const {
+#ifndef NDEBUG
+  {
+assert(
+isCXX11StandardLayout() &&
+"getStandardLayoutBaseWithFields called on a non-standard-layout 
type");
+unsigned NumberOfBasesWithFields = 0;
+if (!field_empty())
+  ++NumberOfBasesWithFields;
+std::set UniqueBases;
+forallBases([&](const CXXRecordDecl *Base) -> bool {
+  if (!Base->field_empty())
+++NumberOfBasesWithFields;
+  assert(
+  UniqueBases.insert(Base->getCanonicalDecl()).second &&
+  "Standard layout struct has multiple base classes of the same type");
+  return true;
+});
+assert(NumberOfBasesWithFields <= 1 &&
+   "Standard layout struct has fields declared in more than one 
class");
+  }
+#endif
+  if (!field_empty())
+return this;
+  const CXXRecordDecl *Result = this;
+  forallBases([&](const CXXRecordDecl *Base) -> bool {
+if (!Base->field_empty()) {
+  // This is the base where the fields are declared; return early
+  Result = Base;
+  return false;
+}
+return true;
+  });
+  return Result;
+}
+
 bool CXXRecordDecl::hasConstexprDestructor() const {
   auto *Dtor = getDestructor();
   return Dtor ? Dtor->isConstexpr() : defaultedDestructorIsConstexpr();
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index ecd1821651140..acd142c1932ad 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19084,7 +19084,8 @@ void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const 
Expr *RHSExpr,
 static bool isLayoutCompatible(ASTContext , QualType T1, QualType T2);
 
 /// Check if two enumeration types are layout-compatible.
-static bool isLayoutCompatible(ASTContext , EnumDecl *ED1, EnumDecl *ED2) {
+static bool isLayoutCompatible(ASTContext , const EnumDecl *ED1,
+   const EnumDecl *ED2) {
   // C++11 [dcl.enum] p8:
   // Two enumeration types are layout-compatible if they have the same
   // underlying type.
@@ -19095,8 +19096,8 @@ static bool isLayoutCompatible(ASTContext , EnumDecl 
*ED1, EnumDecl *ED2) {
 /// Check if two fields are layout-compatible.
 /// Can be used on union members, which are exempt from alignment requirement
 /// of common initial sequence.
-static bool isLayoutCompatible(ASTContext , FieldDecl *Field1,
-   FieldDecl *Field2,
+static bool isLayoutCompatible(ASTContext , const FieldDecl *Field1,
+   

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

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

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

>From 5908130604728b9aa9b70eeb2523d368df08e68d Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Tue, 14 May 2024 08:28:19 +0100
Subject: [PATCH] [Clang] Fix definition of layout-compatible to ignore empty
 classes

Also changes the behaviour of __builtin_is_layout_compatible

None of the historic nor the current definition of layout-compatible classes 
mention anything about base classes (other than implicitly through being 
standard-layout) and are defined in terms of members, not direct members.
---
 clang/include/clang/AST/DeclCXX.h  |  7 
 clang/lib/AST/DeclCXX.cpp  | 36 +
 clang/lib/Sema/SemaChecking.cpp| 63 +-
 clang/test/SemaCXX/type-traits.cpp | 11 ++
 llvm/include/llvm/ADT/STLExtras.h  |  6 +++
 5 files changed, 79 insertions(+), 44 deletions(-)

diff --git a/clang/include/clang/AST/DeclCXX.h 
b/clang/include/clang/AST/DeclCXX.h
index fb52ac804849d..60a5005c51a5e 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1229,6 +1229,13 @@ class CXXRecordDecl : public RecordDecl {
   /// C++11 [class]p7, specifically using the C++11 rules without any DRs.
   bool isCXX11StandardLayout() const { return data().IsCXX11StandardLayout; }
 
+  /// If this is a standard-layout class or union, any and all data members 
will
+  /// be declared in the same type.
+  ///
+  /// This retrieves the type if this class has any data members,
+  /// or the current class if there is no class with fields.
+  const CXXRecordDecl *getStandardLayoutBaseWithFields() const;
+
   /// Determine whether this class, or any of its class subobjects,
   /// contains a mutable field.
   bool hasMutableFields() const { return data().HasMutableFields; }
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 75c441293d62e..ab032a4595d46 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -561,6 +561,42 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl 
*Subobj) {
 data().StructuralIfLiteral = false;
 }
 
+const CXXRecordDecl *CXXRecordDecl::getStandardLayoutBaseWithFields() const {
+#ifndef NDEBUG
+  {
+assert(
+isStandardLayout() &&
+"getStandardLayoutBaseWithFields called on a non-standard-layout 
type");
+unsigned NumberOfBasesWithFields = 0;
+if (!field_empty())
+  ++NumberOfBasesWithFields;
+std::set UniqueBases;
+forallBases([&](const CXXRecordDecl *Base) -> bool {
+  if (!Base->field_empty())
+++NumberOfBasesWithFields;
+  assert(
+  UniqueBases.insert(Base->getCanonicalDecl()).second &&
+  "Standard layout struct has multiple base classes of the same type");
+  return true;
+});
+assert(NumberOfBasesWithFields <= 1 &&
+   "Standard layout struct has fields declared in more than one 
class");
+  }
+#endif
+  if (!field_empty())
+return this;
+  const CXXRecordDecl *Result = this;
+  forallBases([&](const CXXRecordDecl *Base) -> bool {
+if (!Base->field_empty()) {
+  // This is the base where the fields are declared; return early
+  Result = Base;
+  return false;
+}
+return true;
+  });
+  return Result;
+}
+
 bool CXXRecordDecl::hasConstexprDestructor() const {
   auto *Dtor = getDestructor();
   return Dtor ? Dtor->isConstexpr() : defaultedDestructorIsConstexpr();
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index ecd1821651140..acd142c1932ad 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19084,7 +19084,8 @@ void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const 
Expr *RHSExpr,
 static bool isLayoutCompatible(ASTContext , QualType T1, QualType T2);
 
 /// Check if two enumeration types are layout-compatible.
-static bool isLayoutCompatible(ASTContext , EnumDecl *ED1, EnumDecl *ED2) {
+static bool isLayoutCompatible(ASTContext , const EnumDecl *ED1,
+   const EnumDecl *ED2) {
   // C++11 [dcl.enum] p8:
   // Two enumeration types are layout-compatible if they have the same
   // underlying type.
@@ -19095,8 +19096,8 @@ static bool isLayoutCompatible(ASTContext , EnumDecl 
*ED1, EnumDecl *ED2) {
 /// Check if two fields are layout-compatible.
 /// Can be used on union members, which are exempt from alignment requirement
 /// of common initial sequence.
-static bool isLayoutCompatible(ASTContext , FieldDecl *Field1,
-   FieldDecl *Field2,
+static bool isLayoutCompatible(ASTContext , const FieldDecl *Field1,
+   const FieldDecl *Field2,
bool AreUnionMembers = false) {
   [[maybe_unused]] const Type *Field1Parent =
   Field1->getParent()->getTypeForDecl();
@@ -19139,52 +19140,26 @@ static bool isLayoutCompatible(ASTContext , 
FieldDecl *Field1,
 
 /// Check if two standard-layout structs 

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

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

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

>From 74e133215e7ba9049fb021eb9bbb130347496503 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Tue, 14 May 2024 08:28:19 +0100
Subject: [PATCH] [Clang] Fix definition of layout-compatible to ignore empty
 classes

Also changes the behaviour of __builtin_is_layout_compatible

None of the historic nor the current definition of layout-compatible classes 
mention anything about base classes (other than implicitly through being 
standard-layout) and are defined in terms of members, not direct members.
---
 clang/include/clang/AST/DeclCXX.h  |  7 
 clang/lib/AST/DeclCXX.cpp  | 36 +
 clang/lib/Sema/SemaChecking.cpp| 63 +-
 clang/test/SemaCXX/type-traits.cpp | 11 ++
 llvm/include/llvm/ADT/STLExtras.h  |  6 +++
 5 files changed, 79 insertions(+), 44 deletions(-)

diff --git a/clang/include/clang/AST/DeclCXX.h 
b/clang/include/clang/AST/DeclCXX.h
index fb52ac804849d..f29592e1e7520 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1229,6 +1229,13 @@ class CXXRecordDecl : public RecordDecl {
   /// C++11 [class]p7, specifically using the C++11 rules without any DRs.
   bool isCXX11StandardLayout() const { return data().IsCXX11StandardLayout; }
 
+  /// If this is a standard-layout class or union per C++11 rules,
+  /// any and all data members will be declared in the same type.
+  ///
+  /// This retrieves the type if this class has any data members,
+  /// or the current class if there is no class with fields.
+  const CXXRecordDecl *getStandardLayoutBaseWithFields() const;
+
   /// Determine whether this class, or any of its class subobjects,
   /// contains a mutable field.
   bool hasMutableFields() const { return data().HasMutableFields; }
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 75c441293d62e..a101b61ad7392 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -561,6 +561,42 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl 
*Subobj) {
 data().StructuralIfLiteral = false;
 }
 
+const CXXRecordDecl *CXXRecordDecl::getStandardLayoutBaseWithFields() const {
+#ifndef NDEBUG
+  {
+assert(
+isCXX11StandardLayout() &&
+"getStandardLayoutBaseWithFields called on a non-standard-layout 
type");
+unsigned NumberOfBasesWithFields = 0;
+if (!field_empty())
+  ++NumberOfBasesWithFields;
+std::set UniqueBases;
+forallBases([&](const CXXRecordDecl *Base) -> bool {
+  if (!Base->field_empty())
+++NumberOfBasesWithFields;
+  assert(
+  UniqueBases.insert(Base->getCanonicalDecl()).second &&
+  "Standard layout struct has multiple base classes of the same type");
+  return true;
+});
+assert(NumberOfBasesWithFields <= 1 &&
+   "Standard layout struct has fields declared in more than one 
class");
+  }
+#endif
+  if (!field_empty())
+return this;
+  const CXXRecordDecl *Result = this;
+  forallBases([&](const CXXRecordDecl *Base) -> bool {
+if (!Base->field_empty()) {
+  // This is the base where the fields are declared; return early
+  Result = Base;
+  return false;
+}
+return true;
+  });
+  return Result;
+}
+
 bool CXXRecordDecl::hasConstexprDestructor() const {
   auto *Dtor = getDestructor();
   return Dtor ? Dtor->isConstexpr() : defaultedDestructorIsConstexpr();
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index ecd1821651140..acd142c1932ad 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19084,7 +19084,8 @@ void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const 
Expr *RHSExpr,
 static bool isLayoutCompatible(ASTContext , QualType T1, QualType T2);
 
 /// Check if two enumeration types are layout-compatible.
-static bool isLayoutCompatible(ASTContext , EnumDecl *ED1, EnumDecl *ED2) {
+static bool isLayoutCompatible(ASTContext , const EnumDecl *ED1,
+   const EnumDecl *ED2) {
   // C++11 [dcl.enum] p8:
   // Two enumeration types are layout-compatible if they have the same
   // underlying type.
@@ -19095,8 +19096,8 @@ static bool isLayoutCompatible(ASTContext , EnumDecl 
*ED1, EnumDecl *ED2) {
 /// Check if two fields are layout-compatible.
 /// Can be used on union members, which are exempt from alignment requirement
 /// of common initial sequence.
-static bool isLayoutCompatible(ASTContext , FieldDecl *Field1,
-   FieldDecl *Field2,
+static bool isLayoutCompatible(ASTContext , const FieldDecl *Field1,
+   const FieldDecl *Field2,
bool AreUnionMembers = false) {
   [[maybe_unused]] const Type *Field1Parent =
   Field1->getParent()->getTypeForDecl();
@@ -19139,52 +19140,26 @@ static bool isLayoutCompatible(ASTContext , 
FieldDecl *Field1,
 
 /// Check if two 

[clang] [Clang] Add attribute for consteval builtin functions (PR #91894)

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

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


[clang] [Clang] Add attribute for consteval builtins; Declare constexpr builtins as constexpr in C++ (PR #91894)

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

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

>From 56aed689dc5825fc5bacc6dfdff58ee0eaf71f82 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 12 May 2024 19:48:24 +0100
Subject: [PATCH 1/3] [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 f955d21169556..e85ec5b2dca14 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 (unsigned ID) const;
 
diff --git a/clang/include/clang/Basic/BuiltinsBase.td 
b/clang/include/clang/Basic/BuiltinsBase.td
index 724747ec76d73..1196b9e15c10d 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 fb913034bd836..6b0a04585928a 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 53238d355ea09..1b558d70f9b48 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 bb4b116fd73ca..39aa32526d2b1 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7095,8 +7095,12 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, 
NamedDecl *NDecl,
   }
 
   // Bail out 

[clang] [Clang] Add attribute for consteval builtins; Declare constexpr builtins as constexpr in C++ (PR #91894)

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

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

>From 56aed689dc5825fc5bacc6dfdff58ee0eaf71f82 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 12 May 2024 19:48:24 +0100
Subject: [PATCH 1/3] [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 f955d21169556..e85ec5b2dca14 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 (unsigned ID) const;
 
diff --git a/clang/include/clang/Basic/BuiltinsBase.td 
b/clang/include/clang/Basic/BuiltinsBase.td
index 724747ec76d73..1196b9e15c10d 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 fb913034bd836..6b0a04585928a 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 53238d355ea09..1b558d70f9b48 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 bb4b116fd73ca..39aa32526d2b1 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7095,8 +7095,12 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, 
NamedDecl *NDecl,
   }
 
   // Bail out 

[clang] [Clang] Add attribute for consteval builtin functions (PR #91894)

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

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


[clang] [Clang] Add attribute for consteval builtin functions (PR #91894)

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

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

>From 56aed689dc5825fc5bacc6dfdff58ee0eaf71f82 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 12 May 2024 19:48:24 +0100
Subject: [PATCH 1/4] [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 f955d21169556..e85ec5b2dca14 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 (unsigned ID) const;
 
diff --git a/clang/include/clang/Basic/BuiltinsBase.td 
b/clang/include/clang/Basic/BuiltinsBase.td
index 724747ec76d73..1196b9e15c10d 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 fb913034bd836..6b0a04585928a 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 53238d355ea09..1b558d70f9b48 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 bb4b116fd73ca..39aa32526d2b1 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7095,8 +7095,12 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, 
NamedDecl *NDecl,
   }
 
   // Bail out 

[clang] [clang] Add tests for CWG issues regarding completeness of types (PR #92113)

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


@@ -67,6 +63,27 @@ void B::g() requires true;
 
 } // namespace cwg2847
 
+namespace cwg2857 { // cwg2857: 2.7
+struct A {};
+struct B {
+  int operator+(A);
+};
+template 
+struct D;
+
+void f(A* a, D* d) {
+  *d + *a;

MitalAshok wrote:

This wouldn't be an ADL lookup since member functions can't be found via ADL. 
It looks like clang doesn't actually implement CWG2857: 
https://godbolt.org/z/5xdYj7a35 / https://godbolt.org/z/7oqfE5WKW

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


[clang] [clang] Add tests for CWG issues regarding completeness of types (PR #92113)

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

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


[clang] [clang] Add tests for CWG issues regarding completeness of types (PR #92113)

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

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


[clang] [Clang] Add attribute for consteval builtins; Declare constexpr builtins as constexpr in C++ (PR #91894)

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


@@ -14,13 +14,18 @@ void __builtin_va_copy(double d);
 // expected-error@+2 {{cannot redeclare builtin function '__builtin_va_end'}}
 // expected-note@+1 {{'__builtin_va_end' is a builtin with type}}
 void __builtin_va_end(__builtin_va_list);
-// RUN: %clang_cc1 %s -fsyntax-only -verify 
-// RUN: %clang_cc1 %s -fsyntax-only -verify -x c
 
 void __va_start(__builtin_va_list*, ...);
 
+  void *__builtin_assume_aligned(const void *, size_t, ...);
 #ifdef __cplusplus
-void *__builtin_assume_aligned(const void *, size_t, ...) noexcept;
-#else
-void *__builtin_assume_aligned(const void *, size_t, ...);
+constexpr void *__builtin_assume_aligned(const void *, size_t, ...);
+  void *__builtin_assume_aligned(const void *, size_t, ...) noexcept;
+constexpr void *__builtin_assume_aligned(const void *, size_t, ...) noexcept;
+  void *__builtin_assume_aligned(const void *, size_t, ...) throw();
+constexpr void *__builtin_assume_aligned(const void *, size_t, ...) throw();
+

MitalAshok wrote:

That seems like that should go in a separate patch. For now, I'll change this 
one so `ConstexprSpecKind::Constexpr` isn't added to these builtins as before

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


[clang] [Clang][Sema] Fix last argument not being used when comparing function template specializations when one has an explicit object argument (PR #92263)

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

MitalAshok wrote:

See also: #83279

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


[clang] [Clang][Sema] Fix last argument not being used when comparing function template specializations when one has an explicit object argument (PR #92263)

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

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

>From 6496dbfc8100812c8d3ea5a668af0593b532e4fe Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Wed, 15 May 2024 14:23:17 +0100
Subject: [PATCH 1/2] [Clang][Sema] Fix last argument not being used when
 comparing function template specializations when one has an explicit object
 argument

Fixes #92188
---
 clang/docs/ReleaseNotes.rst|  2 +
 clang/lib/Sema/SemaTemplateDeduction.cpp   |  9 +++-
 clang/test/SemaCXX/cxx2b-deducing-this.cpp | 49 ++
 3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ae699ebfc6038..9850fc9f8e0b4 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -713,6 +713,8 @@ Bug Fixes to C++ Support
 - Correctly treat the compound statement of an ``if consteval`` as an 
immediate context. Fixes (#GH91509).
 - When partial ordering alias templates against template template parameters,
   allow pack expansions when the alias has a fixed-size parameter list. Fixes 
(#GH62529).
+- Fix a bug where the last argument was not considered when considering the 
most viable function for
+  explicit object argument member functions. Fixes (#GH92188).
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 853c0e1b50619..094f767399e2a 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -5522,7 +5522,8 @@ static bool isAtLeastAsSpecializedAs(Sema , 
SourceLocation Loc,
 /// function templates.
 ///
 /// \param NumCallArguments1 The number of arguments in the call to FT1, used
-/// only when \c TPOC is \c TPOC_Call.
+/// only when \c TPOC is \c TPOC_Call. Does not include the object argument 
when
+/// calling a member function.
 ///
 /// \param RawObj1Ty The type of the object parameter of FT1 if a member
 /// function only used if \c TPOC is \c TPOC_Call and FT1 is a Function
@@ -5591,7 +5592,11 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
   IsRValRef1);
   Args2.push_back(Obj2Ty);
 }
-size_t NumComparedArguments = NumCallArguments1 + ShouldConvert1;
+size_t NumComparedArguments = NumCallArguments1;
+// Either added an argument above or the prototype includes an explicit
+// object argument we need to count
+if (Method1)
+  ++NumComparedArguments;
 
 Args1.insert(Args1.end(), Proto1->param_type_begin(),
  Proto1->param_type_end());
diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp 
b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
index 5f29a955e053c..55792e1448ac5 100644
--- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp
+++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
@@ -838,3 +838,52 @@ int h() {
   }();
 }
 }
+
+namespace GH92188 {
+struct A {
+  template
+  void operator+=(this auto &&, const char (&)[N]);
+  void operator+=(this auto &&, auto &&) = delete;
+
+  void f1(this A &, auto &);
+  void f1(this A &, auto &&) = delete;
+
+  void f2(this auto&);
+  void f2(this auto&&) = delete;
+
+  void f3(auto&) &;
+  void f3(this A&, auto&&) = delete;
+
+  void f4(auto&&) & = delete;
+  void f4(this A&, auto&);
+
+  static void f5(auto&);
+  void f5(this A&, auto&&) = delete;
+
+  static void f6(auto&&) = delete;
+  void f6(this A&, auto&);
+
+  void implicit_this() {
+int lval;
+operator+=("123");
+f1(lval);
+f2();
+f3(lval);
+f4(lval);
+f5(lval);
+f6(lval);
+  }
+};
+
+void g() {
+  A a;
+  int lval;
+  a += "123";
+  a.f1(lval);
+  a.f2();
+  a.f3(lval);
+  a.f4(lval);
+  a.f5(lval);
+  a.f6(lval);
+}
+}

>From 64e31749874a231956b898e89f00d63790d9f083 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Wed, 15 May 2024 15:05:55 +0100
Subject: [PATCH 2/2] Add test where one template isn't a method

---
 clang/test/SemaCXX/cxx2b-deducing-this.cpp | 8 
 1 file changed, 8 insertions(+)

diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp 
b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
index 55792e1448ac5..58372aaff96ea 100644
--- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp
+++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
@@ -873,6 +873,12 @@ struct A {
 f5(lval);
 f6(lval);
   }
+
+  void operator-(this A&, auto&&) = delete;
+  friend void operator-(A&, auto&);
+
+  void operator*(this A&, auto&);
+  friend void operator*(A&, auto&&) = delete;
 };
 
 void g() {
@@ -885,5 +891,7 @@ void g() {
   a.f4(lval);
   a.f5(lval);
   a.f6(lval);
+  a - lval;
+  a * lval;
 }
 }

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


[clang] [Clang][Sema] Fix last argument not being used when comparing function template specializations when one has an explicit object argument (PR #92263)

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

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

Fixes #92188

>From 6496dbfc8100812c8d3ea5a668af0593b532e4fe Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Wed, 15 May 2024 14:23:17 +0100
Subject: [PATCH] [Clang][Sema] Fix last argument not being used when comparing
 function template specializations when one has an explicit object argument

Fixes #92188
---
 clang/docs/ReleaseNotes.rst|  2 +
 clang/lib/Sema/SemaTemplateDeduction.cpp   |  9 +++-
 clang/test/SemaCXX/cxx2b-deducing-this.cpp | 49 ++
 3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ae699ebfc6038..9850fc9f8e0b4 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -713,6 +713,8 @@ Bug Fixes to C++ Support
 - Correctly treat the compound statement of an ``if consteval`` as an 
immediate context. Fixes (#GH91509).
 - When partial ordering alias templates against template template parameters,
   allow pack expansions when the alias has a fixed-size parameter list. Fixes 
(#GH62529).
+- Fix a bug where the last argument was not considered when considering the 
most viable function for
+  explicit object argument member functions. Fixes (#GH92188).
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 853c0e1b50619..094f767399e2a 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -5522,7 +5522,8 @@ static bool isAtLeastAsSpecializedAs(Sema , 
SourceLocation Loc,
 /// function templates.
 ///
 /// \param NumCallArguments1 The number of arguments in the call to FT1, used
-/// only when \c TPOC is \c TPOC_Call.
+/// only when \c TPOC is \c TPOC_Call. Does not include the object argument 
when
+/// calling a member function.
 ///
 /// \param RawObj1Ty The type of the object parameter of FT1 if a member
 /// function only used if \c TPOC is \c TPOC_Call and FT1 is a Function
@@ -5591,7 +5592,11 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
   IsRValRef1);
   Args2.push_back(Obj2Ty);
 }
-size_t NumComparedArguments = NumCallArguments1 + ShouldConvert1;
+size_t NumComparedArguments = NumCallArguments1;
+// Either added an argument above or the prototype includes an explicit
+// object argument we need to count
+if (Method1)
+  ++NumComparedArguments;
 
 Args1.insert(Args1.end(), Proto1->param_type_begin(),
  Proto1->param_type_end());
diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp 
b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
index 5f29a955e053c..55792e1448ac5 100644
--- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp
+++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
@@ -838,3 +838,52 @@ int h() {
   }();
 }
 }
+
+namespace GH92188 {
+struct A {
+  template
+  void operator+=(this auto &&, const char (&)[N]);
+  void operator+=(this auto &&, auto &&) = delete;
+
+  void f1(this A &, auto &);
+  void f1(this A &, auto &&) = delete;
+
+  void f2(this auto&);
+  void f2(this auto&&) = delete;
+
+  void f3(auto&) &;
+  void f3(this A&, auto&&) = delete;
+
+  void f4(auto&&) & = delete;
+  void f4(this A&, auto&);
+
+  static void f5(auto&);
+  void f5(this A&, auto&&) = delete;
+
+  static void f6(auto&&) = delete;
+  void f6(this A&, auto&);
+
+  void implicit_this() {
+int lval;
+operator+=("123");
+f1(lval);
+f2();
+f3(lval);
+f4(lval);
+f5(lval);
+f6(lval);
+  }
+};
+
+void g() {
+  A a;
+  int lval;
+  a += "123";
+  a.f1(lval);
+  a.f2();
+  a.f3(lval);
+  a.f4(lval);
+  a.f5(lval);
+  a.f6(lval);
+}
+}

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


[clang] [Clang] Fix some assertions not looking through type sugar (PR #92299)

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

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


[clang] [Clang] [Sema] Fix some assertions not looking through type sugar (PR #92299)

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

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

>From b6cb1c53a20637255bf869617b60155bfb636c60 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Wed, 15 May 2024 18:50:14 +0100
Subject: [PATCH] [Clang] Fix some assertions not looking through type sugar

Fixes #92284
---
 clang/lib/AST/ExprConstant.cpp |  2 +-
 clang/lib/Sema/SemaInit.cpp|  2 +-
 clang/test/SemaCXX/paren-list-agg-init.cpp | 16 
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f1aa19e4409e1..dca2b5d016738 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -11420,7 +11420,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const 
CXXConstructExpr *E,
 
 bool ArrayExprEvaluator::VisitCXXParenListInitExpr(
 const CXXParenListInitExpr *E) {
-  assert(dyn_cast(E->getType()) &&
+  assert(E->getType()->isConstantArrayType() &&
  "Expression result is not a constant array type");
 
   return VisitCXXParenListOrInitListExpr(E, E->getInitExprs(),
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 708286e192f9c..77d0075fbfd88 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -5511,7 +5511,7 @@ static void TryOrBuildParenListInitialization(
   << SE->getSourceRange();
   return;
 } else {
-  assert(isa(Entity.getType()));
+  assert(Entity.getType()->isIncompleteArrayType());
   ArrayLength = Args.size();
 }
 EntityIndexToProcess = ArrayLength;
diff --git a/clang/test/SemaCXX/paren-list-agg-init.cpp 
b/clang/test/SemaCXX/paren-list-agg-init.cpp
index c1964a5a9eb00..e8a9cd7e0509c 100644
--- a/clang/test/SemaCXX/paren-list-agg-init.cpp
+++ b/clang/test/SemaCXX/paren-list-agg-init.cpp
@@ -313,3 +313,19 @@ namespace GH63903 {
   constexpr S s(0); // beforecxx20-warning {{aggregate initialization of type 
'const S' from a parenthesized list of values is a C++20 extension}} \
 // expected-error {{constexpr variable 's' must be 
initialized by a constant expression}}
 }
+
+namespace GH92284 {
+  using T = int[1]; T x(42);
+// beforecxx20-warning@-1 {{aggregate initialization of type 'T' (aka 
'int[1]') from a parenthesized list of values is a C++20 extension}}
+  using Ta = int[2]; Ta a(42);
+// beforecxx20-warning@-1 {{aggregate initialization of type 'Ta' (aka 
'int[2]') from a parenthesized list of values is a C++20 extension}}
+  using Tb = int[2]; Tb b(42,43);
+// beforecxx20-warning@-1 {{aggregate initialization of type 'Tb' (aka 
'int[2]') from a parenthesized list of values is a C++20 extension}}
+  using Tc = int[]; Tc c(42);
+// beforecxx20-warning@-1 {{aggregate initialization of type 'int[1]' from a 
parenthesized list of values is a C++20 extension}}
+  using Td = int[]; Td d(42,43);
+// beforecxx20-warning@-1 {{aggregate initialization of type 'int[2]' from a 
parenthesized list of values is a C++20 extension}}
+  template using ThroughAlias = T[Sz];
+  ThroughAlias e(42);
+// beforecxx20-warning@-1 {{aggregate initialization of type 
'ThroughAlias' (aka 'int[1]') from a parenthesized list of values is a 
C++20 extension}}
+}

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


[clang] [Clang] [Sema] Fix some assertions not looking through type sugar (PR #92299)

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

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

Fixes #92284

>From 98d773a3a0a2faa407fddb20a63db7bf01890a98 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Wed, 15 May 2024 18:50:14 +0100
Subject: [PATCH] [Clang] [Sema] Fix some assertions not looking through type
 sugar

Fixes #92284
---
 clang/lib/AST/ExprConstant.cpp |  2 +-
 clang/lib/Sema/SemaInit.cpp|  2 +-
 clang/test/SemaCXX/paren-list-agg-init.cpp | 16 
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f1aa19e4409e1..dca2b5d016738 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -11420,7 +11420,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const 
CXXConstructExpr *E,
 
 bool ArrayExprEvaluator::VisitCXXParenListInitExpr(
 const CXXParenListInitExpr *E) {
-  assert(dyn_cast(E->getType()) &&
+  assert(E->getType()->isConstantArrayType() &&
  "Expression result is not a constant array type");
 
   return VisitCXXParenListOrInitListExpr(E, E->getInitExprs(),
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 708286e192f9c..77d0075fbfd88 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -5511,7 +5511,7 @@ static void TryOrBuildParenListInitialization(
   << SE->getSourceRange();
   return;
 } else {
-  assert(isa(Entity.getType()));
+  assert(Entity.getType()->isIncompleteArrayType());
   ArrayLength = Args.size();
 }
 EntityIndexToProcess = ArrayLength;
diff --git a/clang/test/SemaCXX/paren-list-agg-init.cpp 
b/clang/test/SemaCXX/paren-list-agg-init.cpp
index c1964a5a9eb00..e8a9cd7e0509c 100644
--- a/clang/test/SemaCXX/paren-list-agg-init.cpp
+++ b/clang/test/SemaCXX/paren-list-agg-init.cpp
@@ -313,3 +313,19 @@ namespace GH63903 {
   constexpr S s(0); // beforecxx20-warning {{aggregate initialization of type 
'const S' from a parenthesized list of values is a C++20 extension}} \
 // expected-error {{constexpr variable 's' must be 
initialized by a constant expression}}
 }
+
+namespace GH92284 {
+  using T = int[1]; T x(42);
+// beforecxx20-warning@-1 {{aggregate initialization of type 'T' (aka 
'int[1]') from a parenthesized list of values is a C++20 extension}}
+  using Ta = int[2]; Ta a(42);
+// beforecxx20-warning@-1 {{aggregate initialization of type 'Ta' (aka 
'int[2]') from a parenthesized list of values is a C++20 extension}}
+  using Tb = int[2]; Tb b(42,43);
+// beforecxx20-warning@-1 {{aggregate initialization of type 'Tb' (aka 
'int[2]') from a parenthesized list of values is a C++20 extension}}
+  using Tc = int[]; Tc c(42);
+// beforecxx20-warning@-1 {{aggregate initialization of type 'int[1]' from a 
parenthesized list of values is a C++20 extension}}
+  using Td = int[]; Td d(42,43);
+// beforecxx20-warning@-1 {{aggregate initialization of type 'int[2]' from a 
parenthesized list of values is a C++20 extension}}
+  template using ThroughAlias = T[Sz];
+  ThroughAlias e(42);
+// beforecxx20-warning@-1 {{aggregate initialization of type 
'ThroughAlias' (aka 'int[1]') from a parenthesized list of values is a 
C++20 extension}}
+}

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


[clang] [Clang][Sema] Fix last argument not being used when comparing function template specializations when one has an explicit object argument (PR #92263)

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


@@ -5591,7 +5592,11 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
   IsRValRef1);
   Args2.push_back(Obj2Ty);
 }
-size_t NumComparedArguments = NumCallArguments1 + ShouldConvert1;
+size_t NumComparedArguments = NumCallArguments1;
+// Either added an argument above or the prototype includes an explicit
+// object argument we need to count
+if (Method1)
+  ++NumComparedArguments;

MitalAshok wrote:

@mizvekov It would look something like this: 
b19a252f50e3b6d5dd50b0e51ec2865bb83fd5c9

But I think it's more error-prone because instead of `+1` in one place, it's 
sometimes a `+1` in all the places `ExplicitCallArguments` is set

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


[clang] [clang] Implement CWG2851: floating-point conversions in converted constant expressions (PR #90387)

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

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

>From 0b8176cf2171da0ce780c15131e19a24473a6989 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Sun, 28 Apr 2024 09:48:47 +0100
Subject: [PATCH] [clang] Implement CWG2851: floating-point conversions in
 converted constant expressions

---
 clang/docs/ReleaseNotes.rst   |  3 +
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/lib/Sema/SemaOverload.cpp   | 38 ++-
 clang/test/CXX/drs/dr28xx.cpp | 64 +++
 clang/www/cxx_dr_status.html  |  2 +-
 5 files changed, 107 insertions(+), 4 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 604782ca43dd54..6fb0b2d1030be8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -166,6 +166,9 @@ Resolutions to C++ Defect Reports
 - Clang now diagnoses declarative nested-name-specifiers with 
pack-index-specifiers.
   (`CWG2858: Declarative nested-name-specifiers and pack-index-specifiers 
`_).
 
+- Allow floating-point promotions and conversions in converted constant 
expressions.
+  (`CWG2851 Allow floating-point conversions in converted constant expressions 
`_).
+
 C Language Changes
 --
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index fdca82934cb4dc..cb248f2ea6374b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -85,6 +85,10 @@ def err_expr_not_cce : Error<
   "%select{case value|enumerator value|non-type template argument|"
   "array size|explicit specifier argument|noexcept specifier argument|"
   "call to 'size()'|call to 'data()'}0 is not a constant expression">;
+def err_float_conv_cant_represent : Error<
+  "non-type template argument evaluates to %0 which cannot be "
+  "exactly represented in type %1"
+>;
 def ext_cce_narrowing : ExtWarn<
   "%select{case value|enumerator value|non-type template argument|"
   "array size|explicit specifier argument|noexcept specifier argument|"
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 04cd9e78739d20..40d65638e3afc1 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6072,6 +6072,10 @@ static bool CheckConvertedConstantConversions(Sema ,
   case ICK_Integral_Promotion:
   case ICK_Integral_Conversion: // Narrowing conversions are checked elsewhere.
   case ICK_Zero_Queue_Conversion:
+  // Per CWG2851, floating-point promotions and conversions are allowed.
+  // The value of a conversion is checked afterwards.
+  case ICK_Floating_Promotion:
+  case ICK_Floating_Conversion:
 return true;
 
   case ICK_Boolean_Conversion:
@@ -6091,9 +6095,7 @@ static bool CheckConvertedConstantConversions(Sema ,
 // only permitted if the source type is std::nullptr_t.
 return SCS.getFromType()->isNullPtrType();
 
-  case ICK_Floating_Promotion:
   case ICK_Complex_Promotion:
-  case ICK_Floating_Conversion:
   case ICK_Complex_Conversion:
   case ICK_Floating_Integral:
   case ICK_Compatible_Conversion:
@@ -6229,7 +6231,37 @@ static ExprResult BuildConvertedConstantExpression(Sema 
, Expr *From,
   if (Result.isInvalid())
 return Result;
 
-  // Check for a narrowing implicit conversion.
+  if (SCS->Second == ICK_Floating_Conversion) {
+// Unlike with narrowing conversions, the value must fit
+// exactly even if it is in range
+assert(CCE == Sema::CCEKind::CCEK_TemplateArg &&
+   "Only non-type template args should use floating-point 
conversions");
+
+// Initializer is From, except it is a full-expression
+const Expr *Initializer =
+IgnoreNarrowingConversion(S.Context, Result.get());
+
+// If it's value-dependent, we can't tell whether it will fit
+if (Initializer->isValueDependent())
+  return Result;
+
+// Not-constant diagnosed afterwards
+if (!Initializer->isCXX11ConstantExpr(S.Context, ))
+  return Result;
+
+llvm::APFloat PostNarrowingValue = PreNarrowingValue.getFloat();
+bool LosesInfo = true;
+PostNarrowingValue.convert(S.Context.getFloatTypeSemantics(T),
+   llvm::APFloat::rmNearestTiesToEven, );
+
+if (LosesInfo)
+  S.Diag(From->getBeginLoc(), diag::err_float_conv_cant_represent)
+  << PreNarrowingValue.getAsString(S.Context, From->getType()) << T;
+
+return Result;
+  }
+
+  // Check for a narrowing integer conversion.
   bool ReturnPreNarrowingValue = false;
   QualType PreNarrowingType;
   switch (SCS->getNarrowingKind(S.Context, Result.get(), PreNarrowingValue,
diff --git a/clang/test/CXX/drs/dr28xx.cpp b/clang/test/CXX/drs/dr28xx.cpp
index 1967e8b751db2d..e0a180a1df27f3 100644
--- a/clang/test/CXX/drs/dr28xx.cpp
+++ 

[clang] [Clang] Reuse tail-padding for more types that are not POD for the purpose of layout (PR #90462)

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

MitalAshok wrote:

Some choices I've made:

 * Removed `TargetCXXABI::TailPaddingUseRules` and 
`TargetCXXABI::getTailPaddingUseRules()`. Now there are 5 distinct tail padding 
rules (7 if you count tail padding rules that change with 
`-fclang-abi-compat=18.0`), and it was only used in the `mustSkipTailPadding` 
function anyways.
  * Ignored a comment that the Clang WebAssembley ABI should ignore bit-field 
sizes. I don't think that was actually true, but it didn't matter before 
because we didn't check bit-field sizes.
   * `AppleARM64`/`WatchOS`/`iOS` don't skip tail padding for types with 
potentially-overlapping members as well as the oversized bit-fields they were 
documented to ignore.
   * `XL` and `Fuchsia` are also unchanged, for no particular reason other than 
I could not find what the ABI for C++ layout was supposed to be

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


[clang] [Clang] [C++26] Implement P2573R2: `= delete("should have a reason");` (PR #86526)

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


@@ -2280,18 +2294,18 @@ class FunctionDecl : public DeclaratorDecl,
 
   /// Returns whether this specific declaration of the function has a body.
   bool doesThisDeclarationHaveABody() const {
-return (!FunctionDeclBits.HasDefaultedFunctionInfo && Body) ||
+return (!FunctionDeclBits.HasDefaultedOrDeletedInfo && Body) ||
isLateTemplateParsed();
   }
 
   void setBody(Stmt *B);
   void setLazyBody(uint64_t Offset) {
-FunctionDeclBits.HasDefaultedFunctionInfo = false;
+FunctionDeclBits.HasDefaultedOrDeletedInfo = false;
 Body = LazyDeclStmtPtr(Offset);
   }
 
-  void setDefaultedFunctionInfo(DefaultedFunctionInfo *Info);
-  DefaultedFunctionInfo *getDefaultedFunctionInfo() const;
+  void setDefaultedOrDeletedInfo(DefaultedOrDeletedFunctionInfo *Info);
+  DefaultedOrDeletedFunctionInfo *getDefalutedOrDeletedInfo() const;

MitalAshok wrote:

@Sirraide There's no reason we can't change this name to fix this typo right?

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


[clang] [Clang] Ensure "=default"ed function can be deleted when used as an extension in C++03 (PR #90725)

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

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

Fixes #90605

>From 0793795ba7d5d5974b1403cd6ead0221fc20c5bb Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Wed, 1 May 2024 12:45:54 +0100
Subject: [PATCH] [Clang] Ensure "=default"ed function can be deleted when used
 as an extension in C++03

Fixes #90605
---
 clang/lib/Sema/SemaDeclCXX.cpp|  4 ++-
 .../SemaCXX/cxx0x-cursory-default-delete.cpp  | 34 +--
 .../SemaCXX/cxx0x-defaulted-functions.cpp | 13 +++
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 157d42c09cfcd8..e3c90c8ee1d644 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9767,7 +9767,9 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD,
 return false;
   CXXRecordDecl *RD = MD->getParent();
   assert(!RD->isDependentType() && "do deletion after instantiation");
-  if (!LangOpts.CPlusPlus || (!LangOpts.CPlusPlus11 && !RD->isLambda()) ||
+  if (!LangOpts.CPlusPlus ||
+  (!LangOpts.CPlusPlus11 && !RD->isLambda() &&
+   !MD->isExplicitlyDefaulted()) ||
   RD->isInvalidDecl())
 return false;
 
diff --git a/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp 
b/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
index 6ae146f0d08c7d..f884725a234671 100644
--- a/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
+++ b/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
@@ -1,4 +1,11 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++03 -Wno-c++11-extensions -fsyntax-only -verify %s
+
+#if __cplusplus < 201103L
+#define static_assert _Static_assert
+#define nullptr 0
+#define noexcept throw()
+#endif
 
 struct non_copiable {
   non_copiable(const non_copiable&) = delete; // expected-note {{marked 
deleted here}}
@@ -25,10 +32,12 @@ void fn1 () {
   non_const_copy ncc;
   non_const_copy ncc2 = ncc;
   ncc = ncc2;
+#if __cplusplus >= 201103L
   const non_const_copy cncc{};
+#endif
   const non_const_copy cncc1; // expected-error {{default initialization of an 
object of const type 'const non_const_copy' without a user-provided default 
constructor}}
-  non_const_copy ncc3 = cncc; // expected-error {{no matching}}
-  ncc = cncc; // expected-error {{no viable overloaded}}
+  non_const_copy ncc3 = cncc1; // expected-error {{no matching}}
+  ncc = cncc1; // expected-error {{no viable overloaded}}
 };
 
 struct no_fields { };
@@ -196,7 +205,7 @@ struct except_spec_d_match : except_spec_a, except_spec_b {
 struct S { S(); };
 S::S() __attribute((noreturn)) = default;
 
-using size_t = decltype(sizeof(0));
+using size_t = __SIZE_TYPE__;
 void *operator new(size_t) = delete; // expected-error {{deleted definition 
must be first declaration}} expected-note {{implicit}}
 void operator delete(void *) noexcept = delete; // expected-error {{deleted 
definition must be first declaration}} expected-note {{implicit}}
 
@@ -217,3 +226,22 @@ namespace deleted_overrides_deleted {
   template struct B : A { virtual void f() = delete; };
   template struct B;
 }
+
+namespace GH90605 {
+struct Element {
+Element& operator=(const Element&) = delete; // #GH90605-Element-assign
+};
+
+struct S {
+Element i; // #GH90605-i
+
+S& operator=(const S&) = default;
+// expected-warning@-1 {{explicitly defaulted copy assignment operator is 
implicitly deleted}}
+//   expected-note@#GH90605-i {{copy assignment operator of 'S' is implicitly 
deleted because field 'i' has a deleted copy assignment operator}}
+//   expected-note@#GH90605-Element-assign {{'operator=' has been explicitly 
marked deleted here}}
+//   expected-note@-4 {{replace 'default' with 'delete'}}
+};
+
+static_assert(!__is_trivially_assignable(S&, const S&), "");
+static_assert(!__is_assignable(S&, const S&), "");
+}
diff --git a/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp 
b/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
index 0c3dd1ea7aa274..30d54920a1a686 100644
--- a/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
+++ b/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
@@ -1,4 +1,9 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -fcxx-exceptions 
-Wno-deprecated-builtins %s
+// RUN: %clang_cc1 -std=c++03 -Wno-c++11-extensions -fsyntax-only -verify 
-fcxx-exceptions -Wno-deprecated-builtins %s
+
+#if __cplusplus < 201103L
+#define static_assert _Static_assert
+#endif
 
 void fn() = default; // expected-error {{only special member}}
 struct foo {
@@ -43,6 +48,7 @@ void tester() {
   b = c;
 }
 
+#if __cplusplus >= 201103L
 template struct S : T {
   constexpr S() = default; // expected-note {{previous declaration is 
here}}
   constexpr S(const S&) = default; // expected-note {{previous declaration is 
here}}
@@ -118,6 +124,7 @@ namespace DefaultedFnExceptionSpec {
 *p = *p; // expected-note {{instantiation of}}
   }
 }
+#endif
 
 namespace PR13527 {
   struct X {
@@ 

[clang] [Clang] No longer require complete types with __builtin_launder (PR #91070)

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

MitalAshok wrote:

Here's one scenario where it could make a difference in codegen 
:

```c++
// Header
struct X;
extern X x;
void f(X&);
inline void g() {
f(x);
}
inline void h() {
f(*__builtin_launder(__builtin_addressof(x)));
}

// Source
struct X {
virtual void mem() { __builtin_printf("X::mem()\n"); }
};
void f(X& x) {
x.mem();
}
void(*p[2])() = { g, h };  // Force inline functions to be generated
```

Even though Clang currently doesn't do this optimization, with 
`-fstrict-vtable-pointers`, `g()` is allowed to to devirtualise the call.

Also, we can't "complete" the type at all. See 
,
 where the template is not allowed to be instantiated by `launder`.

Maybe we could delay the code-gen to the end of the TU to see if it's completed 
by then? I do think it's an incredibly rare situation for some incomplete type 
to be `std::launder`ed and then later completed in the same TU.


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


[clang] [Clang] Ensure ``if consteval`` consititute an immediate function context (PR #91939)

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


@@ -7964,6 +7964,15 @@ TreeTransform::TransformIfStmt(IfStmt *S) {
   // Transform the "then" branch.
   StmtResult Then;
   if (!ConstexprConditionValue || *ConstexprConditionValue) {
+Sema::ExpressionEvaluationContext Context =
+S->isNonNegatedConsteval()
+? Sema::ExpressionEvaluationContext::ImmediateFunctionContext
+: Sema::ExpressionEvaluationContext::PotentiallyEvaluated;
+
+EnterExpressionEvaluationContext Ctx(
+getSema(), Context, nullptr,
+Sema::ExpressionEvaluationContextRecord::EK_Other);

MitalAshok wrote:

```suggestion
EnterExpressionEvaluationContext Ctx(
getSema(), Sema::ExpressionEvaluationContext::ImmediateFunctionContext, 
nullptr,
Sema::ExpressionEvaluationContextRecord::EK_Other,
S->isNonNegatedConsteval());
```

(and ditto for the else branch) to only push a context if needed

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


[clang] [Clang] Add attribute for consteval builtins; Declare constexpr builtins as constexpr in C++ (PR #91894)

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


@@ -14,13 +14,18 @@ void __builtin_va_copy(double d);
 // expected-error@+2 {{cannot redeclare builtin function '__builtin_va_end'}}
 // expected-note@+1 {{'__builtin_va_end' is a builtin with type}}
 void __builtin_va_end(__builtin_va_list);
-// RUN: %clang_cc1 %s -fsyntax-only -verify 
-// RUN: %clang_cc1 %s -fsyntax-only -verify -x c
 
 void __va_start(__builtin_va_list*, ...);
 
+  void *__builtin_assume_aligned(const void *, size_t, ...);
 #ifdef __cplusplus
-void *__builtin_assume_aligned(const void *, size_t, ...) noexcept;
-#else
-void *__builtin_assume_aligned(const void *, size_t, ...);
+constexpr void *__builtin_assume_aligned(const void *, size_t, ...);
+  void *__builtin_assume_aligned(const void *, size_t, ...) noexcept;
+constexpr void *__builtin_assume_aligned(const void *, size_t, ...) noexcept;
+  void *__builtin_assume_aligned(const void *, size_t, ...) throw();
+constexpr void *__builtin_assume_aligned(const void *, size_t, ...) throw();
+

MitalAshok wrote:

For backwards compatibility (and compatibility with the same definitions in C 
or with GCC), to allow declarations with or without the `constexpr`. I suspect 
in any real code, it will always be declared without the `constexpr`.

The other solutions is to keep them all as `ConstexprSpecKind::Unspecified` 
like we currently do, but this is asymmetric with `consteval` builtins which 
will be marked `ConstexprSpecKind::Consteval`, and leads to the builtin 
versions of `std::move`/`std::forward`/constexpr cmath functions to have 
differing `getConstexprKind()` from their non-builtin counterparts



https://github.com/llvm/llvm-project/pull/91894
___
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-05-21 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok edited 
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] Change how the argument of a delete expression is converted (PR #92814)

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

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

>From 43e9f8fe5cdb19c0f57a00b352592e56e470ffe7 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Mon, 20 May 2024 20:18:48 +0100
Subject: [PATCH 1/3] [Clang] Change how the argument of a delete expression is
 converted

A new warning -Wdelete-array is issued for the now-accepted delete of an array, 
which becomes a pointer to the first element after an array-to-pointer 
conversion.

The GNU extension of deleting a void pointer is still accepted, but if that 
void pointer comes from a conversion operator, a conversion to a pointer to an 
object type takes priority before conversions are rechecked to allow conversion 
to a void pointer.
This means that previously ambiguous contextual conversions where there was a 
conversion to a void pointer and an object pointer now unambiguously pick the 
conversion to an object pointer.
---
 clang/docs/ReleaseNotes.rst   |   4 +
 clang/include/clang/Basic/DiagnosticGroups.td |   1 +
 .../clang/Basic/DiagnosticSemaKinds.td|   1 +
 clang/lib/Sema/SemaExprCXX.cpp| 187 ++
 clang/test/CXX/drs/cwg5xx.cpp |   9 +-
 .../test/Parser/cxx2c-delete-with-message.cpp |   4 +-
 clang/www/cxx_dr_status.html  |   2 +-
 7 files changed, 117 insertions(+), 91 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 81e9d0423f96a..6e769f1f99ceb 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -749,6 +749,10 @@ Bug Fixes to C++ Support
 - Clang now correctly diagnoses when the current instantiation is used as an 
incomplete base class.
 - Clang no longer treats ``constexpr`` class scope function template 
specializations of non-static members
   as implicitly ``const`` in language modes after C++11.
+- Fix delete-expression operand not undergoing array-to-pointer conversion. 
Now warn ``-Wdelete-array`` when
+  trying to delete an array object.
+- Fix GNU extension that allows deleting ``void *`` making some deletes of 
class type ambiguous when there
+  is an object pointer and void pointer conversion operator. Now chooses the 
object pointer conversion.
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 4cb4f3d999f7a..410c31a25db03 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -168,6 +168,7 @@ def UndefinedFuncTemplate : 
DiagGroup<"undefined-func-template">;
 def MissingNoEscape : DiagGroup<"missing-noescape">;
 
 def DefaultedFunctionDeleted : DiagGroup<"defaulted-function-deleted">;
+def DeleteArray : DiagGroup<"delete-array">;
 def DeleteIncomplete : DiagGroup<"delete-incomplete">;
 def DeleteNonAbstractNonVirtualDtor : 
DiagGroup<"delete-non-abstract-non-virtual-dtor">;
 def DeleteAbstractNonVirtualDtor : 
DiagGroup<"delete-abstract-non-virtual-dtor">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e3c65cba4886a..580f8e57804fa 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7930,6 +7930,7 @@ def ext_default_init_const : ExtWarn<
   "is a Microsoft extension">,
   InGroup;
 def err_delete_operand : Error<"cannot delete expression of type %0">;
+def warn_delete_array : Warning<"deleting array of type %0">, 
InGroup;
 def ext_delete_void_ptr_operand : ExtWarn<
   "cannot delete expression with pointer-to-'void' type %0">,
   InGroup;
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index f543e006060d6..9a1e149a4af8e 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -3675,13 +3675,60 @@ void Sema::AnalyzeDeleteExprMismatch(FieldDecl *Field, 
SourceLocation DeleteLoc,
   }
 }
 
+namespace {
+class DeleteConverter : public Sema::ContextualImplicitConverter {
+public:
+  bool AllowVoidPointer = false;
+
+  DeleteConverter() : ContextualImplicitConverter(false, true) {}
+
+  bool match(QualType ConvType) override {
+return ConvType->isObjectPointerType() &&
+   (AllowVoidPointer || !ConvType->isVoidPointerType());
+  }
+
+  using SDB = Sema::SemaDiagnosticBuilder;
+
+  SDB diagnoseNoMatch(Sema , SourceLocation Loc, QualType T) override {
+return S.Diag(Loc, diag::err_delete_operand) << T;
+  }
+
+  SDB diagnoseIncomplete(Sema , SourceLocation Loc, QualType T) override {
+return S.Diag(Loc, diag::err_delete_incomplete_class_type) << T;
+  }
+
+  SDB diagnoseExplicitConv(Sema , SourceLocation Loc, QualType T,
+   QualType ConvTy) override {
+return S.Diag(Loc, diag::err_delete_explicit_conversion) << T << ConvTy;
+  }
+
+  SDB noteExplicitConv(Sema , CXXConversionDecl *Conv,
+   QualType ConvTy) override 

[clang] [Clang] Change how the argument of a delete expression is converted (PR #92814)

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

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

>From 43e9f8fe5cdb19c0f57a00b352592e56e470ffe7 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Mon, 20 May 2024 20:18:48 +0100
Subject: [PATCH 1/2] [Clang] Change how the argument of a delete expression is
 converted

A new warning -Wdelete-array is issued for the now-accepted delete of an array, 
which becomes a pointer to the first element after an array-to-pointer 
conversion.

The GNU extension of deleting a void pointer is still accepted, but if that 
void pointer comes from a conversion operator, a conversion to a pointer to an 
object type takes priority before conversions are rechecked to allow conversion 
to a void pointer.
This means that previously ambiguous contextual conversions where there was a 
conversion to a void pointer and an object pointer now unambiguously pick the 
conversion to an object pointer.
---
 clang/docs/ReleaseNotes.rst   |   4 +
 clang/include/clang/Basic/DiagnosticGroups.td |   1 +
 .../clang/Basic/DiagnosticSemaKinds.td|   1 +
 clang/lib/Sema/SemaExprCXX.cpp| 187 ++
 clang/test/CXX/drs/cwg5xx.cpp |   9 +-
 .../test/Parser/cxx2c-delete-with-message.cpp |   4 +-
 clang/www/cxx_dr_status.html  |   2 +-
 7 files changed, 117 insertions(+), 91 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 81e9d0423f96a..6e769f1f99ceb 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -749,6 +749,10 @@ Bug Fixes to C++ Support
 - Clang now correctly diagnoses when the current instantiation is used as an 
incomplete base class.
 - Clang no longer treats ``constexpr`` class scope function template 
specializations of non-static members
   as implicitly ``const`` in language modes after C++11.
+- Fix delete-expression operand not undergoing array-to-pointer conversion. 
Now warn ``-Wdelete-array`` when
+  trying to delete an array object.
+- Fix GNU extension that allows deleting ``void *`` making some deletes of 
class type ambiguous when there
+  is an object pointer and void pointer conversion operator. Now chooses the 
object pointer conversion.
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 4cb4f3d999f7a..410c31a25db03 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -168,6 +168,7 @@ def UndefinedFuncTemplate : 
DiagGroup<"undefined-func-template">;
 def MissingNoEscape : DiagGroup<"missing-noescape">;
 
 def DefaultedFunctionDeleted : DiagGroup<"defaulted-function-deleted">;
+def DeleteArray : DiagGroup<"delete-array">;
 def DeleteIncomplete : DiagGroup<"delete-incomplete">;
 def DeleteNonAbstractNonVirtualDtor : 
DiagGroup<"delete-non-abstract-non-virtual-dtor">;
 def DeleteAbstractNonVirtualDtor : 
DiagGroup<"delete-abstract-non-virtual-dtor">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e3c65cba4886a..580f8e57804fa 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7930,6 +7930,7 @@ def ext_default_init_const : ExtWarn<
   "is a Microsoft extension">,
   InGroup;
 def err_delete_operand : Error<"cannot delete expression of type %0">;
+def warn_delete_array : Warning<"deleting array of type %0">, 
InGroup;
 def ext_delete_void_ptr_operand : ExtWarn<
   "cannot delete expression with pointer-to-'void' type %0">,
   InGroup;
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index f543e006060d6..9a1e149a4af8e 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -3675,13 +3675,60 @@ void Sema::AnalyzeDeleteExprMismatch(FieldDecl *Field, 
SourceLocation DeleteLoc,
   }
 }
 
+namespace {
+class DeleteConverter : public Sema::ContextualImplicitConverter {
+public:
+  bool AllowVoidPointer = false;
+
+  DeleteConverter() : ContextualImplicitConverter(false, true) {}
+
+  bool match(QualType ConvType) override {
+return ConvType->isObjectPointerType() &&
+   (AllowVoidPointer || !ConvType->isVoidPointerType());
+  }
+
+  using SDB = Sema::SemaDiagnosticBuilder;
+
+  SDB diagnoseNoMatch(Sema , SourceLocation Loc, QualType T) override {
+return S.Diag(Loc, diag::err_delete_operand) << T;
+  }
+
+  SDB diagnoseIncomplete(Sema , SourceLocation Loc, QualType T) override {
+return S.Diag(Loc, diag::err_delete_incomplete_class_type) << T;
+  }
+
+  SDB diagnoseExplicitConv(Sema , SourceLocation Loc, QualType T,
+   QualType ConvTy) override {
+return S.Diag(Loc, diag::err_delete_explicit_conversion) << T << ConvTy;
+  }
+
+  SDB noteExplicitConv(Sema , CXXConversionDecl *Conv,
+   QualType ConvTy) override 

[clang] [Clang] Change how the argument of a delete expression is converted (PR #92814)

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

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

>From 43e9f8fe5cdb19c0f57a00b352592e56e470ffe7 Mon Sep 17 00:00:00 2001
From: Mital Ashok 
Date: Mon, 20 May 2024 20:18:48 +0100
Subject: [PATCH 1/2] [Clang] Change how the argument of a delete expression is
 converted

A new warning -Wdelete-array is issued for the now-accepted delete of an array, 
which becomes a pointer to the first element after an array-to-pointer 
conversion.

The GNU extension of deleting a void pointer is still accepted, but if that 
void pointer comes from a conversion operator, a conversion to a pointer to an 
object type takes priority before conversions are rechecked to allow conversion 
to a void pointer.
This means that previously ambiguous contextual conversions where there was a 
conversion to a void pointer and an object pointer now unambiguously pick the 
conversion to an object pointer.
---
 clang/docs/ReleaseNotes.rst   |   4 +
 clang/include/clang/Basic/DiagnosticGroups.td |   1 +
 .../clang/Basic/DiagnosticSemaKinds.td|   1 +
 clang/lib/Sema/SemaExprCXX.cpp| 187 ++
 clang/test/CXX/drs/cwg5xx.cpp |   9 +-
 .../test/Parser/cxx2c-delete-with-message.cpp |   4 +-
 clang/www/cxx_dr_status.html  |   2 +-
 7 files changed, 117 insertions(+), 91 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 81e9d0423f96a..6e769f1f99ceb 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -749,6 +749,10 @@ Bug Fixes to C++ Support
 - Clang now correctly diagnoses when the current instantiation is used as an 
incomplete base class.
 - Clang no longer treats ``constexpr`` class scope function template 
specializations of non-static members
   as implicitly ``const`` in language modes after C++11.
+- Fix delete-expression operand not undergoing array-to-pointer conversion. 
Now warn ``-Wdelete-array`` when
+  trying to delete an array object.
+- Fix GNU extension that allows deleting ``void *`` making some deletes of 
class type ambiguous when there
+  is an object pointer and void pointer conversion operator. Now chooses the 
object pointer conversion.
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 4cb4f3d999f7a..410c31a25db03 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -168,6 +168,7 @@ def UndefinedFuncTemplate : 
DiagGroup<"undefined-func-template">;
 def MissingNoEscape : DiagGroup<"missing-noescape">;
 
 def DefaultedFunctionDeleted : DiagGroup<"defaulted-function-deleted">;
+def DeleteArray : DiagGroup<"delete-array">;
 def DeleteIncomplete : DiagGroup<"delete-incomplete">;
 def DeleteNonAbstractNonVirtualDtor : 
DiagGroup<"delete-non-abstract-non-virtual-dtor">;
 def DeleteAbstractNonVirtualDtor : 
DiagGroup<"delete-abstract-non-virtual-dtor">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e3c65cba4886a..580f8e57804fa 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7930,6 +7930,7 @@ def ext_default_init_const : ExtWarn<
   "is a Microsoft extension">,
   InGroup;
 def err_delete_operand : Error<"cannot delete expression of type %0">;
+def warn_delete_array : Warning<"deleting array of type %0">, 
InGroup;
 def ext_delete_void_ptr_operand : ExtWarn<
   "cannot delete expression with pointer-to-'void' type %0">,
   InGroup;
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index f543e006060d6..9a1e149a4af8e 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -3675,13 +3675,60 @@ void Sema::AnalyzeDeleteExprMismatch(FieldDecl *Field, 
SourceLocation DeleteLoc,
   }
 }
 
+namespace {
+class DeleteConverter : public Sema::ContextualImplicitConverter {
+public:
+  bool AllowVoidPointer = false;
+
+  DeleteConverter() : ContextualImplicitConverter(false, true) {}
+
+  bool match(QualType ConvType) override {
+return ConvType->isObjectPointerType() &&
+   (AllowVoidPointer || !ConvType->isVoidPointerType());
+  }
+
+  using SDB = Sema::SemaDiagnosticBuilder;
+
+  SDB diagnoseNoMatch(Sema , SourceLocation Loc, QualType T) override {
+return S.Diag(Loc, diag::err_delete_operand) << T;
+  }
+
+  SDB diagnoseIncomplete(Sema , SourceLocation Loc, QualType T) override {
+return S.Diag(Loc, diag::err_delete_incomplete_class_type) << T;
+  }
+
+  SDB diagnoseExplicitConv(Sema , SourceLocation Loc, QualType T,
+   QualType ConvTy) override {
+return S.Diag(Loc, diag::err_delete_explicit_conversion) << T << ConvTy;
+  }
+
+  SDB noteExplicitConv(Sema , CXXConversionDecl *Conv,
+   QualType ConvTy) override 

[clang] [Clang] Change how the argument of a delete expression is converted (PR #92814)

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


@@ -1230,11 +1230,11 @@ namespace cwg598 { // cwg598: yes
   int  = h(N::i);
 }
 
-namespace cwg599 { // cwg599: partial
+namespace cwg599 { // cwg599: 19
   typedef int Fn();
   struct S { operator void*(); };
   struct T { operator Fn*(); };
-  struct U { operator int*(); operator void*(); }; // #cwg599-U
+  struct U { operator int*(); operator void*(); };
   struct V { operator int*(); operator Fn*(); };
   void f(void *p, void (*q)(), S s, T t, U u, V v) {

MitalAshok wrote:

I've added that in another file along with other contextual implicit 
conversions with references

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


[clang] [Clang] Change how the argument of a delete expression is converted (PR #92814)

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


@@ -1245,12 +1245,7 @@ namespace cwg599 { // cwg599: partial
 // expected-error@-1 {{cannot delete expression with pointer-to-'void' 
type 'void *'}}
 delete t;
 // expected-error@-1 {{cannot delete expression of type 'T'}}
-// FIXME: This is valid, but is rejected due to a non-conforming GNU
-// extension allowing deletion of pointers to void.
 delete u;
-// expected-error@-1 {{ambiguous conversion of delete expression of type 
'U' to a pointer}}

MitalAshok wrote:

@Endilll There is a set of appropriate types (for `delete`, it's all 
pointer-to-object types), and there must be exactly one `T` in that set where 
there is a conversion operator to cv-`T` or reference to cv-`T`. So for `delete 
u;`, the search finds `T = int*`, so `u` is contextually implicitly converted 
to `int*`. See also:  


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


[clang] [Clang] Change how the argument of a delete expression is converted (PR #92814)

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

MitalAshok wrote:

I've also found and fixed a related bug where types were compared with `==` not 
`hasSameType`, leading to two conversion operators appearing to be different 
when they are the same and Clang not compiling valid code: 
https://godbolt.org/z/nY7svGKn8

https://github.com/llvm/llvm-project/pull/92814
___
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-05-21 Thread Mital Ashok via cfe-commits

https://github.com/MitalAshok edited 
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] [llvm] [Clang] Fix definition of layout-compatible to ignore empty classes (PR #92103)

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

MitalAshok wrote:

@dwblaikie This patch will bring Clang in line with GCC and MSVC: 
https://godbolt.org/z/nj715zbsW

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


  1   2   3   >