]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/patches/patch-01-freebsd-kprintf.diff
Update compiler-rt to trunk r228651. This enables using Address
[FreeBSD/FreeBSD.git] / contrib / llvm / patches / patch-01-freebsd-kprintf.diff
1 This patch adds support for the FreeBSD kernel specific printf format
2 specifiers: %b, %D, %r and %y, via a new __freebsd_kprintf__ format
3 string type.
4
5 Sent upstream as http://reviews.llvm.org/D7154
6
7 Index: tools/clang/include/clang/Analysis/Analyses/FormatString.h
8 ===================================================================
9 --- tools/clang/include/clang/Analysis/Analyses/FormatString.h
10 +++ tools/clang/include/clang/Analysis/Analyses/FormatString.h
11 @@ -161,6 +161,12 @@ class ConversionSpecifier {
12      ObjCObjArg,  // '@'
13      ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
14  
15 +    // FreeBSD kernel specific specifiers.
16 +    FreeBSDbArg,
17 +    FreeBSDDArg,
18 +    FreeBSDrArg,
19 +    FreeBSDyArg,
20 +
21      // GlibC specific specifiers.
22      PrintErrno,   // 'm'
23  
24 @@ -204,7 +210,8 @@ class ConversionSpecifier {
25      return EndScanList ? EndScanList - Position : 1;
26    }
27  
28 -  bool isIntArg() const { return kind >= IntArgBeg && kind <= IntArgEnd; }
29 +  bool isIntArg() const { return (kind >= IntArgBeg && kind <= IntArgEnd) ||
30 +    kind == FreeBSDrArg || kind == FreeBSDyArg; }
31    bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }
32    bool isAnyIntArg() const { return kind >= IntArgBeg && kind <= UIntArgEnd; }
33    const char *toString() const;
34 @@ -646,7 +653,7 @@ class FormatStringHandler {
35  
36  bool ParsePrintfString(FormatStringHandler &H,
37                         const char *beg, const char *end, const LangOptions &LO,
38 -                       const TargetInfo &Target);
39 +                       const TargetInfo &Target, bool isFreeBSDKPrintf);
40    
41  bool ParseFormatStringHasSArg(const char *beg, const char *end, const LangOptions &LO,
42                                const TargetInfo &Target);
43 Index: tools/clang/include/clang/Sema/Sema.h
44 ===================================================================
45 --- tools/clang/include/clang/Sema/Sema.h
46 +++ tools/clang/include/clang/Sema/Sema.h
47 @@ -8566,6 +8566,7 @@ class Sema {
48      FST_Strftime,
49      FST_Strfmon,
50      FST_Kprintf,
51 +    FST_FreeBSDKPrintf,
52      FST_Unknown
53    };
54    static FormatStringType GetFormatStringType(const FormatAttr *Format);
55 Index: tools/clang/lib/Analysis/FormatString.cpp
56 ===================================================================
57 --- tools/clang/lib/Analysis/FormatString.cpp
58 +++ tools/clang/lib/Analysis/FormatString.cpp
59 @@ -552,6 +552,12 @@ const char *ConversionSpecifier::toString() const
60    // Objective-C specific specifiers.
61    case ObjCObjArg: return "@";
62  
63 +  // FreeBSD kernel specific specifiers.
64 +  case FreeBSDbArg: return "b";
65 +  case FreeBSDDArg: return "D";
66 +  case FreeBSDrArg: return "r";
67 +  case FreeBSDyArg: return "y";
68 +
69    // GlibC specific specifiers.
70    case PrintErrno: return "m";
71  
72 @@ -647,6 +653,9 @@ bool FormatSpecifier::hasValidLengthModifier(const
73          case ConversionSpecifier::XArg:
74          case ConversionSpecifier::nArg:
75            return true;
76 +        case ConversionSpecifier::FreeBSDrArg:
77 +        case ConversionSpecifier::FreeBSDyArg:
78 +          return Target.getTriple().isOSFreeBSD();
79          default:
80            return false;
81        }
82 @@ -677,6 +686,9 @@ bool FormatSpecifier::hasValidLengthModifier(const
83          case ConversionSpecifier::ScanListArg:
84          case ConversionSpecifier::ZArg:
85            return true;
86 +        case ConversionSpecifier::FreeBSDrArg:
87 +        case ConversionSpecifier::FreeBSDyArg:
88 +          return Target.getTriple().isOSFreeBSD();
89          default:
90            return false;
91        }
92 @@ -807,6 +819,10 @@ bool FormatSpecifier::hasStandardConversionSpecifi
93      case ConversionSpecifier::SArg:
94        return LangOpt.ObjC1 || LangOpt.ObjC2;
95      case ConversionSpecifier::InvalidSpecifier:
96 +    case ConversionSpecifier::FreeBSDbArg:
97 +    case ConversionSpecifier::FreeBSDDArg:
98 +    case ConversionSpecifier::FreeBSDrArg:
99 +    case ConversionSpecifier::FreeBSDyArg:
100      case ConversionSpecifier::PrintErrno:
101      case ConversionSpecifier::DArg:
102      case ConversionSpecifier::OArg:
103 Index: tools/clang/lib/Analysis/PrintfFormatString.cpp
104 ===================================================================
105 --- tools/clang/lib/Analysis/PrintfFormatString.cpp
106 +++ tools/clang/lib/Analysis/PrintfFormatString.cpp
107 @@ -55,7 +55,8 @@ static PrintfSpecifierResult ParsePrintfSpecifier(
108                                                    unsigned &argIndex,
109                                                    const LangOptions &LO,
110                                                    const TargetInfo &Target,
111 -                                                  bool Warn) {
112 +                                                  bool Warn,
113 +                                                  bool isFreeBSDKPrintf) {
114  
115    using namespace clang::analyze_format_string;
116    using namespace clang::analyze_printf;
117 @@ -206,9 +207,24 @@ static PrintfSpecifierResult ParsePrintfSpecifier(
118      case '@': k = ConversionSpecifier::ObjCObjArg; break;
119      // Glibc specific.
120      case 'm': k = ConversionSpecifier::PrintErrno; break;
121 +    // FreeBSD kernel specific.
122 +    case 'b':
123 +      if (isFreeBSDKPrintf)
124 +        k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
125 +      break;
126 +    case 'r':
127 +      if (isFreeBSDKPrintf)
128 +        k = ConversionSpecifier::FreeBSDrArg; // int
129 +      break;
130 +    case 'y':
131 +      if (isFreeBSDKPrintf)
132 +        k = ConversionSpecifier::FreeBSDyArg; // int
133 +      break;
134      // Apple-specific.
135      case 'D':
136 -      if (Target.getTriple().isOSDarwin())
137 +      if (isFreeBSDKPrintf)
138 +        k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *
139 +      else if (Target.getTriple().isOSDarwin())
140          k = ConversionSpecifier::DArg;
141        break;
142      case 'O':
143 @@ -228,6 +244,10 @@ static PrintfSpecifierResult ParsePrintfSpecifier(
144    FS.setConversionSpecifier(CS);
145    if (CS.consumesDataArgument() && !FS.usesPositionalArg())
146      FS.setArgIndex(argIndex++);
147 +  // FreeBSD kernel specific.
148 +  if (k == ConversionSpecifier::FreeBSDbArg ||
149 +      k == ConversionSpecifier::FreeBSDDArg)
150 +    argIndex++;
151  
152    if (k == ConversionSpecifier::InvalidSpecifier) {
153      // Assume the conversion takes one argument.
154 @@ -240,7 +260,8 @@ bool clang::analyze_format_string::ParsePrintfStri
155                                                       const char *I,
156                                                       const char *E,
157                                                       const LangOptions &LO,
158 -                                                     const TargetInfo &Target) {
159 +                                                     const TargetInfo &Target,
160 +                                                     bool isFreeBSDKPrintf) {
161  
162    unsigned argIndex = 0;
163  
164 @@ -247,7 +268,8 @@ bool clang::analyze_format_string::ParsePrintfStri
165    // Keep looking for a format specifier until we have exhausted the string.
166    while (I != E) {
167      const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
168 -                                                            LO, Target, true);
169 +                                                            LO, Target, true,
170 +                                                            isFreeBSDKPrintf);
171      // Did a fail-stop error of any kind occur when parsing the specifier?
172      // If so, don't do any more processing.
173      if (FSR.shouldStop())
174 @@ -276,7 +298,8 @@ bool clang::analyze_format_string::ParseFormatStri
175    FormatStringHandler H;
176    while (I != E) {
177      const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
178 -                                                            LO, Target, false);
179 +                                                            LO, Target, false,
180 +                                                            false);
181      // Did a fail-stop error of any kind occur when parsing the specifier?
182      // If so, don't do any more processing.
183      if (FSR.shouldStop())
184 @@ -674,6 +697,8 @@ bool PrintfSpecifier::hasValidPlusPrefix() const {
185    case ConversionSpecifier::GArg:
186    case ConversionSpecifier::aArg:
187    case ConversionSpecifier::AArg:
188 +  case ConversionSpecifier::FreeBSDrArg:
189 +  case ConversionSpecifier::FreeBSDyArg:
190      return true;
191  
192    default:
193 @@ -699,6 +724,8 @@ bool PrintfSpecifier::hasValidAlternativeForm() co
194    case ConversionSpecifier::FArg:
195    case ConversionSpecifier::gArg:
196    case ConversionSpecifier::GArg:
197 +  case ConversionSpecifier::FreeBSDrArg:
198 +  case ConversionSpecifier::FreeBSDyArg:
199      return true;
200  
201    default:
202 @@ -729,6 +756,8 @@ bool PrintfSpecifier::hasValidLeadingZeros() const
203    case ConversionSpecifier::FArg:
204    case ConversionSpecifier::gArg:
205    case ConversionSpecifier::GArg:
206 +  case ConversionSpecifier::FreeBSDrArg:
207 +  case ConversionSpecifier::FreeBSDyArg:
208      return true;
209  
210    default:
211 @@ -753,6 +782,8 @@ bool PrintfSpecifier::hasValidSpacePrefix() const
212    case ConversionSpecifier::GArg:
213    case ConversionSpecifier::aArg:
214    case ConversionSpecifier::AArg:
215 +  case ConversionSpecifier::FreeBSDrArg:
216 +  case ConversionSpecifier::FreeBSDyArg:
217      return true;
218  
219    default:
220 @@ -818,6 +849,8 @@ bool PrintfSpecifier::hasValidPrecision() const {
221    case ConversionSpecifier::gArg:
222    case ConversionSpecifier::GArg:
223    case ConversionSpecifier::sArg:
224 +  case ConversionSpecifier::FreeBSDrArg:
225 +  case ConversionSpecifier::FreeBSDyArg:
226      return true;
227  
228    default:
229 Index: tools/clang/lib/Sema/SemaChecking.cpp
230 ===================================================================
231 --- tools/clang/lib/Sema/SemaChecking.cpp
232 +++ tools/clang/lib/Sema/SemaChecking.cpp
233 @@ -2584,6 +2584,7 @@ Sema::FormatStringType Sema::GetFormatStringType(c
234    .Case("strftime", FST_Strftime)
235    .Case("strfmon", FST_Strfmon)
236    .Cases("kprintf", "cmn_err", "vcmn_err", "zcmn_err", FST_Kprintf)
237 +  .Case("freebsd_kprintf", FST_FreeBSDKPrintf)
238    .Default(FST_Unknown);
239  }
240  
241 @@ -3365,6 +3366,43 @@ CheckPrintfHandler::HandlePrintfSpecifier(const an
242      CoveredArgs.set(argIndex);
243    }
244  
245 +  // FreeBSD kernel extensions.
246 +  if (CS.getKind() == ConversionSpecifier::FreeBSDbArg ||
247 +      CS.getKind() == ConversionSpecifier::FreeBSDDArg) {
248 +    // We need at least two arguments.
249 +    if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex + 1))
250 +      return false;
251 +
252 +    // Claim the second argument.
253 +    CoveredArgs.set(argIndex + 1);
254 +
255 +    // Type check the first argument (int for %b, pointer for %D)
256 +    const Expr *Ex = getDataArg(argIndex);
257 +    const analyze_printf::ArgType &AT =
258 +      (CS.getKind() == ConversionSpecifier::FreeBSDbArg) ?
259 +        ArgType(S.Context.IntTy) : ArgType::CPointerTy;
260 +    if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType()))
261 +      EmitFormatDiagnostic(
262 +        S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
263 +        << AT.getRepresentativeTypeName(S.Context) << Ex->getType()
264 +        << false << Ex->getSourceRange(),
265 +        Ex->getLocStart(), /*IsStringLocation*/false,
266 +        getSpecifierRange(startSpecifier, specifierLen));
267 +
268 +    // Type check the second argument (char * for both %b and %D)
269 +    Ex = getDataArg(argIndex + 1);
270 +    const analyze_printf::ArgType &AT2 = ArgType::CStrTy;
271 +    if (AT2.isValid() && !AT2.matchesType(S.Context, Ex->getType()))
272 +      EmitFormatDiagnostic(
273 +        S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
274 +        << AT2.getRepresentativeTypeName(S.Context) << Ex->getType()
275 +        << false << Ex->getSourceRange(),
276 +        Ex->getLocStart(), /*IsStringLocation*/false,
277 +        getSpecifierRange(startSpecifier, specifierLen));
278 +
279 +     return true;
280 +  }
281 +
282    // Check for using an Objective-C specific conversion specifier
283    // in a non-ObjC literal.
284    if (!ObjCContext && CS.isObjCArg()) {
285 @@ -3988,7 +4026,8 @@ void Sema::CheckFormatString(const StringLiteral *
286      return;
287    }
288    
289 -  if (Type == FST_Printf || Type == FST_NSString) {
290 +  if (Type == FST_Printf || Type == FST_NSString ||
291 +      Type == FST_FreeBSDKPrintf) {
292      CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg,
293                           numDataArgs, (Type == FST_NSString),
294                           Str, HasVAListArg, Args, format_idx,
295 @@ -3996,7 +4035,8 @@ void Sema::CheckFormatString(const StringLiteral *
296    
297      if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen,
298                                                    getLangOpts(),
299 -                                                  Context.getTargetInfo()))
300 +                                                  Context.getTargetInfo(),
301 +                                                  Type == FST_FreeBSDKPrintf))
302        H.DoneProcessing();
303    } else if (Type == FST_Scanf) {
304      CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs,
305 Index: tools/clang/lib/Sema/SemaDeclAttr.cpp
306 ===================================================================
307 --- tools/clang/lib/Sema/SemaDeclAttr.cpp
308 +++ tools/clang/lib/Sema/SemaDeclAttr.cpp
309 @@ -2481,6 +2481,7 @@ static FormatAttrKind getFormatAttrKind(StringRef
310      .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat)
311      .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat)
312      .Case("kprintf", SupportedFormat) // OpenBSD.
313 +    .Case("freebsd_kprintf", SupportedFormat) // FreeBSD.
314  
315      .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat)
316      .Default(InvalidFormat);
317 Index: tools/clang/test/Sema/attr-format.c
318 ===================================================================
319 --- tools/clang/test/Sema/attr-format.c
320 +++ tools/clang/test/Sema/attr-format.c
321 @@ -57,8 +57,15 @@ void callnull(void){
322    null(0,  (int*)0); // expected-warning {{incompatible pointer types}}
323  }
324  
325 +// FreeBSD kernel extensions
326 +void a3(const char *a, ...)    __attribute__((format(freebsd_kprintf, 1,2))); // no-error
327 +void b3(const char *a, ...)    __attribute__((format(freebsd_kprintf, 1,1))); // expected-error {{'format' attribute parameter 3 is out of bounds}}
328 +void c3(const char *a, ...)    __attribute__((format(freebsd_kprintf, 0,2))); // expected-error {{'format' attribute parameter 2 is out of bounds}}
329 +void d3(const char *a, int c)  __attribute__((format(freebsd_kprintf, 1,2))); // expected-error {{format attribute requires variadic function}}
330 +void e3(char *str, int c, ...) __attribute__((format(freebsd_kprintf, 2,3))); // expected-error {{format argument not a string type}}
331  
332  
333 +
334  // PR4470
335  int xx_vprintf(const char *, va_list);
336  
337 Index: tools/clang/test/Sema/format-strings-freebsd.c
338 ===================================================================
339 --- tools/clang/test/Sema/format-strings-freebsd.c
340 +++ tools/clang/test/Sema/format-strings-freebsd.c
341 @@ -0,0 +1,40 @@
342 +// RUN: %clang_cc1 -fsyntax-only -verify -triple i386-unknown-freebsd %s
343 +// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-unknown-freebsd %s
344 +
345 +// Test FreeBSD kernel printf extensions.
346 +int freebsd_kernel_printf(const char *, ...) __attribute__((__format__(__freebsd_kprintf__, 1, 2)));
347 +
348 +void check_freebsd_kernel_extensions(int i, long l, char *s)
349 +{
350 +  // %b expects an int and a char *
351 +  freebsd_kernel_printf("reg=%b\n", i, "\10\2BITTWO\1BITONE\n"); // no-warning
352 +  freebsd_kernel_printf("reg=%b\n", l, "\10\2BITTWO\1BITONE\n"); // expected-warning{{format specifies type 'int' but the argument has type 'long'}}
353 +  freebsd_kernel_printf("reg=%b\n", i, l); // expected-warning{{format specifies type 'char *' but the argument has type 'long'}}
354 +  freebsd_kernel_printf("reg=%b\n", i); // expected-warning{{more '%' conversions than data arguments}}
355 +  freebsd_kernel_printf("reg=%b\n", i, "\10\2BITTWO\1BITONE\n", l); // expected-warning{{data argument not used by format string}}
356 +
357 +  // %D expects an unsigned char * and a char *
358 +  freebsd_kernel_printf("%6D", s, ":"); // no-warning
359 +  freebsd_kernel_printf("%6D", i, ":"); // expected-warning{{format specifies type 'void *' but the argument has type 'int'}}
360 +  freebsd_kernel_printf("%6D", s, i); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
361 +  freebsd_kernel_printf("%6D", s); // expected-warning{{more '%' conversions than data arguments}}
362 +  freebsd_kernel_printf("%6D", s, ":", i); // expected-warning{{data argument not used by format string}}
363 +
364 +  freebsd_kernel_printf("%*D", 42, s, ":"); // no-warning
365 +  freebsd_kernel_printf("%*D", 42, i, ":"); // expected-warning{{format specifies type 'void *' but the argument has type 'int'}}
366 +  freebsd_kernel_printf("%*D", 42, s, i); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
367 +  freebsd_kernel_printf("%*D", 42, s); // expected-warning{{more '%' conversions than data arguments}}
368 +  freebsd_kernel_printf("%*D", 42, s, ":", i); // expected-warning{{data argument not used by format string}}
369 +
370 +  // %r expects an int
371 +  freebsd_kernel_printf("%r", i); // no-warning
372 +  freebsd_kernel_printf("%r", l); // expected-warning{{format specifies type 'int' but the argument has type 'long'}}
373 +  freebsd_kernel_printf("%lr", i); // expected-warning{{format specifies type 'long' but the argument has type 'int'}}
374 +  freebsd_kernel_printf("%lr", l); // no-warning
375 +
376 +  // %y expects an int
377 +  freebsd_kernel_printf("%y", i); // no-warning
378 +  freebsd_kernel_printf("%y", l); // expected-warning{{format specifies type 'int' but the argument has type 'long'}}
379 +  freebsd_kernel_printf("%ly", i); // expected-warning{{format specifies type 'long' but the argument has type 'int'}}
380 +  freebsd_kernel_printf("%ly", l); // no-warning
381 +}