[PATCH] D51211: [Sema] Emit -Wformat properly for bitfield promotions.
Bevin Hansson via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 18 00:27:59 PST 2018
ebevhan updated this revision to Diff 178605.
ebevhan added a comment.
Use `auto`.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D51211/new/
https://reviews.llvm.org/D51211
Files:
lib/Sema/SemaChecking.cpp
test/Sema/format-strings-bitfield-promotion.c
test/Sema/format-strings-bitfield-promotion.cxx
Index: test/Sema/format-strings-bitfield-promotion.cxx
===================================================================
--- /dev/null
+++ test/Sema/format-strings-bitfield-promotion.cxx
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fsyntax-only -verify %s
+
+// In C++, the bitfield promotion from long to int does not occur, unlike C.
+// expected-no-diagnostics
+
+int printf(const char *restrict, ...);
+
+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);
+ printf("%lu", bf.b);
+ printf("%ld", bf.c);
+ printf("%lu", bf.d);
+}
Index: test/Sema/format-strings-bitfield-promotion.c
===================================================================
--- /dev/null
+++ test/Sema/format-strings-bitfield-promotion.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fsyntax-only -verify %s
+
+int printf(const char *restrict, ...);
+
+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
@@ -7709,6 +7709,30 @@
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 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;
+ // Look through vector types, since we do default argument promotion for
+ // those in OpenCL.
+ if (const auto *VecTy = From->getAs<ExtVectorType>())
+ From = VecTy->getElementType();
+ if (const auto *VecTy = To->getAs<ExtVectorType>())
+ To = VecTy->getElementType();
+ // It's a floating promotion if the source type is a lower rank.
+ return ICE->getCastKind() == CK_FloatingCast &&
+ S.Context.getFloatingTypeOrder(From, To) < 0;
+}
+
bool
CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
const char *StartSpecifier,
@@ -7736,11 +7760,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.178605.patch
Type: text/x-patch
Size: 4201 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20181218/0bd1cfae/attachment.bin>
More information about the cfe-commits
mailing list