From 3b185ba83143cc291816f2bc3577ee5cec2446b6 Mon Sep 17 00:00:00 2001
From: Carl Norum <carl.norum@apple.com>
Date: Tue, 27 Oct 2015 11:29:34 -0700
Subject: [PATCH] Add -Wdouble-promotion to clang.

Change-Id: I7b5fbbac33556178d1f63b46f965166b0561325a
---
 include/clang/Basic/DiagnosticGroups.td        |  1 +
 include/clang/Basic/DiagnosticSemaKinds.td     |  3 ++
 lib/Sema/SemaChecking.cpp                      |  9 ++++++
 test/SemaCXX/warn-double-promotion.cpp         | 34 ++++++++++++++++++++++
 4 files changed, 47 insertions(+)
 create mode 100644 test/SemaCXX/warn-double-promotion.cpp

diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 05683bf..11ae67a 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -44,6 +44,7 @@ def BoolConversion : DiagGroup<"bool-conversion", [PointerBoolConversion,
 def IntConversion : DiagGroup<"int-conversion">;
 def EnumConversion : DiagGroup<"enum-conversion">;
 def FloatConversion : DiagGroup<"float-conversion">;
+def DoublePromotion : DiagGroup<"double-promotion">;
 def EnumTooLarge : DiagGroup<"enum-too-large">;
 def UnsupportedNan : DiagGroup<"unsupported-nan">;
 def NonLiteralNullConversion : DiagGroup<"non-literal-null-conversion">;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 51e069a..8ac2641 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2561,6 +2561,9 @@ def warn_impcast_complex_scalar : Warning<
 def warn_impcast_float_precision : Warning<
   "implicit conversion loses floating-point precision: %0 to %1">,
   InGroup<Conversion>, DefaultIgnore;
+def warn_impcast_double_promotion : Warning<
+  "implicit conversion from %0 to %1">,
+  InGroup<DoublePromotion>, DefaultIgnore;
 def warn_impcast_float_integer : Warning<
   "implicit conversion turns floating-point number into integer: %0 to %1">,
   InGroup<FloatConversion>, DefaultIgnore;
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index d9d26e2..c6d7129 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -7083,6 +7083,15 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
           return;
 
         DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision);
+
+      }
+      // ... or possibly if we're increasing rank, too
+      else if (TargetBT->getKind() > SourceBT->getKind()) {
+
+        if (S.SourceMgr.isInSystemMacro(CC))
+          return;
+
+        DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_double_promotion);
       }
       return;
     }
diff --git a/test/SemaCXX/warn-double-promotion.cpp b/test/SemaCXX/warn-double-promotion.cpp
new file mode 100644
index 0000000..a34a4a3
--- /dev/null
+++ b/test/SemaCXX/warn-double-promotion.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s -Wdouble-promotion
+
+float ReturnFloatFromDouble(double d) {
+  return d;
+}
+
+float ReturnFloatFromLongDouble(long double ld) {
+  return ld;
+}
+
+double ReturnDoubleFromLongDouble(long double ld) {
+  return ld;
+}
+
+double ReturnDoubleFromFloat(float f) {
+  return f;  //expected-warning{{implicit conversion from 'float' to 'double'}}
+}
+
+long double ReturnLongDoubleFromFloat(float f) {
+  return f;  //expected-warning{{implicit conversion from 'float' to 'long double'}}
+}
+
+long double ReturnLongDoubleFromDouble(double d) {
+  return d;  //expected-warning{{implicit conversion from 'double' to 'long double'}}
+}
+
+void Convert(float f, double d, long double ld) {
+  d = f;  //expected-warning{{implicit conversion from 'float' to 'double'}}
+  ld = f; //expected-warning{{implicit conversion from 'float' to 'long double'}}
+  ld = d; //expected-warning{{implicit conversion from 'double' to 'long double'}}
+  f = d;
+  f = ld;
+  d = ld;
+}
-- 
2.6.2

