On Tue, Dec 11, 2018 at 2:21 PM Aaron Ballman via cfe-commits <cfe-commits@lists.llvm.org> wrote: > > Author: aaronballman > Date: Tue Dec 11 11:18:01 2018 > New Revision: 348889 > > URL: http://llvm.org/viewvc/llvm-project?rev=348889&view=rev > Log: > Emit -Wformat properly for bit-field promotions. > > Only explicitly look through integer and floating-point promotion where the > result type is actually a promotion, which is not always the case for > bit-fields in C.
Patch by Bevin Hansson. (Sorry for missing that in the commit message, Bevin!) ~Aaron > > Added: > cfe/trunk/test/Sema/format-strings-bitfield-promotion.c > cfe/trunk/test/Sema/format-strings-bitfield-promotion.cxx > Modified: > cfe/trunk/lib/Sema/SemaChecking.cpp > > Modified: cfe/trunk/lib/Sema/SemaChecking.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=348889&r1=348888&r2=348889&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) > +++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue Dec 11 11:18:01 2018 > @@ -7709,6 +7709,24 @@ shouldNotPrintDirectly(const ASTContext > 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. > + return ICE->getCastKind() == CK_IntegralCast && > + From->isPromotableIntegerType() && > + S.Context.getPromotedIntegerType(From) == To; > +} > + > bool > CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier > &FS, > const char *StartSpecifier, > @@ -7736,11 +7754,11 @@ CheckPrintfHandler::checkFormatExpr(cons > > // 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(); > > > Added: cfe/trunk/test/Sema/format-strings-bitfield-promotion.c > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-bitfield-promotion.c?rev=348889&view=auto > ============================================================================== > --- cfe/trunk/test/Sema/format-strings-bitfield-promotion.c (added) > +++ cfe/trunk/test/Sema/format-strings-bitfield-promotion.c Tue Dec 11 > 11:18:01 2018 > @@ -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'}} > +} > > Added: cfe/trunk/test/Sema/format-strings-bitfield-promotion.cxx > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-bitfield-promotion.cxx?rev=348889&view=auto > ============================================================================== > --- cfe/trunk/test/Sema/format-strings-bitfield-promotion.cxx (added) > +++ cfe/trunk/test/Sema/format-strings-bitfield-promotion.cxx Tue Dec 11 > 11:18:01 2018 > @@ -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); > +} > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits