Skip to content

Commit 40ba1f6

Browse files
authored
[clang] Update -Wformat warnings for fixed-point format specifiers (llvm#82855)
ISO/IEC TR 18037 defines %r, %R, %k, and %K for fixed point format specifiers. -Wformat should not warn on these when they are provided.
1 parent 16e74fd commit 40ba1f6

File tree

6 files changed

+306
-3
lines changed

6 files changed

+306
-3
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2981,6 +2981,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
29812981
// corresponding saturated type for a given fixed point type.
29822982
QualType getCorrespondingSaturatedType(QualType Ty) const;
29832983

2984+
// Per ISO N1169, this method accepts fixed point types and returns the
2985+
// corresponding non-saturated type for a given fixed point type.
2986+
QualType getCorrespondingUnsaturatedType(QualType Ty) const;
2987+
29842988
// This method accepts fixed point types and returns the corresponding signed
29852989
// type. Unlike getCorrespondingUnsignedType(), this only accepts unsigned
29862990
// fixed point types because there are unsigned integer types like bool and

clang/include/clang/AST/FormatString.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,14 @@ class ConversionSpecifier {
171171

172172
ZArg, // MS extension
173173

174+
// ISO/IEC TR 18037 (fixed-point) specific specifiers.
175+
kArg, // %k for signed accum types
176+
KArg, // %K for unsigned accum types
177+
rArg, // %r for signed fract types
178+
RArg, // %R for unsigned fract types
179+
FixedPointArgBeg = kArg,
180+
FixedPointArgEnd = RArg,
181+
174182
// Objective-C specific specifiers.
175183
ObjCObjArg, // '@'
176184
ObjCBeg = ObjCObjArg,
@@ -237,6 +245,9 @@ class ConversionSpecifier {
237245
bool isDoubleArg() const {
238246
return kind >= DoubleArgBeg && kind <= DoubleArgEnd;
239247
}
248+
bool isFixedPointArg() const {
249+
return kind >= FixedPointArgBeg && kind <= FixedPointArgEnd;
250+
}
240251

241252
const char *toString() const;
242253

clang/lib/AST/ASTContext.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13314,6 +13314,42 @@ QualType ASTContext::getCommonSugaredType(QualType X, QualType Y,
1331413314
return R;
1331513315
}
1331613316

13317+
QualType ASTContext::getCorrespondingUnsaturatedType(QualType Ty) const {
13318+
assert(Ty->isFixedPointType());
13319+
13320+
if (Ty->isUnsaturatedFixedPointType())
13321+
return Ty;
13322+
13323+
switch (Ty->castAs<BuiltinType>()->getKind()) {
13324+
default:
13325+
llvm_unreachable("Not a saturated fixed point type!");
13326+
case BuiltinType::SatShortAccum:
13327+
return ShortAccumTy;
13328+
case BuiltinType::SatAccum:
13329+
return AccumTy;
13330+
case BuiltinType::SatLongAccum:
13331+
return LongAccumTy;
13332+
case BuiltinType::SatUShortAccum:
13333+
return UnsignedShortAccumTy;
13334+
case BuiltinType::SatUAccum:
13335+
return UnsignedAccumTy;
13336+
case BuiltinType::SatULongAccum:
13337+
return UnsignedLongAccumTy;
13338+
case BuiltinType::SatShortFract:
13339+
return ShortFractTy;
13340+
case BuiltinType::SatFract:
13341+
return FractTy;
13342+
case BuiltinType::SatLongFract:
13343+
return LongFractTy;
13344+
case BuiltinType::SatUShortFract:
13345+
return UnsignedShortFractTy;
13346+
case BuiltinType::SatUFract:
13347+
return UnsignedFractTy;
13348+
case BuiltinType::SatULongFract:
13349+
return UnsignedLongFractTy;
13350+
}
13351+
}
13352+
1331713353
QualType ASTContext::getCorrespondingSaturatedType(QualType Ty) const {
1331813354
assert(Ty->isFixedPointType());
1331913355

clang/lib/AST/FormatString.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,10 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
403403
else if (ETy->isUnscopedEnumerationType())
404404
argTy = ETy->getDecl()->getIntegerType();
405405
}
406+
407+
if (argTy->isSaturatedFixedPointType())
408+
argTy = C.getCorrespondingUnsaturatedType(argTy);
409+
406410
argTy = C.getCanonicalType(argTy).getUnqualifiedType();
407411

408412
if (T == argTy)
@@ -761,6 +765,16 @@ const char *ConversionSpecifier::toString() const {
761765

762766
// MS specific specifiers.
763767
case ZArg: return "Z";
768+
769+
// ISO/IEC TR 18037 (fixed-point) specific specifiers.
770+
case rArg:
771+
return "r";
772+
case RArg:
773+
return "R";
774+
case kArg:
775+
return "k";
776+
case KArg:
777+
return "K";
764778
}
765779
return nullptr;
766780
}
@@ -825,6 +839,9 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target,
825839
if (LO.OpenCL && CS.isDoubleArg())
826840
return !VectorNumElts.isInvalid();
827841

842+
if (CS.isFixedPointArg())
843+
return true;
844+
828845
if (Target.getTriple().isOSMSVCRT()) {
829846
switch (CS.getKind()) {
830847
case ConversionSpecifier::cArg:
@@ -877,6 +894,9 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target,
877894
return true;
878895
}
879896

897+
if (CS.isFixedPointArg())
898+
return true;
899+
880900
switch (CS.getKind()) {
881901
case ConversionSpecifier::bArg:
882902
case ConversionSpecifier::BArg:
@@ -1043,6 +1063,11 @@ bool FormatSpecifier::hasStandardConversionSpecifier(
10431063
case ConversionSpecifier::UArg:
10441064
case ConversionSpecifier::ZArg:
10451065
return false;
1066+
case ConversionSpecifier::rArg:
1067+
case ConversionSpecifier::RArg:
1068+
case ConversionSpecifier::kArg:
1069+
case ConversionSpecifier::KArg:
1070+
return LangOpt.FixedPoint;
10461071
}
10471072
llvm_unreachable("Invalid ConversionSpecifier Kind!");
10481073
}

clang/lib/AST/PrintfFormatString.cpp

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
348348
case 'r':
349349
if (isFreeBSDKPrintf)
350350
k = ConversionSpecifier::FreeBSDrArg; // int
351+
else if (LO.FixedPoint)
352+
k = ConversionSpecifier::rArg;
351353
break;
352354
case 'y':
353355
if (isFreeBSDKPrintf)
@@ -373,6 +375,20 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
373375
if (Target.getTriple().isOSMSVCRT())
374376
k = ConversionSpecifier::ZArg;
375377
break;
378+
// ISO/IEC TR 18037 (fixed-point) specific.
379+
// NOTE: 'r' is handled up above since FreeBSD also supports %r.
380+
case 'k':
381+
if (LO.FixedPoint)
382+
k = ConversionSpecifier::kArg;
383+
break;
384+
case 'K':
385+
if (LO.FixedPoint)
386+
k = ConversionSpecifier::KArg;
387+
break;
388+
case 'R':
389+
if (LO.FixedPoint)
390+
k = ConversionSpecifier::RArg;
391+
break;
376392
}
377393

378394
// Check to see if we used the Objective-C modifier flags with
@@ -627,6 +643,9 @@ ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx,
627643
}
628644
}
629645

646+
if (CS.isFixedPointArg() && !Ctx.getLangOpts().FixedPoint)
647+
return ArgType::Invalid();
648+
630649
switch (CS.getKind()) {
631650
case ConversionSpecifier::sArg:
632651
if (LM.getKind() == LengthModifier::AsWideChar) {
@@ -658,6 +677,50 @@ ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx,
658677
return ArgType::CPointerTy;
659678
case ConversionSpecifier::ObjCObjArg:
660679
return ArgType::ObjCPointerTy;
680+
case ConversionSpecifier::kArg:
681+
switch (LM.getKind()) {
682+
case LengthModifier::None:
683+
return Ctx.AccumTy;
684+
case LengthModifier::AsShort:
685+
return Ctx.ShortAccumTy;
686+
case LengthModifier::AsLong:
687+
return Ctx.LongAccumTy;
688+
default:
689+
return ArgType::Invalid();
690+
}
691+
case ConversionSpecifier::KArg:
692+
switch (LM.getKind()) {
693+
case LengthModifier::None:
694+
return Ctx.UnsignedAccumTy;
695+
case LengthModifier::AsShort:
696+
return Ctx.UnsignedShortAccumTy;
697+
case LengthModifier::AsLong:
698+
return Ctx.UnsignedLongAccumTy;
699+
default:
700+
return ArgType::Invalid();
701+
}
702+
case ConversionSpecifier::rArg:
703+
switch (LM.getKind()) {
704+
case LengthModifier::None:
705+
return Ctx.FractTy;
706+
case LengthModifier::AsShort:
707+
return Ctx.ShortFractTy;
708+
case LengthModifier::AsLong:
709+
return Ctx.LongFractTy;
710+
default:
711+
return ArgType::Invalid();
712+
}
713+
case ConversionSpecifier::RArg:
714+
switch (LM.getKind()) {
715+
case LengthModifier::None:
716+
return Ctx.UnsignedFractTy;
717+
case LengthModifier::AsShort:
718+
return Ctx.UnsignedShortFractTy;
719+
case LengthModifier::AsLong:
720+
return Ctx.UnsignedLongFractTy;
721+
default:
722+
return ArgType::Invalid();
723+
}
661724
default:
662725
break;
663726
}
@@ -955,6 +1018,8 @@ bool PrintfSpecifier::hasValidPlusPrefix() const {
9551018
case ConversionSpecifier::AArg:
9561019
case ConversionSpecifier::FreeBSDrArg:
9571020
case ConversionSpecifier::FreeBSDyArg:
1021+
case ConversionSpecifier::rArg:
1022+
case ConversionSpecifier::kArg:
9581023
return true;
9591024

9601025
default:
@@ -966,7 +1031,7 @@ bool PrintfSpecifier::hasValidAlternativeForm() const {
9661031
if (!HasAlternativeForm)
9671032
return true;
9681033

969-
// Alternate form flag only valid with the bBoxXaAeEfFgG conversions
1034+
// Alternate form flag only valid with the bBoxXaAeEfFgGrRkK conversions
9701035
switch (CS.getKind()) {
9711036
case ConversionSpecifier::bArg:
9721037
case ConversionSpecifier::BArg:
@@ -984,6 +1049,10 @@ bool PrintfSpecifier::hasValidAlternativeForm() const {
9841049
case ConversionSpecifier::GArg:
9851050
case ConversionSpecifier::FreeBSDrArg:
9861051
case ConversionSpecifier::FreeBSDyArg:
1052+
case ConversionSpecifier::rArg:
1053+
case ConversionSpecifier::RArg:
1054+
case ConversionSpecifier::kArg:
1055+
case ConversionSpecifier::KArg:
9871056
return true;
9881057

9891058
default:
@@ -995,7 +1064,7 @@ bool PrintfSpecifier::hasValidLeadingZeros() const {
9951064
if (!HasLeadingZeroes)
9961065
return true;
9971066

998-
// Leading zeroes flag only valid with the bBdiouxXaAeEfFgG conversions
1067+
// Leading zeroes flag only valid with the bBdiouxXaAeEfFgGrRkK conversions
9991068
switch (CS.getKind()) {
10001069
case ConversionSpecifier::bArg:
10011070
case ConversionSpecifier::BArg:
@@ -1018,6 +1087,10 @@ bool PrintfSpecifier::hasValidLeadingZeros() const {
10181087
case ConversionSpecifier::GArg:
10191088
case ConversionSpecifier::FreeBSDrArg:
10201089
case ConversionSpecifier::FreeBSDyArg:
1090+
case ConversionSpecifier::rArg:
1091+
case ConversionSpecifier::RArg:
1092+
case ConversionSpecifier::kArg:
1093+
case ConversionSpecifier::KArg:
10211094
return true;
10221095

10231096
default:
@@ -1044,6 +1117,8 @@ bool PrintfSpecifier::hasValidSpacePrefix() const {
10441117
case ConversionSpecifier::AArg:
10451118
case ConversionSpecifier::FreeBSDrArg:
10461119
case ConversionSpecifier::FreeBSDyArg:
1120+
case ConversionSpecifier::rArg:
1121+
case ConversionSpecifier::kArg:
10471122
return true;
10481123

10491124
default:
@@ -1089,7 +1164,7 @@ bool PrintfSpecifier::hasValidPrecision() const {
10891164
if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
10901165
return true;
10911166

1092-
// Precision is only valid with the bBdiouxXaAeEfFgGsP conversions
1167+
// Precision is only valid with the bBdiouxXaAeEfFgGsPrRkK conversions
10931168
switch (CS.getKind()) {
10941169
case ConversionSpecifier::bArg:
10951170
case ConversionSpecifier::BArg:
@@ -1114,6 +1189,10 @@ bool PrintfSpecifier::hasValidPrecision() const {
11141189
case ConversionSpecifier::FreeBSDrArg:
11151190
case ConversionSpecifier::FreeBSDyArg:
11161191
case ConversionSpecifier::PArg:
1192+
case ConversionSpecifier::rArg:
1193+
case ConversionSpecifier::RArg:
1194+
case ConversionSpecifier::kArg:
1195+
case ConversionSpecifier::KArg:
11171196
return true;
11181197

11191198
default:

0 commit comments

Comments
 (0)