@@ -11500,26 +11500,18 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
11500
11500
ImplicitMatch == ArgType::NoMatchTypeConfusion)
11501
11501
Match = ImplicitMatch;
11502
11502
assert(Match != ArgType::MatchPromotion);
11503
-
11504
- // Look through unscoped enums to their underlying type.
11503
+ // Look through enums to their underlying type.
11505
11504
bool IsEnum = false;
11506
11505
bool IsScopedEnum = false;
11507
- QualType IntendedTy = ExprTy;
11508
11506
if (auto EnumTy = ExprTy->getAs<EnumType>()) {
11509
- IntendedTy = EnumTy->getDecl()->getIntegerType();
11510
- if (EnumTy->isUnscopedEnumerationType()) {
11511
- ExprTy = IntendedTy;
11512
- // This controls whether we're talking about the underlying type or not,
11513
- // which we only want to do when it's an unscoped enum.
11514
- IsEnum = true;
11515
- } else {
11516
- IsScopedEnum = true;
11517
- }
11507
+ ExprTy = EnumTy->getDecl()->getIntegerType();
11508
+ IsEnum = true;
11518
11509
}
11519
11510
11520
11511
// %C in an Objective-C context prints a unichar, not a wchar_t.
11521
11512
// If the argument is an integer of some kind, believe the %C and suggest
11522
11513
// a cast instead of changing the conversion specifier.
11514
+ QualType IntendedTy = ExprTy;
11523
11515
if (isObjCContext() &&
11524
11516
FS.getConversionSpecifier().getKind() == ConversionSpecifier::CArg) {
11525
11517
if (ExprTy->isIntegralOrUnscopedEnumerationType() &&
@@ -11555,10 +11547,8 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
11555
11547
std::tie(CastTy, CastTyName) = shouldNotPrintDirectly(S.Context, IntendedTy, E);
11556
11548
if (!CastTy.isNull()) {
11557
11549
// %zi/%zu and %td/%tu are OK to use for NSInteger/NSUInteger of type int
11558
- // (long in ASTContext). Only complain to pedants or when they're the
11559
- // underlying type of a scoped enum (which always needs a cast).
11560
- if (!IsScopedEnum &&
11561
- (CastTyName == "NSInteger" || CastTyName == "NSUInteger") &&
11550
+ // (long in ASTContext). Only complain to pedants.
11551
+ if ((CastTyName == "NSInteger" || CastTyName == "NSUInteger") &&
11562
11552
(AT.isSizeT() || AT.isPtrdiffT()) &&
11563
11553
AT.matchesType(S.Context, CastTy))
11564
11554
Match = ArgType::NoMatchPedantic;
@@ -11613,15 +11603,20 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
11613
11603
// should be printed as 'long' for 64-bit compatibility.)
11614
11604
// Rather than emitting a normal format/argument mismatch, we want to
11615
11605
// add a cast to the recommended type (and correct the format string
11616
- // if necessary). We should also do so for scoped enumerations.
11606
+ // if necessary).
11617
11607
SmallString<16> CastBuf;
11618
11608
llvm::raw_svector_ostream CastFix(CastBuf);
11619
11609
CastFix << (S.LangOpts.CPlusPlus ? "static_cast<" : "(");
11620
- IntendedTy.print(CastFix, S.Context.getPrintingPolicy());
11610
+ if (IsScopedEnum) {
11611
+ CastFix << AT.getRepresentativeType(S.Context).getAsString(
11612
+ S.Context.getPrintingPolicy());
11613
+ } else {
11614
+ IntendedTy.print(CastFix, S.Context.getPrintingPolicy());
11615
+ }
11621
11616
CastFix << (S.LangOpts.CPlusPlus ? ">" : ")");
11622
11617
11623
11618
SmallVector<FixItHint,4> Hints;
11624
- if (AT.matchesType(S.Context, IntendedTy) != ArgType::Match ||
11619
+ if ((! AT.matchesType(S.Context, IntendedTy) && !IsScopedEnum) ||
11625
11620
ShouldNotPrintDirectly)
11626
11621
Hints.push_back(FixItHint::CreateReplacement(SpecRange, os.str()));
11627
11622
@@ -11649,7 +11644,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
11649
11644
Hints.push_back(FixItHint::CreateInsertion(After, ")"));
11650
11645
}
11651
11646
11652
- if (ShouldNotPrintDirectly && !IsScopedEnum ) {
11647
+ if (ShouldNotPrintDirectly) {
11653
11648
// The expression has a type that should not be printed directly.
11654
11649
// We extract the name from the typedef because we don't want to show
11655
11650
// the underlying type in the diagnostic.
0 commit comments