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://svn.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,40 @@ CheckPrintfHandler::HandlePrintfSpecifier(const an
122 CoveredArgs.set(argIndex);
125 + // FreeBSD extensions
126 + if (CS.getKind() == ConversionSpecifier::FreeBSDbArg ||
127 + CS.getKind() == ConversionSpecifier::FreeBSDDArg) {
128 + // claim the second argument
129 + CoveredArgs.set(argIndex + 1);
131 + // Now type check the data expression that matches the
132 + // format specifier.
133 + const Expr *Ex = getDataArg(argIndex);
134 + const analyze_printf::ArgType &AT =
135 + (CS.getKind() == ConversionSpecifier::FreeBSDbArg) ?
136 + ArgType(S.Context.IntTy) : ArgType::CStrTy;
137 + if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType()))
138 + S.Diag(getLocationOfByte(CS.getStart()),
139 + diag::warn_printf_conversion_argument_type_mismatch)
140 + << AT.getRepresentativeType(S.Context) << Ex->getType()
141 + << getSpecifierRange(startSpecifier, specifierLen)
142 + << Ex->getSourceRange();
144 + // Now type check the data expression that matches the
145 + // format specifier.
146 + Ex = getDataArg(argIndex + 1);
147 + const analyze_printf::ArgType &AT2 = ArgType::CStrTy;
148 + if (AT2.isValid() && !AT2.matchesType(S.Context, Ex->getType()))
149 + S.Diag(getLocationOfByte(CS.getStart()),
150 + diag::warn_printf_conversion_argument_type_mismatch)
151 + << AT2.getRepresentativeType(S.Context) << Ex->getType()
152 + << getSpecifierRange(startSpecifier, specifierLen)
153 + << Ex->getSourceRange();
157 + // END OF FREEBSD EXTENSIONS
159 // Check for using an Objective-C specific conversion specifier
160 // in a non-ObjC literal.
161 if (!ObjCContext && CS.isObjCArg()) {
162 Index: tools/clang/lib/Driver/Tools.cpp
163 ===================================================================
164 --- tools/clang/lib/Driver/Tools.cpp
165 +++ tools/clang/lib/Driver/Tools.cpp
166 @@ -2991,6 +2991,7 @@ void Clang::ConstructJob(Compilation &C, const Job
168 // Forward -f (flag) options which we can pass directly.
169 Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
170 + Args.AddLastArg(CmdArgs, options::OPT_fformat_extensions);
171 Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
172 Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info);
173 Args.AddLastArg(CmdArgs, options::OPT_fno_limit_debug_info);
174 Index: tools/clang/include/clang/Basic/LangOptions.def
175 ===================================================================
176 --- tools/clang/include/clang/Basic/LangOptions.def
177 +++ tools/clang/include/clang/Basic/LangOptions.def
178 @@ -84,6 +84,7 @@ LANGOPT(TraditionalCPP , 1, 0, "traditional CPP
179 LANGOPT(RTTI , 1, 1, "run-time type information")
180 LANGOPT(MSBitfields , 1, 0, "Microsoft-compatible structure layout")
181 LANGOPT(Freestanding, 1, 0, "freestanding implementation")
182 +LANGOPT(FormatExtensions , 1, 0, "FreeBSD format extensions")
183 LANGOPT(NoBuiltin , 1, 0, "disable builtin functions")
184 LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions")
186 Index: tools/clang/include/clang/Analysis/Analyses/FormatString.h
187 ===================================================================
188 --- tools/clang/include/clang/Analysis/Analyses/FormatString.h
189 +++ tools/clang/include/clang/Analysis/Analyses/FormatString.h
190 @@ -158,6 +158,11 @@ class ConversionSpecifier {
192 ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
194 + // FreeBSD specific specifiers
199 // GlibC specific specifiers.
202 Index: tools/clang/include/clang/Driver/Options.td
203 ===================================================================
204 --- tools/clang/include/clang/Driver/Options.td
205 +++ tools/clang/include/clang/Driver/Options.td
206 @@ -530,6 +530,8 @@ def fno_rewrite_includes : Flag<["-"], "fno-rewrit
208 def ffreestanding : Flag<["-"], "ffreestanding">, Group<f_Group>, Flags<[CC1Option]>,
209 HelpText<"Assert that the compilation takes place in a freestanding environment">;
210 +def fformat_extensions: Flag<["-"], "fformat-extensions">, Group<f_Group>, Flags<[CC1Option]>,
211 + HelpText<"Enable FreeBSD kernel specific format string extensions">;
212 def fgnu_keywords : Flag<["-"], "fgnu-keywords">, Group<f_Group>, Flags<[CC1Option]>,
213 HelpText<"Allow GNU-extension keywords regardless of language standard">;
214 def fgnu89_inline : Flag<["-"], "fgnu89-inline">, Group<f_Group>, Flags<[CC1Option]>,