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/Sema/SemaChecking.cpp | |
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/Sema/SemaChecking.cpp')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index b9af98da132..16b96615c96 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2680,6 +2680,7 @@ Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) { .Case("strftime", FST_Strftime) .Case("strfmon", FST_Strfmon) .Cases("kprintf", "cmn_err", "vcmn_err", "zcmn_err", FST_Kprintf) + .Case("freebsd_kprintf", FST_FreeBSDKPrintf) .Default(FST_Unknown); } @@ -3461,6 +3462,43 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier CoveredArgs.set(argIndex); } + // FreeBSD kernel extensions. + if (CS.getKind() == ConversionSpecifier::FreeBSDbArg || + CS.getKind() == ConversionSpecifier::FreeBSDDArg) { + // We need at least two arguments. + if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex + 1)) + return false; + + // Claim the second argument. + CoveredArgs.set(argIndex + 1); + + // Type check the first argument (int for %b, pointer for %D) + const Expr *Ex = getDataArg(argIndex); + const analyze_printf::ArgType &AT = + (CS.getKind() == ConversionSpecifier::FreeBSDbArg) ? + ArgType(S.Context.IntTy) : ArgType::CPointerTy; + if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType())) + EmitFormatDiagnostic( + S.PDiag(diag::warn_format_conversion_argument_type_mismatch) + << AT.getRepresentativeTypeName(S.Context) << Ex->getType() + << false << Ex->getSourceRange(), + Ex->getLocStart(), /*IsStringLocation*/false, + getSpecifierRange(startSpecifier, specifierLen)); + + // Type check the second argument (char * for both %b and %D) + Ex = getDataArg(argIndex + 1); + const analyze_printf::ArgType &AT2 = ArgType::CStrTy; + if (AT2.isValid() && !AT2.matchesType(S.Context, Ex->getType())) + EmitFormatDiagnostic( + S.PDiag(diag::warn_format_conversion_argument_type_mismatch) + << AT2.getRepresentativeTypeName(S.Context) << Ex->getType() + << false << Ex->getSourceRange(), + Ex->getLocStart(), /*IsStringLocation*/false, + getSpecifierRange(startSpecifier, specifierLen)); + + return true; + } + // Check for using an Objective-C specific conversion specifier // in a non-ObjC literal. if (!ObjCContext && CS.isObjCArg()) { @@ -4084,7 +4122,8 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, return; } - if (Type == FST_Printf || Type == FST_NSString) { + if (Type == FST_Printf || Type == FST_NSString || + Type == FST_FreeBSDKPrintf) { CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs, (Type == FST_NSString), Str, HasVAListArg, Args, format_idx, @@ -4092,7 +4131,8 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen, getLangOpts(), - Context.getTargetInfo())) + Context.getTargetInfo(), + Type == FST_FreeBSDKPrintf)) H.DoneProcessing(); } else if (Type == FST_Scanf) { CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs, |