diff options
author | Hans Wennborg <hans@hanshq.net> | 2011-12-15 10:25:47 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2011-12-15 10:25:47 +0000 |
commit | d02deebce5f1b283101e035a7f5d5bab0d2068ec (patch) | |
tree | 58459abff0fef9bd9fe64d4188a7c702b6e06cdf /lib/Analysis/FormatString.cpp | |
parent | db7a800e0b76036d0faa7123f2e05e45ee3294e5 (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.cpp | 29 |
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; } |