summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2010-06-10 16:13:32 +0000
committerrdivacky <rdivacky@FreeBSD.org>2010-06-10 16:13:32 +0000
commit970bcaaade62f997fe73cc23cab599c5b941ce93 (patch)
tree76a7a5a5050a10cbf87b2fd97e3018f723a711a7 /contrib/llvm/tools/clang/lib
parentfb808063cd6ca3766528a3fd83fb51fb7070200d (diff)
downloadFreeBSD-src-970bcaaade62f997fe73cc23cab599c5b941ce93.zip
FreeBSD-src-970bcaaade62f997fe73cc23cab599c5b941ce93.tar.gz
Introduce -fformat-extensions. A local FreeBSD extension used
for additional printf modifiers in kernel. Approved by: ed (mentor)
Diffstat (limited to 'contrib/llvm/tools/clang/lib')
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp15
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tools.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp36
4 files changed, 51 insertions, 4 deletions
diff --git a/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp b/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp
index c38aae3..0b111e9 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp
@@ -210,7 +210,8 @@ static bool ParseArgPosition(FormatStringHandler &H,
static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H,
const char *&Beg,
const char *E,
- unsigned &argIndex) {
+ unsigned &argIndex,
+ bool FormatExtensions) {
using namespace clang::analyze_printf;
@@ -369,11 +370,19 @@ static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H,
case '@': k = ConversionSpecifier::ObjCObjArg; break;
// Glibc specific.
case 'm': k = ConversionSpecifier::PrintErrno; break;
+ // FreeBSD format extensions
+ case 'b': if (FormatExtensions) k = ConversionSpecifier::bArg; break; /* check for int and then char * */
+ case 'r': if (FormatExtensions) k = ConversionSpecifier::xArg; break;
+ case 'y': if (FormatExtensions) k = ConversionSpecifier::iArg; break;
+ case 'D': if (FormatExtensions) k = ConversionSpecifier::DArg; break; /* check for u_char * pointer and a char * string */
}
ConversionSpecifier CS(conversionPosition, k);
FS.setConversionSpecifier(CS);
if (CS.consumesDataArgument() && !FS.usesPositionalArg())
FS.setArgIndex(argIndex++);
+ // FreeBSD extension
+ if (k == ConversionSpecifier::bArg || k == ConversionSpecifier::DArg)
+ argIndex++;
if (k == ConversionSpecifier::InvalidSpecifier) {
// Assume the conversion takes one argument.
@@ -383,13 +392,13 @@ static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H,
}
bool clang::analyze_printf::ParseFormatString(FormatStringHandler &H,
- const char *I, const char *E) {
+ const char *I, const char *E, bool FormatExtensions) {
unsigned argIndex = 0;
// Keep looking for a format specifier until we have exhausted the string.
while (I != E) {
- const FormatSpecifierResult &FSR = ParseFormatSpecifier(H, I, E, argIndex);
+ const FormatSpecifierResult &FSR = ParseFormatSpecifier(H, I, E, argIndex, FormatExtensions);
// Did a fail-stop error of any kind occur when parsing the specifier?
// If so, don't do any more processing.
if (FSR.shouldStop())
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
index 8391d96..ce35552 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
@@ -1156,6 +1156,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fcatch_undefined_behavior);
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
+ Args.AddLastArg(CmdArgs, options::OPT_fformat_extensions);
// -flax-vector-conversions is default.
if (!Args.hasFlag(options::OPT_flax_vector_conversions,
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
index 1d81e82..ff372e1 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
@@ -530,6 +530,8 @@ static void LangOptsToArgs(const LangOptions &Opts,
Res.push_back("-fgnu-runtime");
if (Opts.Freestanding)
Res.push_back("-ffreestanding");
+ if (Opts.FormatExtensions)
+ Res.push_back("-fformat-extensions");
if (Opts.NoBuiltin)
Res.push_back("-fno-builtin");
if (!Opts.AssumeSaneOperatorNew)
@@ -1245,6 +1247,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char);
Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar);
Opts.Freestanding = Args.hasArg(OPT_ffreestanding);
+ Opts.FormatExtensions = Args.hasArg(OPT_fformat_extensions);
Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
index 4f3f41b..6fc36c2 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
@@ -1276,6 +1276,39 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier
CoveredArgs.set(argIndex);
}
+ // FreeBSD extensions
+ if (CS.getKind() == ConversionSpecifier::bArg || CS.getKind() == ConversionSpecifier::DArg) {
+ // claim the second argument
+ CoveredArgs.set(argIndex + 1);
+
+ // Now type check the data expression that matches the
+ // format specifier.
+ const Expr *Ex = getDataArg(argIndex);
+ QualType type = (CS.getKind() == ConversionSpecifier::bArg) ? S.Context.IntTy : S.Context.getPointerType(S.Context.UnsignedCharTy);
+ //const analyze_printf::ArgTypeResult &ATR = S.Context.IntTy;
+ const analyze_printf::ArgTypeResult &ATR = type;
+ if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType()))
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_printf_conversion_argument_type_mismatch)
+ << ATR.getRepresentativeType(S.Context) << Ex->getType()
+ << getFormatSpecifierRange(startSpecifier, specifierLen)
+ << Ex->getSourceRange();
+
+ // Now type check the data expression that matches the
+ // format specifier.
+ Ex = getDataArg(argIndex + 1);
+ const analyze_printf::ArgTypeResult &ATR2 = ArgTypeResult::CStrTy;
+ if (ATR2.isValid() && !ATR2.matchesType(S.Context, Ex->getType()))
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_printf_conversion_argument_type_mismatch)
+ << ATR2.getRepresentativeType(S.Context) << Ex->getType()
+ << getFormatSpecifierRange(startSpecifier, specifierLen)
+ << Ex->getSourceRange();
+
+ return true;
+ }
+ // END OF FREEBSD EXTENSIONS
+
// Check for using an Objective-C specific conversion specifier
// in a non-ObjC literal.
if (!IsObjCLiteral && CS.isObjCArg()) {
@@ -1400,7 +1433,8 @@ void Sema::CheckPrintfString(const StringLiteral *FExpr,
isa<ObjCStringLiteral>(OrigFormatExpr), Str,
HasVAListArg, TheCall, format_idx);
- if (!analyze_printf::ParseFormatString(H, Str, Str + StrLen))
+ bool FormatExtensions = getLangOptions().FormatExtensions;
+ if (!analyze_printf::ParseFormatString(H, Str, Str + StrLen, FormatExtensions))
H.DoneProcessing();
}
OpenPOWER on IntegriCloud