summaryrefslogtreecommitdiffstats
path: root/clang/lib/Analysis
diff options
context:
space:
mode:
authorDimitry Andric <dimitry@andric.com>2015-02-19 22:32:33 +0000
committerDimitry Andric <dimitry@andric.com>2015-02-19 22:32:33 +0000
commit6b5ed34a406451f33b60cdd52c3d5df6e0afab0c (patch)
treeee650a02344f07d3a83c14f48d31605317918776 /clang/lib/Analysis
parentf567e1aab7b06756e6938430808981c3875c2e14 (diff)
downloadbcm5719-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.cpp16
-rw-r--r--clang/lib/Analysis/PrintfFormatString.cpp43
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:
OpenPOWER on IntegriCloud