aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Analysis/PrintfFormatString.cpp
diff options
context:
space:
mode:
authorMehdi Amini <mehdi.amini@apple.com>2016-10-24 20:39:34 +0000
committerMehdi Amini <mehdi.amini@apple.com>2016-10-24 20:39:34 +0000
commit06d367c6c6851b272f56f4e6af63da1f71ceb0d3 (patch)
treef00dac755362c7010b9676aa676efae25c44b905 /clang/lib/Analysis/PrintfFormatString.cpp
parent06ca6ea6c38f5ec8dcc3ec010176d61f992ae15c (diff)
downloadllvm-06d367c6c6851b272f56f4e6af63da1f71ceb0d3.zip
llvm-06d367c6c6851b272f56f4e6af63da1f71ceb0d3.tar.gz
llvm-06d367c6c6851b272f56f4e6af63da1f71ceb0d3.tar.bz2
Add support for __builtin_os_log_format[_buffer_size]
This reverts commit r285007 and reapply r284990, with a fix for the opencl test that I broke. Original commit message follows: These new builtins support a mechanism for logging OS events, using a printf-like format string to specify the layout of data in a buffer. The _buffer_size version of the builtin can be used to determine the size of the buffer to allocate to hold the data, and then __builtin_os_log_format can write data into that buffer. This implements format checking to report mismatches between the format string and the data arguments. Most of this code was written by Chris Willmore. Differential Revision: https://reviews.llvm.org/D25888 llvm-svn: 285019
Diffstat (limited to 'clang/lib/Analysis/PrintfFormatString.cpp')
-rw-r--r--clang/lib/Analysis/PrintfFormatString.cpp43
1 files changed, 41 insertions, 2 deletions
diff --git a/clang/lib/Analysis/PrintfFormatString.cpp b/clang/lib/Analysis/PrintfFormatString.cpp
index ac6cef9..ed7193e 100644
--- a/clang/lib/Analysis/PrintfFormatString.cpp
+++ b/clang/lib/Analysis/PrintfFormatString.cpp
@@ -119,6 +119,39 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
return true;
}
+ const char *OSLogVisibilityFlagsStart = nullptr,
+ *OSLogVisibilityFlagsEnd = nullptr;
+ if (*I == '{') {
+ OSLogVisibilityFlagsStart = I++;
+ // Find the end of the modifier.
+ while (I != E && *I != '}') {
+ I++;
+ }
+ if (I == E) {
+ if (Warn)
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+ assert(*I == '}');
+ OSLogVisibilityFlagsEnd = I++;
+
+ // Just see if 'private' or 'public' is the first word. os_log itself will
+ // do any further parsing.
+ const char *P = OSLogVisibilityFlagsStart + 1;
+ while (P < OSLogVisibilityFlagsEnd && isspace(*P))
+ P++;
+ const char *WordStart = P;
+ while (P < OSLogVisibilityFlagsEnd && (isalnum(*P) || *P == '_'))
+ P++;
+ const char *WordEnd = P;
+ StringRef Word(WordStart, WordEnd - WordStart);
+ if (Word == "private") {
+ FS.setIsPrivate(WordStart);
+ } else if (Word == "public") {
+ FS.setIsPublic(WordStart);
+ }
+ }
+
// Look for flags (if any).
bool hasMore = true;
for ( ; I != E; ++I) {
@@ -253,6 +286,10 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
// POSIX specific.
case 'C': k = ConversionSpecifier::CArg; break;
case 'S': k = ConversionSpecifier::SArg; break;
+ // Apple extension for os_log
+ case 'P':
+ k = ConversionSpecifier::PArg;
+ break;
// Objective-C.
case '@': k = ConversionSpecifier::ObjCObjArg; break;
// Glibc specific.
@@ -301,7 +338,7 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
conversionPosition);
return true;
}
-
+
PrintfConversionSpecifier CS(conversionPosition, k);
FS.setConversionSpecifier(CS);
if (CS.consumesDataArgument() && !FS.usesPositionalArg())
@@ -541,6 +578,7 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
return Ctx.IntTy;
return ArgType(Ctx.WideCharTy, "wchar_t");
case ConversionSpecifier::pArg:
+ case ConversionSpecifier::PArg:
return ArgType::CPointerTy;
case ConversionSpecifier::ObjCObjArg:
return ArgType::ObjCPointerTy;
@@ -900,7 +938,7 @@ bool PrintfSpecifier::hasValidPrecision() const {
if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
return true;
- // Precision is only valid with the diouxXaAeEfFgGs conversions
+ // Precision is only valid with the diouxXaAeEfFgGsP conversions
switch (CS.getKind()) {
case ConversionSpecifier::dArg:
case ConversionSpecifier::DArg:
@@ -922,6 +960,7 @@ bool PrintfSpecifier::hasValidPrecision() const {
case ConversionSpecifier::sArg:
case ConversionSpecifier::FreeBSDrArg:
case ConversionSpecifier::FreeBSDyArg:
+ case ConversionSpecifier::PArg:
return true;
default: