Parse 'technical term' format specifier.
Objective-C format strings now support modifier flags
that can be attached to a '@' conversion. Currently
the only one supported, as of iOS 9 and OS X 10.11,
is the new "technical term", denoted by the flag "tt",
for example:
%[tt]@
instead of just:
%@
The 'tt' stands for "technical term", which is used
by the string-localization facilities on Darwin to
add the appropriate spacing or quotation depending
the language locale.
Implements <rdar://problem/20374720>.
llvm-svn: 241243
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 870da78..5737e83 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3572,8 +3572,18 @@
const char *startSpecifier, unsigned specifierLen);
bool checkForCStrMembers(const analyze_printf::ArgType &AT,
const Expr *E);
+
+ void HandleEmptyObjCModifierFlag(const char *startFlag,
+ unsigned flagLen) override;
-};
+ void HandleInvalidObjCModifierFlag(const char *startFlag,
+ unsigned flagLen) override;
+
+ void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart,
+ const char *flagsEnd,
+ const char *conversionPosition)
+ override;
+};
}
bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier(
@@ -3693,6 +3703,41 @@
getSpecifierRange(ignoredFlag.getPosition(), 1)));
}
+// void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc,
+// bool IsStringLocation, Range StringRange,
+// ArrayRef<FixItHint> Fixit = None);
+
+void CheckPrintfHandler::HandleEmptyObjCModifierFlag(const char *startFlag,
+ unsigned flagLen) {
+ // Warn about an empty flag.
+ EmitFormatDiagnostic(S.PDiag(diag::warn_printf_empty_objc_flag),
+ getLocationOfByte(startFlag),
+ /*IsStringLocation*/true,
+ getSpecifierRange(startFlag, flagLen));
+}
+
+void CheckPrintfHandler::HandleInvalidObjCModifierFlag(const char *startFlag,
+ unsigned flagLen) {
+ // Warn about an invalid flag.
+ auto Range = getSpecifierRange(startFlag, flagLen);
+ StringRef flag(startFlag, flagLen);
+ EmitFormatDiagnostic(S.PDiag(diag::warn_printf_invalid_objc_flag) << flag,
+ getLocationOfByte(startFlag),
+ /*IsStringLocation*/true,
+ Range, FixItHint::CreateRemoval(Range));
+}
+
+void CheckPrintfHandler::HandleObjCFlagsWithNonObjCConversion(
+ const char *flagsStart, const char *flagsEnd, const char *conversionPosition) {
+ // Warn about using '[...]' without a '@' conversion.
+ auto Range = getSpecifierRange(flagsStart, flagsEnd - flagsStart + 1);
+ auto diag = diag::warn_printf_ObjCflags_without_ObjCConversion;
+ EmitFormatDiagnostic(S.PDiag(diag) << StringRef(conversionPosition, 1),
+ getLocationOfByte(conversionPosition),
+ /*IsStringLocation*/true,
+ Range, FixItHint::CreateRemoval(Range));
+}
+
// Determines if the specified is a C++ class or struct containing
// a member with the specified name and kind (e.g. a CXXMethodDecl named
// "c_str()").