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
diff --git a/lib/Analysis/ScanfFormatString.cpp b/lib/Analysis/ScanfFormatString.cpp
index 77d9c96..e8bd0d0 100644
--- a/lib/Analysis/ScanfFormatString.cpp
+++ b/lib/Analysis/ScanfFormatString.cpp
@@ -67,7 +67,8 @@
 static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
                                                 const char *&Beg,
                                                 const char *E,
-                                                unsigned &argIndex) {
+                                                unsigned &argIndex,
+                                                const LangOptions &LO) {
   
   using namespace clang::analyze_scanf;
   const char *I = Beg;
@@ -132,7 +133,7 @@
   }
   
   // Look for the length modifier.
-  if (ParseLengthModifier(FS, I, E) && I == E) {
+  if (ParseLengthModifier(FS, I, E, LO, /*scanf=*/true) && I == E) {
       // No more characters left?
     H.HandleIncompleteSpecifier(Start, E - Start);
     return true;
@@ -218,6 +219,7 @@
         case LengthModifier::AsPtrDiff:
           return ScanfArgTypeResult(Ctx.getPointerDiffType(), "ptrdiff_t *");
         case LengthModifier::AsLongDouble: return ScanfArgTypeResult::Invalid();
+        case LengthModifier::AsAllocate: return ScanfArgTypeResult::Invalid();
       }
 
     // Unsigned int.
@@ -240,6 +242,7 @@
           // FIXME: Unsigned version of ptrdiff_t?
           return ScanfArgTypeResult();
         case LengthModifier::AsLongDouble: return ScanfArgTypeResult::Invalid();
+        case LengthModifier::AsAllocate: return ScanfArgTypeResult::Invalid();
       }
 
     // Float.
@@ -274,7 +277,9 @@
     case ConversionSpecifier::CArg:
     case ConversionSpecifier::SArg:
       // FIXME: Mac OS X specific?
-      return ScanfArgTypeResult(ScanfArgTypeResult::WCStrTy, "wchar_t *");
+      if (LM.getKind() == LengthModifier::None)
+        return ScanfArgTypeResult(ScanfArgTypeResult::WCStrTy, "wchar_t *");
+      return ScanfArgTypeResult::Invalid();
 
     // Pointer.
     case ConversionSpecifier::pArg:
@@ -401,13 +406,15 @@
 
 bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,
                                                     const char *I,
-                                                    const char *E) {
+                                                    const char *E,
+                                                    const LangOptions &LO) {
   
   unsigned argIndex = 0;
   
   // Keep looking for a format specifier until we have exhausted the string.
   while (I != E) {
-    const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex);
+    const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex,
+                                                          LO);
     // Did a fail-stop error of any kind occur when parsing the specifier?
     // If so, don't do any more processing.
     if (FSR.shouldStop())