diff options
author | Dimitry Andric <dimitry@andric.com> | 2015-02-19 22:32:33 +0000 |
---|---|---|
committer | Dimitry Andric <dimitry@andric.com> | 2015-02-19 22:32:33 +0000 |
commit | 6b5ed34a406451f33b60cdd52c3d5df6e0afab0c (patch) | |
tree | ee650a02344f07d3a83c14f48d31605317918776 /clang/lib/Analysis | |
parent | f567e1aab7b06756e6938430808981c3875c2e14 (diff) | |
download | bcm5719-llvm-6b5ed34a406451f33b60cdd52c3d5df6e0afab0c.tar.gz bcm5719-llvm-6b5ed34a406451f33b60cdd52c3d5df6e0afab0c.zip |
Add support for analyzing FreeBSD kernel printf extensions.
This adds a new __freebsd_kprintf__ format string type, which enables
checking when used in __attribute__((format(...))) attributes. It can
check the FreeBSD kernel specific %b, %D, %r and %y specifiers, using
existing diagnostic messages. Also adds test cases for all these
specifiers.
Differential Revision: http://reviews.llvm.org/D7154
llvm-svn: 229921
Diffstat (limited to 'clang/lib/Analysis')
-rw-r--r-- | clang/lib/Analysis/FormatString.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Analysis/PrintfFormatString.cpp | 43 |
2 files changed, 54 insertions, 5 deletions
diff --git a/clang/lib/Analysis/FormatString.cpp b/clang/lib/Analysis/FormatString.cpp index 8c663d856f6..662166ccaac 100644 --- a/clang/lib/Analysis/FormatString.cpp +++ b/clang/lib/Analysis/FormatString.cpp @@ -552,6 +552,12 @@ const char *ConversionSpecifier::toString() const { // Objective-C specific specifiers. case ObjCObjArg: return "@"; + // FreeBSD kernel specific specifiers. + case FreeBSDbArg: return "b"; + case FreeBSDDArg: return "D"; + case FreeBSDrArg: return "r"; + case FreeBSDyArg: return "y"; + // GlibC specific specifiers. case PrintErrno: return "m"; @@ -647,6 +653,9 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const { case ConversionSpecifier::XArg: case ConversionSpecifier::nArg: return true; + case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::FreeBSDyArg: + return Target.getTriple().isOSFreeBSD(); default: return false; } @@ -677,6 +686,9 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const { case ConversionSpecifier::ScanListArg: case ConversionSpecifier::ZArg: return true; + case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::FreeBSDyArg: + return Target.getTriple().isOSFreeBSD(); default: return false; } @@ -807,6 +819,10 @@ bool FormatSpecifier::hasStandardConversionSpecifier(const LangOptions &LangOpt) case ConversionSpecifier::SArg: return LangOpt.ObjC1 || LangOpt.ObjC2; case ConversionSpecifier::InvalidSpecifier: + case ConversionSpecifier::FreeBSDbArg: + case ConversionSpecifier::FreeBSDDArg: + case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::FreeBSDyArg: case ConversionSpecifier::PrintErrno: case ConversionSpecifier::DArg: case ConversionSpecifier::OArg: diff --git a/clang/lib/Analysis/PrintfFormatString.cpp b/clang/lib/Analysis/PrintfFormatString.cpp index 146635b8870..b8d3ec18016 100644 --- a/clang/lib/Analysis/PrintfFormatString.cpp +++ b/clang/lib/Analysis/PrintfFormatString.cpp @@ -55,7 +55,8 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, unsigned &argIndex, const LangOptions &LO, const TargetInfo &Target, - bool Warn) { + bool Warn, + bool isFreeBSDKPrintf) { using namespace clang::analyze_format_string; using namespace clang::analyze_printf; @@ -206,9 +207,24 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, case '@': k = ConversionSpecifier::ObjCObjArg; break; // Glibc specific. case 'm': k = ConversionSpecifier::PrintErrno; break; + // FreeBSD kernel specific. + case 'b': + if (isFreeBSDKPrintf) + k = ConversionSpecifier::FreeBSDbArg; // int followed by char * + break; + case 'r': + if (isFreeBSDKPrintf) + k = ConversionSpecifier::FreeBSDrArg; // int + break; + case 'y': + if (isFreeBSDKPrintf) + k = ConversionSpecifier::FreeBSDyArg; // int + break; // Apple-specific. case 'D': - if (Target.getTriple().isOSDarwin()) + if (isFreeBSDKPrintf) + k = ConversionSpecifier::FreeBSDDArg; // void * followed by char * + else if (Target.getTriple().isOSDarwin()) k = ConversionSpecifier::DArg; break; case 'O': @@ -228,6 +244,10 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, FS.setConversionSpecifier(CS); if (CS.consumesDataArgument() && !FS.usesPositionalArg()) FS.setArgIndex(argIndex++); + // FreeBSD kernel specific. + if (k == ConversionSpecifier::FreeBSDbArg || + k == ConversionSpecifier::FreeBSDDArg) + argIndex++; if (k == ConversionSpecifier::InvalidSpecifier) { // Assume the conversion takes one argument. @@ -240,14 +260,16 @@ bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H, const char *I, const char *E, const LangOptions &LO, - const TargetInfo &Target) { + const TargetInfo &Target, + bool isFreeBSDKPrintf) { unsigned argIndex = 0; // Keep looking for a format specifier until we have exhausted the string. while (I != E) { const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex, - LO, Target, true); + LO, Target, true, + isFreeBSDKPrintf); // Did a fail-stop error of any kind occur when parsing the specifier? // If so, don't do any more processing. if (FSR.shouldStop()) @@ -276,7 +298,8 @@ bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I, FormatStringHandler H; while (I != E) { const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex, - LO, Target, false); + LO, Target, false, + false); // Did a fail-stop error of any kind occur when parsing the specifier? // If so, don't do any more processing. if (FSR.shouldStop()) @@ -674,6 +697,8 @@ bool PrintfSpecifier::hasValidPlusPrefix() const { case ConversionSpecifier::GArg: case ConversionSpecifier::aArg: case ConversionSpecifier::AArg: + case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::FreeBSDyArg: return true; default: @@ -699,6 +724,8 @@ bool PrintfSpecifier::hasValidAlternativeForm() const { case ConversionSpecifier::FArg: case ConversionSpecifier::gArg: case ConversionSpecifier::GArg: + case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::FreeBSDyArg: return true; default: @@ -729,6 +756,8 @@ bool PrintfSpecifier::hasValidLeadingZeros() const { case ConversionSpecifier::FArg: case ConversionSpecifier::gArg: case ConversionSpecifier::GArg: + case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::FreeBSDyArg: return true; default: @@ -753,6 +782,8 @@ bool PrintfSpecifier::hasValidSpacePrefix() const { case ConversionSpecifier::GArg: case ConversionSpecifier::aArg: case ConversionSpecifier::AArg: + case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::FreeBSDyArg: return true; default: @@ -818,6 +849,8 @@ bool PrintfSpecifier::hasValidPrecision() const { case ConversionSpecifier::gArg: case ConversionSpecifier::GArg: case ConversionSpecifier::sArg: + case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::FreeBSDyArg: return true; default: |