lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] master 20e94fa 4/4: Resolve another '-Wconversion' i


From: Greg Chicares
Subject: [lmi-commits] [lmi] master 20e94fa 4/4: Resolve another '-Wconversion' issue
Date: Thu, 31 May 2018 20:05:36 -0400 (EDT)

branch: master
commit 20e94fa22652f43b5197b84a39f8323bbcde2911
Author: Gregory W. Chicares <address@hidden>
Commit: Gregory W. Chicares <address@hidden>

    Resolve another '-Wconversion' issue
---
 facets.cpp     | 39 ++++++++++++++++++++++++++++++++++++++-
 workhorse.make |  1 -
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/facets.cpp b/facets.cpp
index a9bad60..2aeb705 100644
--- a/facets.cpp
+++ b/facets.cpp
@@ -63,6 +63,41 @@
 // This custom facet, therefore, passes std::ctype<char>'s constructor
 // a third argument that differs from the default, specifying instead
 // that the locale should not take responsibility for deletion.
+//
+// Implementation note--with this original line:
+//   rc[C] &= ~std::ctype_base::space;
+// gcc-7.3 warns:
+//   conversion to 'std::ctype_base::mask {aka short unsigned int}' from 'int'
+// which seems incorrect: according to C++17 (N4659),
+//   [category.ctype]
+// 'space' is of type 'mask', a bitmask type for which
+//   [bitmask.types]
+// operator~(bitmask) returns the bitmask type, and
+// operator&=() returns a reference to the bitmask type.
+//
+// But compare this defect report:
+//   http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3110.html
+// "Bitmask types need operator~ in order to clear a value from the bitmask
+// type, as show [sic] in 17.5.2.1.3 paragraph 4:
+// - To clear a value Y in an object X is to evaluate the expression X &= ~Y.
+// However the definition for fmtflags above does not have well-specified
+// behaviour if the underlying type is smaller than int, because ~int(f) is
+// likely to produce a value outside the range of fmtflags."
+//
+// The underlying problem is that 'short unsigned int' does not fulfill the
+// bitmask requirements, as unary operator ~ performs integral promotions.
+//
+// This would avoid the warning:
+//   rc[C] &= static_cast<std::ctype_base::mask>(~std::ctype_base::space);
+// but seems too violent. This does not avoid the warning:
+//   constexpr auto z = ~std::ctype_base::space;
+//   rc[C] &= z;
+// due to integral promotion. And braces are not allowed here:
+//   rc[C] &= {~std::ctype_base::space};
+// so this code (used in the implementation below):
+//   constexpr std::ctype_base::mask z = {~std::ctype_base::space};
+//   rc[C] &= z;
+// is the least awful thing that works.
 
 namespace
 {
@@ -79,7 +114,9 @@ namespace
             {
             static std::ctype_base::mask rc[table_size];
             std::copy(classic_table(), classic_table() + table_size, rc);
-            rc[C] &= ~std::ctype_base::space;
+            // See "Implementation note" above.
+            constexpr std::ctype_base::mask z = {~std::ctype_base::space};
+            rc[C] &= z;
             return rc;
             }
     };
diff --git a/workhorse.make b/workhorse.make
index f89ac8d..fcf70ef 100644
--- a/workhorse.make
+++ b/workhorse.make
@@ -477,7 +477,6 @@ gcc_common_extra_warnings := \
 wno_conv_objects := \
   CgiUtils.o \
   currency_test.o \
-  facets.o \
   rate_table.o \
   round_glibc.o \
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]