Improve error recovery in C/ObjC when the first argument of a function
declarator is incorrect.  Not being a typename causes the parser to 
dive down into the K&R identifier list handling stuff, which is almost
never the right thing to do.

Before:

r.c:3:17: error: expected ')'
void bar(intptr y);
                ^
r.c:3:9: note: to match this '('
void bar(intptr y);
        ^
r.c:3:10: error: a parameter list without types is only allowed in a function definition
void bar(intptr y);
         ^

After:

r.c:3:10: error: unknown type name 'intptr'; did you mean 'intptr_t'?
void bar(intptr y);
         ^~~~~~
         intptr_t
r.c:1:13: note: 'intptr_t' declared here
typedef int intptr_t;
            ^

This fixes rdar://7980651 - poor recovery for bad type in the first arg of a C function



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103783 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 9b4264d..28d9dd0 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2941,12 +2941,29 @@
       // Identifier list.  Note that '(' identifier-list ')' is only allowed for
       // normal declarators, not for abstract-declarators.  Get the first
       // identifier.
-      IdentifierInfo *FirstIdent = Tok.getIdentifierInfo();
-      SourceLocation FirstIdentLoc = Tok.getLocation();
+      Token FirstTok = Tok;
       ConsumeToken();  // eat the first identifier.
-
-      return ParseFunctionDeclaratorIdentifierList(LParenLoc, FirstIdent,
-                                                   FirstIdentLoc, D);
+      
+      // Identifier lists follow a really simple grammar: the identifiers can
+      // be followed *only* by a ", moreidentifiers" or ")".  However, K&R
+      // identifier lists are really rare in the brave new modern world, and it
+      // is very common for someone to typo a type in a non-k&r style list.  If
+      // we are presented with something like: "void foo(intptr x, float y)",
+      // we don't want to start parsing the function declarator as though it is
+      // a K&R style declarator just because intptr is an invalid type.
+      //
+      // To handle this, we check to see if the token after the first identifier
+      // is a "," or ")".  Only if so, do we parse it as an identifier list.
+      if (Tok.is(tok::comma) || Tok.is(tok::r_paren))
+        return ParseFunctionDeclaratorIdentifierList(LParenLoc,
+                                                   FirstTok.getIdentifierInfo(),
+                                                     FirstTok.getLocation(), D);
+      
+      // If we get here, the code is invalid.  Push the first identifier back
+      // into the token stream and parse the first argument as an (invalid)
+      // normal argument declarator.
+      PP.EnterToken(Tok);
+      Tok = FirstTok;
     }
   }