Skip to content

Commit bf4832c

Browse files
committed
Add semantic checking that the "thousands grouping"
prefix in a printf format string is matched with the appropriate conversion specifier. llvm-svn: 123055
1 parent a322cae commit bf4832c

File tree

4 files changed

+27
-0
lines changed

4 files changed

+27
-0
lines changed

clang/include/clang/Analysis/Analyses/FormatString.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,9 @@ class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
450450
/// more than one type.
451451
ArgTypeResult getArgType(ASTContext &Ctx) const;
452452

453+
const OptionalFlag &hasThousandsGrouping() const {
454+
return HasThousandsGrouping;
455+
}
453456
const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
454457
const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }
455458
const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }
@@ -470,6 +473,7 @@ class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
470473
bool hasValidLeadingZeros() const;
471474
bool hasValidSpacePrefix() const;
472475
bool hasValidLeftJustified() const;
476+
bool hasValidThousandsGroupingPrefix() const;
473477

474478
bool hasValidPrecision() const;
475479
bool hasValidFieldWidth() const;

clang/lib/Analysis/PrintfFormatString.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,24 @@ bool PrintfSpecifier::hasValidLeftJustified() const {
590590
}
591591
}
592592

593+
bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
594+
if (!HasThousandsGrouping)
595+
return true;
596+
597+
switch (CS.getKind()) {
598+
case ConversionSpecifier::dArg:
599+
case ConversionSpecifier::iArg:
600+
case ConversionSpecifier::uArg:
601+
case ConversionSpecifier::fArg:
602+
case ConversionSpecifier::FArg:
603+
case ConversionSpecifier::gArg:
604+
case ConversionSpecifier::GArg:
605+
return true;
606+
default:
607+
return false;
608+
}
609+
}
610+
593611
bool PrintfSpecifier::hasValidPrecision() const {
594612
if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
595613
return true;

clang/lib/Sema/SemaChecking.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,6 +1491,8 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
14911491
}
14921492

14931493
// Check each flag does not conflict with any other component.
1494+
if (!FS.hasValidThousandsGroupingPrefix())
1495+
HandleFlag(FS, FS.hasThousandsGrouping(), startSpecifier, specifierLen);
14941496
if (!FS.hasValidLeadingZeros())
14951497
HandleFlag(FS, FS.hasLeadingZeros(), startSpecifier, specifierLen);
14961498
if (!FS.hasValidPlusPrefix())

clang/test/Sema/format-strings.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,4 +336,7 @@ void posix_extensions() {
336336
// Test %'d, "thousands grouping".
337337
// <rdar://problem/8816343>
338338
printf("%'d\n", 123456789); // no-warning
339+
printf("%'i\n", 123456789); // no-warning
340+
printf("%'f\n", (float) 1.0); // no-warning
341+
printf("%'p\n", (void*) 0); // expected-warning{{results in undefined behavior with 'p' conversion specifier}}
339342
}

0 commit comments

Comments
 (0)