1 This patch adds support for the FreeBSD-specific -fformat-extension option,
2 which enables additional printf modifiers for the kernel.
4 Introduced here: http://svnweb.freebsd.org/changeset/base/208987
6 Index: tools/clang/lib/Frontend/CompilerInvocation.cpp
7 ===================================================================
8 --- tools/clang/lib/Frontend/CompilerInvocation.cpp
9 +++ tools/clang/lib/Frontend/CompilerInvocation.cpp
10 @@ -1319,6 +1319,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgLi
11 Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar);
12 Opts.ShortEnums = Args.hasArg(OPT_fshort_enums);
13 Opts.Freestanding = Args.hasArg(OPT_ffreestanding);
14 + Opts.FormatExtensions = Args.hasArg(OPT_fformat_extensions);
15 Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
16 Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin);
17 Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
18 Index: tools/clang/lib/Analysis/FormatString.cpp
19 ===================================================================
20 --- tools/clang/lib/Analysis/FormatString.cpp
21 +++ tools/clang/lib/Analysis/FormatString.cpp
22 @@ -548,6 +548,11 @@ const char *ConversionSpecifier::toString() const
23 // Objective-C specific specifiers.
24 case ObjCObjArg: return "@";
26 + // FreeBSD specific specifiers.
27 + case FreeBSDbArg: return "b";
28 + case FreeBSDDArg: return "D";
29 + case FreeBSDrArg: return "r";
31 // GlibC specific specifiers.
32 case PrintErrno: return "m";
34 @@ -626,6 +631,7 @@ bool FormatSpecifier::hasValidLengthModifier(const
35 case ConversionSpecifier::xArg:
36 case ConversionSpecifier::XArg:
37 case ConversionSpecifier::nArg:
38 + case ConversionSpecifier::FreeBSDrArg:
42 @@ -654,6 +660,7 @@ bool FormatSpecifier::hasValidLengthModifier(const
43 case ConversionSpecifier::nArg:
44 case ConversionSpecifier::cArg:
45 case ConversionSpecifier::sArg:
46 + case ConversionSpecifier::FreeBSDrArg:
47 case ConversionSpecifier::ScanListArg:
50 @@ -774,6 +781,9 @@ bool FormatSpecifier::hasStandardConversionSpecifi
51 case ConversionSpecifier::SArg:
52 return LangOpt.ObjC1 || LangOpt.ObjC2;
53 case ConversionSpecifier::InvalidSpecifier:
54 + case ConversionSpecifier::FreeBSDbArg:
55 + case ConversionSpecifier::FreeBSDDArg:
56 + case ConversionSpecifier::FreeBSDrArg:
57 case ConversionSpecifier::PrintErrno:
58 case ConversionSpecifier::DArg:
59 case ConversionSpecifier::OArg:
60 Index: tools/clang/lib/Analysis/PrintfFormatString.cpp
61 ===================================================================
62 --- tools/clang/lib/Analysis/PrintfFormatString.cpp
63 +++ tools/clang/lib/Analysis/PrintfFormatString.cpp
64 @@ -198,10 +198,25 @@ static PrintfSpecifierResult ParsePrintfSpecifier(
65 case '@': k = ConversionSpecifier::ObjCObjArg; break;
67 case 'm': k = ConversionSpecifier::PrintErrno; break;
68 + // FreeBSD format extensions
70 + if (LO.FormatExtensions)
71 + k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
74 + if (LO.FormatExtensions)
75 + k = ConversionSpecifier::FreeBSDrArg;
78 + if (LO.FormatExtensions)
79 + k = ConversionSpecifier::iArg;
83 if (Target.getTriple().isOSDarwin())
84 k = ConversionSpecifier::DArg;
85 + else if (LO.FormatExtensions)
86 + k = ConversionSpecifier::FreeBSDDArg; // u_char * followed by char *
89 if (Target.getTriple().isOSDarwin())
90 @@ -216,6 +231,10 @@ static PrintfSpecifierResult ParsePrintfSpecifier(
91 FS.setConversionSpecifier(CS);
92 if (CS.consumesDataArgument() && !FS.usesPositionalArg())
93 FS.setArgIndex(argIndex++);
94 + // FreeBSD extension
95 + if (k == ConversionSpecifier::FreeBSDbArg ||
96 + k == ConversionSpecifier::FreeBSDDArg)
99 if (k == ConversionSpecifier::InvalidSpecifier) {
100 // Assume the conversion takes one argument.
101 @@ -618,6 +637,7 @@ bool PrintfSpecifier::hasValidPlusPrefix() const {
102 case ConversionSpecifier::GArg:
103 case ConversionSpecifier::aArg:
104 case ConversionSpecifier::AArg:
105 + case ConversionSpecifier::FreeBSDrArg:
109 @@ -643,6 +663,7 @@ bool PrintfSpecifier::hasValidAlternativeForm() co
110 case ConversionSpecifier::FArg:
111 case ConversionSpecifier::gArg:
112 case ConversionSpecifier::GArg:
113 + case ConversionSpecifier::FreeBSDrArg:
117 Index: tools/clang/lib/Sema/SemaChecking.cpp
118 ===================================================================
119 --- tools/clang/lib/Sema/SemaChecking.cpp
120 +++ tools/clang/lib/Sema/SemaChecking.cpp
121 @@ -2980,6 +2980,42 @@ CheckPrintfHandler::HandlePrintfSpecifier(const an
122 CoveredArgs.set(argIndex);
125 + // FreeBSD kernel extensions.
126 + if (CS.getKind() == ConversionSpecifier::FreeBSDbArg ||
127 + CS.getKind() == ConversionSpecifier::FreeBSDDArg) {
128 + // We need at least two arguments.
129 + if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex + 1))
132 + // Claim the second argument.
133 + CoveredArgs.set(argIndex + 1);
135 + // Type check the first argument (int for %b, pointer for %D)
136 + const Expr *Ex = getDataArg(argIndex);
137 + const analyze_printf::ArgType &AT =
138 + (CS.getKind() == ConversionSpecifier::FreeBSDbArg) ?
139 + ArgType(S.Context.IntTy) : ArgType::CPointerTy;
140 + if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType()))
141 + S.Diag(getLocationOfByte(CS.getStart()),
142 + diag::warn_printf_conversion_argument_type_mismatch)
143 + << AT.getRepresentativeType(S.Context) << Ex->getType()
144 + << getSpecifierRange(startSpecifier, specifierLen)
145 + << Ex->getSourceRange();
147 + // Type check the second argument (char * for both %b and %D)
148 + Ex = getDataArg(argIndex + 1);
149 + const analyze_printf::ArgType &AT2 = ArgType::CStrTy;
150 + if (AT2.isValid() && !AT2.matchesType(S.Context, Ex->getType()))
151 + S.Diag(getLocationOfByte(CS.getStart()),
152 + diag::warn_printf_conversion_argument_type_mismatch)
153 + << AT2.getRepresentativeType(S.Context) << Ex->getType()
154 + << getSpecifierRange(startSpecifier, specifierLen)
155 + << Ex->getSourceRange();
159 + // END OF FREEBSD EXTENSIONS
161 // Check for using an Objective-C specific conversion specifier
162 // in a non-ObjC literal.
163 if (!ObjCContext && CS.isObjCArg()) {
164 Index: tools/clang/lib/Driver/Tools.cpp
165 ===================================================================
166 --- tools/clang/lib/Driver/Tools.cpp
167 +++ tools/clang/lib/Driver/Tools.cpp
168 @@ -2984,6 +2984,7 @@ void Clang::ConstructJob(Compilation &C, const Job
170 // Forward -f (flag) options which we can pass directly.
171 Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
172 + Args.AddLastArg(CmdArgs, options::OPT_fformat_extensions);
173 Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
174 Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info);
175 Args.AddLastArg(CmdArgs, options::OPT_fno_limit_debug_info);
176 Index: tools/clang/include/clang/Basic/LangOptions.def
177 ===================================================================
178 --- tools/clang/include/clang/Basic/LangOptions.def
179 +++ tools/clang/include/clang/Basic/LangOptions.def
180 @@ -84,6 +84,7 @@ LANGOPT(TraditionalCPP , 1, 0, "traditional CPP
181 LANGOPT(RTTI , 1, 1, "run-time type information")
182 LANGOPT(MSBitfields , 1, 0, "Microsoft-compatible structure layout")
183 LANGOPT(Freestanding, 1, 0, "freestanding implementation")
184 +LANGOPT(FormatExtensions , 1, 0, "FreeBSD format extensions")
185 LANGOPT(NoBuiltin , 1, 0, "disable builtin functions")
186 LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions")
188 Index: tools/clang/include/clang/Analysis/Analyses/FormatString.h
189 ===================================================================
190 --- tools/clang/include/clang/Analysis/Analyses/FormatString.h
191 +++ tools/clang/include/clang/Analysis/Analyses/FormatString.h
192 @@ -158,6 +158,11 @@ class ConversionSpecifier {
194 ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
196 + // FreeBSD specific specifiers
201 // GlibC specific specifiers.
204 Index: tools/clang/include/clang/Driver/Options.td
205 ===================================================================
206 --- tools/clang/include/clang/Driver/Options.td
207 +++ tools/clang/include/clang/Driver/Options.td
208 @@ -530,6 +530,8 @@ def fno_rewrite_includes : Flag<["-"], "fno-rewrit
210 def ffreestanding : Flag<["-"], "ffreestanding">, Group<f_Group>, Flags<[CC1Option]>,
211 HelpText<"Assert that the compilation takes place in a freestanding environment">;
212 +def fformat_extensions: Flag<["-"], "fformat-extensions">, Group<f_Group>, Flags<[CC1Option]>,
213 + HelpText<"Enable FreeBSD kernel specific format string extensions">;
214 def fgnu_keywords : Flag<["-"], "fgnu-keywords">, Group<f_Group>, Flags<[CC1Option]>,
215 HelpText<"Allow GNU-extension keywords regardless of language standard">;
216 def fgnu89_inline : Flag<["-"], "fgnu89-inline">, Group<f_Group>, Flags<[CC1Option]>,