[PATCH] D51211: [Sema] Emit -Wformat properly for bitfield promotions.

Bevin Hansson via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 24 04:27:28 PDT 2018


ebevhan created this revision.
ebevhan added reviewers: krememek, rsmith.
Herald added a subscriber: cfe-commits.

The integer promotions apply to bitfields as well, but
rather oddly. If you have a bitfield with a lower width
than int, then the type of the member expression will
be int regardless of the type of the bitfield member.
This means that you can effectively get 'type demotion'
in a bitfield member expression.

However, when analyzing format string types, we
would look through argument promotions like integer
promotion. Looking through bitfield demotion means
that we would get the wrong type when analyzing,
hiding -Wformat issues.

This patch fixes this so that we only explicitly look
through integer and floating point promotion where
the result type is actually a promotion.


Repository:
  rC Clang

https://reviews.llvm.org/D51211

Files:
  lib/Sema/SemaChecking.cpp
  test/Sema/format-strings.c


Index: test/Sema/format-strings.c
===================================================================
--- test/Sema/format-strings.c
+++ test/Sema/format-strings.c
@@ -692,3 +692,17 @@
   // This caused crashes due to invalid casts.
   printf(1 > 0); // expected-warning{{format string is not a string literal}} expected-warning{{incompatible integer to pointer conversion}} expected-note at format-strings.c:*{{passing argument to parameter here}} expected-note{{to avoid this}}
 }
+
+struct bitfields {
+  long a : 2;
+  unsigned long b : 2;
+  long c : 32;          // assumes that int is 32 bits
+  unsigned long d : 32; // assumes that int is 32 bits
+} bf;
+
+void bitfield_promotion() {
+  printf("%ld", bf.a); // expected-warning {{format specifies type 'long' but the argument has type 'int'}}
+  printf("%lu", bf.b); // expected-warning {{format specifies type 'unsigned long' but the argument has type 'int'}}
+  printf("%ld", bf.c); // expected-warning {{format specifies type 'long' but the argument has type 'int'}}
+  printf("%lu", bf.d); // expected-warning {{format specifies type 'unsigned long' but the argument has type 'unsigned int'}}
+}
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -7582,6 +7582,26 @@
   return std::make_pair(QualType(), StringRef());
 }
 
+/// Return true if \p ICE is an implicit argument promotion of an arithmetic
+/// type. Bit-field 'promotions' from a higher ranked type to a lower ranked
+/// type do not count.
+static bool
+isArithmeticArgumentPromotion(Sema &S, const ImplicitCastExpr *ICE) {
+  QualType From = ICE->getSubExpr()->getType();
+  QualType To = ICE->getType();
+  // It's a floating promotion if the source type is a lower rank.
+  if (ICE->getCastKind() == CK_FloatingCast &&
+      S.Context.getFloatingTypeOrder(From, To) < 0)
+    return true;
+  // It's an integer promotion if the destination type is the promoted
+  // source type.
+  if (ICE->getCastKind() == CK_IntegralCast &&
+      From->isPromotableIntegerType() &&
+      S.Context.getPromotedIntegerType(From) == To)
+    return true;
+  return false;
+}
+
 bool
 CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
                                     const char *StartSpecifier,
@@ -7609,11 +7629,11 @@
 
   // Look through argument promotions for our error message's reported type.
   // This includes the integral and floating promotions, but excludes array
-  // and function pointer decay; seeing that an argument intended to be a
-  // string has type 'char [6]' is probably more confusing than 'char *'.
+  // and function pointer decay (seeing that an argument intended to be a
+  // string has type 'char [6]' is probably more confusing than 'char *') and
+  // certain bitfield promotions (bitfields can be 'demoted' to a lesser type).
   if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
-    if (ICE->getCastKind() == CK_IntegralCast ||
-        ICE->getCastKind() == CK_FloatingCast) {
+    if (isArithmeticArgumentPromotion(S, ICE)) {
       E = ICE->getSubExpr();
       ExprTy = E->getType();
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D51211.162340.patch
Type: text/x-patch
Size: 3203 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180824/ad604cd9/attachment.bin>


More information about the cfe-commits mailing list