patch-r208987-format-extensions.diff revision 269012
1This patch adds support for the FreeBSD-specific -fformat-extension option, 2which enables additional printf modifiers for the kernel. 3 4Introduced here: http://svnweb.freebsd.org/changeset/base/208987 5 6Index: 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); 18Index: 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 "@"; 25 26+ // FreeBSD specific specifiers. 27+ case FreeBSDbArg: return "b"; 28+ case FreeBSDDArg: return "D"; 29+ case FreeBSDrArg: return "r"; 30+ 31 // GlibC specific specifiers. 32 case PrintErrno: return "m"; 33 } 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: 39 return true; 40 default: 41 return false; 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: 48 return true; 49 default: 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: 60Index: 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; 66 // Glibc specific. 67 case 'm': k = ConversionSpecifier::PrintErrno; break; 68+ // FreeBSD format extensions 69+ case 'b': 70+ if (LO.FormatExtensions) 71+ k = ConversionSpecifier::FreeBSDbArg; // int followed by char * 72+ break; 73+ case 'r': 74+ if (LO.FormatExtensions) 75+ k = ConversionSpecifier::FreeBSDrArg; 76+ break; 77+ case 'y': 78+ if (LO.FormatExtensions) 79+ k = ConversionSpecifier::iArg; 80+ break; 81 // Apple-specific 82 case 'D': 83 if (Target.getTriple().isOSDarwin()) 84 k = ConversionSpecifier::DArg; 85+ else if (LO.FormatExtensions) 86+ k = ConversionSpecifier::FreeBSDDArg; // u_char * followed by char * 87 break; 88 case 'O': 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) 97+ argIndex++; 98 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: 106 return true; 107 108 default: 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: 114 return true; 115 116 default: 117Index: 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); 123 } 124 125+ // FreeBSD extensions 126+ if (CS.getKind() == ConversionSpecifier::FreeBSDbArg || 127+ CS.getKind() == ConversionSpecifier::FreeBSDDArg) { 128+ // claim the second argument 129+ CoveredArgs.set(argIndex + 1); 130+ 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(); 143+ 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(); 154+ 155+ return true; 156+ } 157+ // END OF FREEBSD EXTENSIONS 158+ 159 // Check for using an Objective-C specific conversion specifier 160 // in a non-ObjC literal. 161 if (!ObjCContext && CS.isObjCArg()) { 162Index: 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 167 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); 174Index: 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") 185 186Index: 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 { 191 ObjCObjArg, // '@' 192 ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg, 193 194+ // FreeBSD specific specifiers 195+ FreeBSDbArg, 196+ FreeBSDDArg, 197+ FreeBSDrArg, 198+ 199 // GlibC specific specifiers. 200 PrintErrno, // 'm' 201 202Index: 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 207 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]>, 215