Skip to content

Commit dff61e0

Browse files
committed
Implement NaN cases
1 parent 1ea05d5 commit dff61e0

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

clang/lib/Sema/SemaOverload.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,14 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
432432
Converted.convert(Ctx.getFloatTypeSemantics(FromType),
433433
llvm::APFloat::rmNearestTiesToEven, &ignored);
434434
if (Ctx.getLangOpts().C23) {
435+
if (FloatVal.isNaN() && Converted.isNaN()) {
436+
if (!FloatVal.isSignaling() && !Converted.isSignaling()) {
437+
// Quiet NaNs are considered the same value, regardless of
438+
// payloads.
439+
return NK_Not_Narrowing;
440+
}
441+
}
442+
// For normal values, check exact equality.
435443
if (!Converted.bitwiseIsEqual(FloatVal)) {
436444
ConstantType = Initializer->getType();
437445
return NK_Constant_Narrowing;
@@ -514,6 +522,25 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
514522
return NK_Type_Narrowing;
515523
return NK_Not_Narrowing;
516524

525+
case ICK_Floating_Promotion:
526+
if (Ctx.getLangOpts().C23) {
527+
const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted);
528+
Expr::EvalResult R;
529+
if (Initializer->EvaluateAsRValue(R, Ctx)) {
530+
ConstantValue = R.Val;
531+
assert(ConstantValue.isFloat());
532+
llvm::APFloat FloatVal = ConstantValue.getFloat();
533+
// C23 6.7.3p6 If the initializer has real type and a signaling NaN
534+
// value, the unqualified versions of the type of the initializer and
535+
// the corresponding real type of the object declared shall be
536+
// compatible.
537+
if (FloatVal.isNaN() && FloatVal.isSignaling()) {
538+
ConstantType = Initializer->getType();
539+
return NK_Constant_Narrowing;
540+
}
541+
}
542+
}
543+
return NK_Not_Narrowing;
517544
default:
518545
// Other kinds of conversions are not narrowings.
519546
return NK_Not_Narrowing;

clang/test/Sema/constexpr.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,3 +330,30 @@ void f7(int n, int array[n]) {
330330
int (*(*fp)(int n))[n];
331331
constexpr typeof(fp) bar = 0; // expected-error {{constexpr variable cannot have type 'const typeof (fp)' (aka 'int (*(*const)(int))[n]')}}
332332
}
333+
334+
// Check how constexpr works with NaNs and infinities.
335+
#define FLT_NAN __builtin_nanf("1")
336+
#define DBL_NAN __builtin_nan("1")
337+
#define LD_NAN __builtin_nanf("1")
338+
#define FLT_SNAN __builtin_nansf("1")
339+
#define DBL_SNAN __builtin_nans("1")
340+
#define LD_SNAN __builtin_nansl("1")
341+
#define INF __builtin_inf()
342+
void infsNaNs() {
343+
// Inf and quiet NaN is always fine, signaling NaN must have the same type.
344+
constexpr float fl0 = INF;
345+
constexpr float fl1 = (long double)INF;
346+
constexpr float fl2 = (long double)FLT_NAN;
347+
constexpr float fl3 = FLT_NAN;
348+
constexpr float fl5 = DBL_NAN;
349+
constexpr float fl6 = LD_NAN;
350+
constexpr float fl7 = DBL_SNAN; // expected-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const float'}}
351+
constexpr float fl8 = LD_SNAN; // expected-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const float'}}
352+
353+
constexpr double db0 = FLT_NAN;
354+
constexpr double db2 = DBL_NAN;
355+
constexpr double db3 = DBL_SNAN;
356+
constexpr double db4 = FLT_SNAN; // expected-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const double'}}
357+
constexpr double db5 = LD_SNAN; // expected-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const double'}}
358+
constexpr double db6 = INF;
359+
}

0 commit comments

Comments
 (0)