aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/FormatString.cpp
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2011-12-15 10:25:47 +0000
committerHans Wennborg <hans@hanshq.net>2011-12-15 10:25:47 +0000
commitd02deebce5f1b283101e035a7f5d5bab0d2068ec (patch)
tree58459abff0fef9bd9fe64d4188a7c702b6e06cdf /lib/Analysis/FormatString.cpp
parentdb7a800e0b76036d0faa7123f2e05e45ee3294e5 (diff)
Support the 'a' length modifier in scanf format strings as a C90
extension. This fixes gcc.dg/format/c90-scanf-3.c and ext-4.c (test for excess errors). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146649 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/FormatString.cpp')
-rw-r--r--lib/Analysis/FormatString.cpp29
1 files changed, 28 insertions, 1 deletions
diff --git a/lib/Analysis/FormatString.cpp b/lib/Analysis/FormatString.cpp
index 2d56c233b6..bbc6f07b36 100644
--- a/lib/Analysis/FormatString.cpp
+++ b/lib/Analysis/FormatString.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "FormatStringParsing.h"
+#include "clang/Basic/LangOptions.h"
using clang::analyze_format_string::ArgTypeResult;
using clang::analyze_format_string::FormatStringHandler;
@@ -175,7 +176,9 @@ clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H,
bool
clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
const char *&I,
- const char *E) {
+ const char *E,
+ const LangOptions &LO,
+ bool IsScanf) {
LengthModifier::Kind lmKind = LengthModifier::None;
const char *lmPosition = I;
switch (*I) {
@@ -196,6 +199,19 @@ clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break;
case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break;
case 'q': lmKind = LengthModifier::AsLongLong; ++I; break;
+ case 'a':
+ if (IsScanf && !LO.C99 && !LO.CPlusPlus) {
+ // For scanf in C90, look at the next character to see if this should
+ // be parsed as the GNU extension 'a' length modifier. If not, this
+ // will be parsed as a conversion specifier.
+ ++I;
+ if (I != E && (*I == 's' || *I == 'S' || *I == '[')) {
+ lmKind = LengthModifier::AsAllocate;
+ break;
+ }
+ --I;
+ }
+ return false;
}
LengthModifier lm(lmPosition, lmKind);
FS.setLengthModifier(lm);
@@ -391,6 +407,8 @@ analyze_format_string::LengthModifier::toString() const {
return "t";
case AsLongDouble:
return "L";
+ case AsAllocate:
+ return "a";
case None:
return "";
}
@@ -527,6 +545,15 @@ bool FormatSpecifier::hasValidLengthModifier() const {
default:
return false;
}
+
+ case LengthModifier::AsAllocate:
+ switch (CS.getKind()) {
+ case ConversionSpecifier::sArg:
+ case ConversionSpecifier::SArg:
+ return true;
+ default:
+ return false;
+ }
}
return false;
}