r348889 - Emit -Wformat properly for bit-field promotions.

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 11 11:22:20 PST 2018


On Tue, Dec 11, 2018 at 2:21 PM Aaron Ballman via cfe-commits
<cfe-commits at 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 at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


More information about the cfe-commits mailing list