215 lines
9.1 KiB
Diff
215 lines
9.1 KiB
Diff
This patch adds support for the FreeBSD-specific -fformat-extension option,
|
|
which enables additional printf modifiers for the kernel.
|
|
|
|
Introduced here: http://svnweb.freebsd.org/changeset/base/208987
|
|
|
|
Index: tools/clang/include/clang/Driver/Options.td
|
|
===================================================================
|
|
--- tools/clang/include/clang/Driver/Options.td
|
|
+++ tools/clang/include/clang/Driver/Options.td
|
|
@@ -563,6 +563,8 @@ def fno_rewrite_includes : Flag<["-"], "fno-rewrit
|
|
|
|
def ffreestanding : Flag<["-"], "ffreestanding">, Group<f_Group>, Flags<[CC1Option]>,
|
|
HelpText<"Assert that the compilation takes place in a freestanding environment">;
|
|
+def fformat_extensions: Flag<["-"], "fformat-extensions">, Group<f_Group>, Flags<[CC1Option]>,
|
|
+ HelpText<"Enable FreeBSD kernel specific format string extensions">;
|
|
def fgnu_keywords : Flag<["-"], "fgnu-keywords">, Group<f_Group>, Flags<[CC1Option]>,
|
|
HelpText<"Allow GNU-extension keywords regardless of language standard">;
|
|
def fgnu89_inline : Flag<["-"], "fgnu89-inline">, Group<f_Group>, Flags<[CC1Option]>,
|
|
Index: tools/clang/include/clang/Basic/LangOptions.def
|
|
===================================================================
|
|
--- tools/clang/include/clang/Basic/LangOptions.def
|
|
+++ tools/clang/include/clang/Basic/LangOptions.def
|
|
@@ -87,6 +87,7 @@ LANGOPT(RTTI , 1, 1, "run-time type i
|
|
LANGOPT(RTTIData , 1, 1, "emit run-time type information data")
|
|
LANGOPT(MSBitfields , 1, 0, "Microsoft-compatible structure layout")
|
|
LANGOPT(Freestanding, 1, 0, "freestanding implementation")
|
|
+LANGOPT(FormatExtensions , 1, 0, "FreeBSD format extensions")
|
|
LANGOPT(NoBuiltin , 1, 0, "disable builtin functions")
|
|
LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions")
|
|
|
|
Index: tools/clang/include/clang/Analysis/Analyses/FormatString.h
|
|
===================================================================
|
|
--- tools/clang/include/clang/Analysis/Analyses/FormatString.h
|
|
+++ tools/clang/include/clang/Analysis/Analyses/FormatString.h
|
|
@@ -158,6 +158,11 @@ class ConversionSpecifier {
|
|
ObjCObjArg, // '@'
|
|
ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
|
|
|
|
+ // FreeBSD specific specifiers
|
|
+ FreeBSDbArg,
|
|
+ FreeBSDDArg,
|
|
+ FreeBSDrArg,
|
|
+
|
|
// GlibC specific specifiers.
|
|
PrintErrno, // 'm'
|
|
|
|
Index: tools/clang/lib/Sema/SemaChecking.cpp
|
|
===================================================================
|
|
--- tools/clang/lib/Sema/SemaChecking.cpp
|
|
+++ tools/clang/lib/Sema/SemaChecking.cpp
|
|
@@ -3074,6 +3074,40 @@ CheckPrintfHandler::HandlePrintfSpecifier(const an
|
|
CoveredArgs.set(argIndex);
|
|
}
|
|
|
|
+ // FreeBSD extensions
|
|
+ if (CS.getKind() == ConversionSpecifier::FreeBSDbArg ||
|
|
+ CS.getKind() == ConversionSpecifier::FreeBSDDArg) {
|
|
+ // claim the second argument
|
|
+ CoveredArgs.set(argIndex + 1);
|
|
+
|
|
+ // Now type check the data expression that matches the
|
|
+ // format specifier.
|
|
+ const Expr *Ex = getDataArg(argIndex);
|
|
+ const analyze_printf::ArgType &AT =
|
|
+ (CS.getKind() == ConversionSpecifier::FreeBSDbArg) ?
|
|
+ ArgType(S.Context.IntTy) : ArgType::CStrTy;
|
|
+ if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType()))
|
|
+ S.Diag(getLocationOfByte(CS.getStart()),
|
|
+ diag::warn_format_conversion_argument_type_mismatch)
|
|
+ << AT.getRepresentativeType(S.Context) << Ex->getType()
|
|
+ << getSpecifierRange(startSpecifier, specifierLen)
|
|
+ << Ex->getSourceRange();
|
|
+
|
|
+ // Now type check the data expression that matches the
|
|
+ // format specifier.
|
|
+ Ex = getDataArg(argIndex + 1);
|
|
+ const analyze_printf::ArgType &AT2 = ArgType::CStrTy;
|
|
+ if (AT2.isValid() && !AT2.matchesType(S.Context, Ex->getType()))
|
|
+ S.Diag(getLocationOfByte(CS.getStart()),
|
|
+ diag::warn_format_conversion_argument_type_mismatch)
|
|
+ << AT2.getRepresentativeType(S.Context) << Ex->getType()
|
|
+ << getSpecifierRange(startSpecifier, specifierLen)
|
|
+ << Ex->getSourceRange();
|
|
+
|
|
+ return true;
|
|
+ }
|
|
+ // END OF FREEBSD EXTENSIONS
|
|
+
|
|
// Check for using an Objective-C specific conversion specifier
|
|
// in a non-ObjC literal.
|
|
if (!ObjCContext && CS.isObjCArg()) {
|
|
Index: tools/clang/lib/Driver/Tools.cpp
|
|
===================================================================
|
|
--- tools/clang/lib/Driver/Tools.cpp
|
|
+++ tools/clang/lib/Driver/Tools.cpp
|
|
@@ -3517,6 +3517,7 @@ void Clang::ConstructJob(Compilation &C, const Job
|
|
|
|
// Forward -f (flag) options which we can pass directly.
|
|
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
|
|
+ Args.AddLastArg(CmdArgs, options::OPT_fformat_extensions);
|
|
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
|
|
Args.AddLastArg(CmdArgs, options::OPT_fstandalone_debug);
|
|
Args.AddLastArg(CmdArgs, options::OPT_fno_standalone_debug);
|
|
Index: tools/clang/lib/Frontend/CompilerInvocation.cpp
|
|
===================================================================
|
|
--- tools/clang/lib/Frontend/CompilerInvocation.cpp
|
|
+++ tools/clang/lib/Frontend/CompilerInvocation.cpp
|
|
@@ -1443,6 +1443,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgLi
|
|
Opts.ShortWChar = Args.hasFlag(OPT_fshort_wchar, OPT_fno_short_wchar, false);
|
|
Opts.ShortEnums = Args.hasArg(OPT_fshort_enums);
|
|
Opts.Freestanding = Args.hasArg(OPT_ffreestanding);
|
|
+ Opts.FormatExtensions = Args.hasArg(OPT_fformat_extensions);
|
|
Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
|
|
Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin);
|
|
Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
|
|
Index: tools/clang/lib/Analysis/FormatString.cpp
|
|
===================================================================
|
|
--- tools/clang/lib/Analysis/FormatString.cpp
|
|
+++ tools/clang/lib/Analysis/FormatString.cpp
|
|
@@ -548,6 +548,11 @@ const char *ConversionSpecifier::toString() const
|
|
// Objective-C specific specifiers.
|
|
case ObjCObjArg: return "@";
|
|
|
|
+ // FreeBSD specific specifiers.
|
|
+ case FreeBSDbArg: return "b";
|
|
+ case FreeBSDDArg: return "D";
|
|
+ case FreeBSDrArg: return "r";
|
|
+
|
|
// GlibC specific specifiers.
|
|
case PrintErrno: return "m";
|
|
}
|
|
@@ -626,6 +631,7 @@ bool FormatSpecifier::hasValidLengthModifier(const
|
|
case ConversionSpecifier::xArg:
|
|
case ConversionSpecifier::XArg:
|
|
case ConversionSpecifier::nArg:
|
|
+ case ConversionSpecifier::FreeBSDrArg:
|
|
return true;
|
|
default:
|
|
return false;
|
|
@@ -654,6 +660,7 @@ bool FormatSpecifier::hasValidLengthModifier(const
|
|
case ConversionSpecifier::nArg:
|
|
case ConversionSpecifier::cArg:
|
|
case ConversionSpecifier::sArg:
|
|
+ case ConversionSpecifier::FreeBSDrArg:
|
|
case ConversionSpecifier::ScanListArg:
|
|
return true;
|
|
default:
|
|
@@ -774,6 +781,9 @@ bool FormatSpecifier::hasStandardConversionSpecifi
|
|
case ConversionSpecifier::SArg:
|
|
return LangOpt.ObjC1 || LangOpt.ObjC2;
|
|
case ConversionSpecifier::InvalidSpecifier:
|
|
+ case ConversionSpecifier::FreeBSDbArg:
|
|
+ case ConversionSpecifier::FreeBSDDArg:
|
|
+ case ConversionSpecifier::FreeBSDrArg:
|
|
case ConversionSpecifier::PrintErrno:
|
|
case ConversionSpecifier::DArg:
|
|
case ConversionSpecifier::OArg:
|
|
Index: tools/clang/lib/Analysis/PrintfFormatString.cpp
|
|
===================================================================
|
|
--- tools/clang/lib/Analysis/PrintfFormatString.cpp
|
|
+++ tools/clang/lib/Analysis/PrintfFormatString.cpp
|
|
@@ -198,10 +198,25 @@ static PrintfSpecifierResult ParsePrintfSpecifier(
|
|
case '@': k = ConversionSpecifier::ObjCObjArg; break;
|
|
// Glibc specific.
|
|
case 'm': k = ConversionSpecifier::PrintErrno; break;
|
|
+ // FreeBSD format extensions
|
|
+ case 'b':
|
|
+ if (LO.FormatExtensions)
|
|
+ k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
|
|
+ break;
|
|
+ case 'r':
|
|
+ if (LO.FormatExtensions)
|
|
+ k = ConversionSpecifier::FreeBSDrArg;
|
|
+ break;
|
|
+ case 'y':
|
|
+ if (LO.FormatExtensions)
|
|
+ k = ConversionSpecifier::iArg;
|
|
+ break;
|
|
// Apple-specific
|
|
case 'D':
|
|
if (Target.getTriple().isOSDarwin())
|
|
k = ConversionSpecifier::DArg;
|
|
+ else if (LO.FormatExtensions)
|
|
+ k = ConversionSpecifier::FreeBSDDArg; // u_char * followed by char *
|
|
break;
|
|
case 'O':
|
|
if (Target.getTriple().isOSDarwin())
|
|
@@ -216,6 +231,10 @@ static PrintfSpecifierResult ParsePrintfSpecifier(
|
|
FS.setConversionSpecifier(CS);
|
|
if (CS.consumesDataArgument() && !FS.usesPositionalArg())
|
|
FS.setArgIndex(argIndex++);
|
|
+ // FreeBSD extension
|
|
+ if (k == ConversionSpecifier::FreeBSDbArg ||
|
|
+ k == ConversionSpecifier::FreeBSDDArg)
|
|
+ argIndex++;
|
|
|
|
if (k == ConversionSpecifier::InvalidSpecifier) {
|
|
// Assume the conversion takes one argument.
|
|
@@ -618,6 +637,7 @@ bool PrintfSpecifier::hasValidPlusPrefix() const {
|
|
case ConversionSpecifier::GArg:
|
|
case ConversionSpecifier::aArg:
|
|
case ConversionSpecifier::AArg:
|
|
+ case ConversionSpecifier::FreeBSDrArg:
|
|
return true;
|
|
|
|
default:
|
|
@@ -643,6 +663,7 @@ bool PrintfSpecifier::hasValidAlternativeForm() co
|
|
case ConversionSpecifier::FArg:
|
|
case ConversionSpecifier::gArg:
|
|
case ConversionSpecifier::GArg:
|
|
+ case ConversionSpecifier::FreeBSDrArg:
|
|
return true;
|
|
|
|
default:
|