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

2024-04-30 Thread Shafik Yaghmour 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"))>));

shafik wrote:

I discussed this with @jensmaurer offline and he felt similarly as well. So 
let's go with that for now but I will make sure we discuss that next we discuss 
cwg2864.

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-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-29 Thread Shafik Yaghmour 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"))>));

shafik wrote:

Why does `nanl` fail but `nans` does not? I am not sure this is consistent with 
[CWG2864](https://cplusplus.github.io/CWG/issues/2864.html), which is not final 
yet either.

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

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] 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] Implement CWG2851: floating-point conversions in converted constant expressions (PR #90387)

2024-04-29 Thread Vlad Serebrennikov via cfe-commits

Endilll wrote:

https://github.com/llvm/llvm-project/pull/90352 has been merged.

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

Sirraide wrote:

Right, there’s a difference between ‘can be represented in the range of’ and 
‘can be represented exactly’, that makes sense. I missed that somehow.

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] Implement CWG2851: floating-point conversions in converted constant expressions (PR #90387)

2024-04-29 Thread 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) {

Sirraide wrote:

‘all of this’ being everything you added here

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

Sirraide wrote:

Is there a reason all of this is here instead of in 
`StandardConversionSequence::getNarrowingKind()`, where we seem to be already 
handling most of this?

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 via cfe-commits

https://github.com/Sirraide commented:

The approach here looks correct, but I’m not sure it’s in the right place.

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 via cfe-commits

https://github.com/Sirraide edited 
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

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-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 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 Vlad Serebrennikov via cfe-commits

https://github.com/Endilll commented:

I'm fine with the way DR test is written, but I'm not qualified to review the 
contents on the test, unfortunately.

I'd like to point to related Core issues 
[CWG2836](https://cplusplus.github.io/CWG/issues/2836.html) and 
[CWG2864](https://cplusplus.github.io/CWG/issues/2864.html).

You also need to run `clang/www/make_cxx_dr_status` to update the DR status 
page.

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 via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Mital Ashok (MitalAshok)


Changes

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+.

---
Full diff: https://github.com/llvm/llvm-project/pull/90387.diff


4 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+3) 
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+4) 
- (modified) clang/lib/Sema/SemaOverload.cpp (+35-3) 
- (modified) clang/test/CXX/drs/dr28xx.cpp (+35) 


``diff
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(), PreNarrowingValue,
diff --git a/clang/test/CXX/drs/dr28xx.cpp b/clang/test/CXX/drs/dr28xx.cpp
index 4d9b0c76758d53..cf9676ddb73385 100644
--- a/clang/test/CXX/drs/dr28xx.cpp
+++ b/clang/test/CXX/drs/dr28xx.cpp
@@ -59,6 +59,41 @@ 

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