summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2013-08-21 21:54:46 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2013-08-21 21:54:46 +0000
commit3cba495abca1f41a17f4092c5cf3f01374271adc (patch)
tree1a5c9393d8e5f55889463147399fa953acecb622 /clang
parent3db39dc1ae6f27f10bd7bed91d40048b71c3ffc0 (diff)
downloadbcm5719-llvm-3cba495abca1f41a17f4092c5cf3f01374271adc.tar.gz
bcm5719-llvm-3cba495abca1f41a17f4092c5cf3f01374271adc.zip
Analysis: Add support for MS specific printf format specifiers
Summary: Adds support for %I, %I32 and %I64. Reviewers: hans, jordan_rose, rnk, majnemer Reviewed By: majnemer CC: cfe-commits, cdavis5x Differential Revision: http://llvm-reviews.chandlerc.com/D1456 llvm-svn: 188937
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Analysis/Analyses/FormatString.h6
-rw-r--r--clang/lib/Analysis/FormatString.cpp46
-rw-r--r--clang/lib/Analysis/PrintfFormatString.cpp28
-rw-r--r--clang/lib/Analysis/ScanfFormatString.cpp14
-rw-r--r--clang/test/Sema/format-strings-ms.c9
5 files changed, 96 insertions, 7 deletions
diff --git a/clang/include/clang/Analysis/Analyses/FormatString.h b/clang/include/clang/Analysis/Analyses/FormatString.h
index 6ad89aec0a3..c9516b50cae 100644
--- a/clang/include/clang/Analysis/Analyses/FormatString.h
+++ b/clang/include/clang/Analysis/Analyses/FormatString.h
@@ -73,6 +73,9 @@ public:
AsIntMax, // 'j'
AsSizeT, // 'z'
AsPtrDiff, // 't'
+ AsInt32, // 'I32' (MSVCRT, like __int32)
+ AsInt3264, // 'I' (MSVCRT, like __int3264 from MIDL)
+ AsInt64, // 'I64' (MSVCRT, like __int64)
AsLongDouble, // 'L'
AsAllocate, // for '%as', GNU extension to C90 scanf
AsMAllocate, // for '%ms', GNU extension to scanf
@@ -95,6 +98,9 @@ public:
case AsLongLong:
case AsChar:
return 2;
+ case AsInt32:
+ case AsInt64:
+ return 3;
case None:
return 0;
}
diff --git a/clang/lib/Analysis/FormatString.cpp b/clang/lib/Analysis/FormatString.cpp
index 382be24dca7..43ecc6682e3 100644
--- a/clang/lib/Analysis/FormatString.cpp
+++ b/clang/lib/Analysis/FormatString.cpp
@@ -223,6 +223,27 @@ clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
break;
}
return false;
+ // printf: AsInt64, AsInt32, AsInt3264
+ // scanf: AsInt64
+ case 'I':
+ if (I + 1 != E && I + 2 != E) {
+ if (I[1] == '6' && I[2] == '4') {
+ I += 3;
+ lmKind = LengthModifier::AsInt64;
+ break;
+ }
+ if (IsScanf)
+ return false;
+
+ if (I[1] == '3' && I[2] == '2') {
+ I += 3;
+ lmKind = LengthModifier::AsInt32;
+ break;
+ }
+ }
+ ++I;
+ lmKind = LengthModifier::AsInt3264;
+ break;
}
LengthModifier lm(lmPosition, lmKind);
FS.setLengthModifier(lm);
@@ -471,6 +492,12 @@ analyze_format_string::LengthModifier::toString() const {
return "z";
case AsPtrDiff:
return "t";
+ case AsInt32:
+ return "I32";
+ case AsInt3264:
+ return "I";
+ case AsInt64:
+ return "I64";
case AsLongDouble:
return "L";
case AsAllocate:
@@ -514,7 +541,7 @@ const char *ConversionSpecifier::toString() const {
case ScanListArg: return "[";
case InvalidSpecifier: return NULL;
- // MacOS X unicode extensions.
+ // POSIX unicode extensions.
case CArg: return "C";
case SArg: return "S";
@@ -678,6 +705,20 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const {
default:
return false;
}
+ case LengthModifier::AsInt32:
+ case LengthModifier::AsInt3264:
+ case LengthModifier::AsInt64:
+ switch (CS.getKind()) {
+ case ConversionSpecifier::dArg:
+ case ConversionSpecifier::iArg:
+ case ConversionSpecifier::oArg:
+ case ConversionSpecifier::uArg:
+ case ConversionSpecifier::xArg:
+ case ConversionSpecifier::XArg:
+ return Target.getTriple().isOSMSVCRT();
+ default:
+ return false;
+ }
}
llvm_unreachable("Invalid LengthModifier Kind!");
}
@@ -697,6 +738,9 @@ bool FormatSpecifier::hasStandardLengthModifier() const {
case LengthModifier::AsAllocate:
case LengthModifier::AsMAllocate:
case LengthModifier::AsQuad:
+ case LengthModifier::AsInt32:
+ case LengthModifier::AsInt3264:
+ case LengthModifier::AsInt64:
return false;
}
llvm_unreachable("Invalid LengthModifier Kind!");
diff --git a/clang/lib/Analysis/PrintfFormatString.cpp b/clang/lib/Analysis/PrintfFormatString.cpp
index 60f9517e7f9..cdf6122363e 100644
--- a/clang/lib/Analysis/PrintfFormatString.cpp
+++ b/clang/lib/Analysis/PrintfFormatString.cpp
@@ -187,8 +187,8 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
case 'i': k = ConversionSpecifier::iArg; break;
case 'n': k = ConversionSpecifier::nArg; break;
case 'o': k = ConversionSpecifier::oArg; break;
- case 'p': k = ConversionSpecifier::pArg; break;
- case 's': k = ConversionSpecifier::sArg; break;
+ case 'p': k = ConversionSpecifier::pArg; break;
+ case 's': k = ConversionSpecifier::sArg; break;
case 'u': k = ConversionSpecifier::uArg; break;
case 'x': k = ConversionSpecifier::xArg; break;
// POSIX specific.
@@ -278,18 +278,26 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
case LengthModifier::AsLongDouble:
// GNU extension.
return Ctx.LongLongTy;
- case LengthModifier::None: return Ctx.IntTy;
+ case LengthModifier::None:
+ return Ctx.IntTy;
+ case LengthModifier::AsInt32:
+ return ArgType(Ctx.IntTy, "__int32");
case LengthModifier::AsChar: return ArgType::AnyCharTy;
case LengthModifier::AsShort: return Ctx.ShortTy;
case LengthModifier::AsLong: return Ctx.LongTy;
case LengthModifier::AsLongLong:
case LengthModifier::AsQuad:
return Ctx.LongLongTy;
+ case LengthModifier::AsInt64:
+ return ArgType(Ctx.LongLongTy, "__int64");
case LengthModifier::AsIntMax:
return ArgType(Ctx.getIntMaxType(), "intmax_t");
case LengthModifier::AsSizeT:
// FIXME: How to get the corresponding signed version of size_t?
return ArgType();
+ case LengthModifier::AsInt3264:
+ return Ctx.getTargetInfo().getTriple().isArch64Bit() ? Ctx.LongLongTy
+ : Ctx.IntTy;
case LengthModifier::AsPtrDiff:
return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t");
case LengthModifier::AsAllocate:
@@ -302,17 +310,26 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
case LengthModifier::AsLongDouble:
// GNU extension.
return Ctx.UnsignedLongLongTy;
- case LengthModifier::None: return Ctx.UnsignedIntTy;
+ case LengthModifier::None:
+ return Ctx.UnsignedIntTy;
+ case LengthModifier::AsInt32:
+ return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
case LengthModifier::AsLongLong:
case LengthModifier::AsQuad:
return Ctx.UnsignedLongLongTy;
+ case LengthModifier::AsInt64:
+ return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
case LengthModifier::AsIntMax:
return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
case LengthModifier::AsSizeT:
return ArgType(Ctx.getSizeType(), "size_t");
+ case LengthModifier::AsInt3264:
+ return Ctx.getTargetInfo().getTriple().isArch64Bit()
+ ? Ctx.UnsignedLongLongTy
+ : Ctx.UnsignedIntTy;
case LengthModifier::AsPtrDiff:
// FIXME: How to get the corresponding unsigned
// version of ptrdiff_t?
@@ -351,6 +368,9 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
return ArgType(); // FIXME: Is this a known extension?
case LengthModifier::AsAllocate:
case LengthModifier::AsMAllocate:
+ case LengthModifier::AsInt32:
+ case LengthModifier::AsInt3264:
+ case LengthModifier::AsInt64:
return ArgType::Invalid();
}
}
diff --git a/clang/lib/Analysis/ScanfFormatString.cpp b/clang/lib/Analysis/ScanfFormatString.cpp
index 676b68f391c..f5ce84fe361 100644
--- a/clang/lib/Analysis/ScanfFormatString.cpp
+++ b/clang/lib/Analysis/ScanfFormatString.cpp
@@ -232,6 +232,8 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
case LengthModifier::AsLongLong:
case LengthModifier::AsQuad:
return ArgType::PtrTo(Ctx.LongLongTy);
+ case LengthModifier::AsInt64:
+ return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
case LengthModifier::AsIntMax:
return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
case LengthModifier::AsSizeT:
@@ -243,8 +245,9 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
// GNU extension.
return ArgType::PtrTo(Ctx.LongLongTy);
case LengthModifier::AsAllocate:
- return ArgType::Invalid();
case LengthModifier::AsMAllocate:
+ case LengthModifier::AsInt32:
+ case LengthModifier::AsInt3264:
return ArgType::Invalid();
}
@@ -267,6 +270,8 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
case LengthModifier::AsLongLong:
case LengthModifier::AsQuad:
return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
+ case LengthModifier::AsInt64:
+ return ArgType::PtrTo(ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"));
case LengthModifier::AsIntMax:
return ArgType::PtrTo(ArgType(Ctx.getUIntMaxType(), "uintmax_t"));
case LengthModifier::AsSizeT:
@@ -278,8 +283,9 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
// GNU extension.
return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
case LengthModifier::AsAllocate:
- return ArgType::Invalid();
case LengthModifier::AsMAllocate:
+ case LengthModifier::AsInt32:
+ case LengthModifier::AsInt3264:
return ArgType::Invalid();
}
@@ -349,6 +355,8 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
case LengthModifier::AsLongLong:
case LengthModifier::AsQuad:
return ArgType::PtrTo(Ctx.LongLongTy);
+ case LengthModifier::AsInt64:
+ return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
case LengthModifier::AsIntMax:
return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
case LengthModifier::AsSizeT:
@@ -359,6 +367,8 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
return ArgType(); // FIXME: Is this a known extension?
case LengthModifier::AsAllocate:
case LengthModifier::AsMAllocate:
+ case LengthModifier::AsInt32:
+ case LengthModifier::AsInt3264:
return ArgType::Invalid();
}
diff --git a/clang/test/Sema/format-strings-ms.c b/clang/test/Sema/format-strings-ms.c
new file mode 100644
index 00000000000..cc574a7a986
--- /dev/null
+++ b/clang/test/Sema/format-strings-ms.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-compatibility -triple=i386-pc-win32 -pedantic %s
+
+int printf(const char *format, ...) __attribute__((format(printf, 1, 2)));
+
+void test() {
+ short val = 30;
+ printf("val = %I64d\n", val); // expected-warning{{'I64' length modifier is not supported by ISO C}} \
+ // expected-warning{{format specifies type '__int64' (aka 'long long') but the argument has type 'short'}}
+}
OpenPOWER on IntegriCloud