Handle any undeclared parameters in a K&R-style function with a
special action, inside function prototype scope. This avoids confusion
when we try to inject these parameters into the scope of the function
body before the function itself has been added to the surrounding
scope. Fixes <rdar://problem/6097326>.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62849 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 5d87b17..0f0d88a 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -223,6 +223,13 @@
     return Group;
   }
 
+  /// @brief Indicates that all K&R-style parameter declarations have
+  /// been parsed prior to a function definition.
+  /// @param S  The function prototype scope.
+  /// @param D  The function declarator.
+  virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D) {
+  }
+
   /// ActOnStartOfFunctionDef - This is called at the start of a function
   /// definition, instead of calling ActOnDeclarator.  The Declarator includes
   /// information about formal arguments that are part of this function.
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 6ae3bf0..7e1cef9 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -674,6 +674,7 @@
   }
 
   // The actions module must verify that all arguments were declared.
+  Actions.ActOnFinishKNRParamDeclarations(CurScope, D);
 }
 
 
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 128ba88..40cfe8f 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -311,6 +311,7 @@
   void ActOnUninitializedDecl(DeclTy *dcl);
   virtual DeclTy *FinalizeDeclaratorGroup(Scope *S, DeclTy *Group);
 
+  virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D);
   virtual DeclTy *ActOnStartOfFunctionDef(Scope *S, Declarator &D);
   virtual DeclTy *ActOnStartOfFunctionDef(Scope *S, DeclTy *D);
   virtual void ObjCActOnStartOfMethodDef(Scope *S, DeclTy *D);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 276f2e2..e766ca0 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2633,8 +2633,7 @@
 
 }
 
-Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
-  assert(getCurFunctionDecl() == 0 && "Function parsing confused");
+void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D) {
   assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
          "Not a function declarator!");
   DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
@@ -2654,10 +2653,19 @@
                            PrevSpec);
         Declarator ParamD(DS, Declarator::KNRTypeListContext);
         ParamD.SetIdentifier(FTI.ArgInfo[i].Ident, FTI.ArgInfo[i].IdentLoc);
-        FTI.ArgInfo[i].Param = ActOnParamDeclarator(FnBodyScope, ParamD);
+        FTI.ArgInfo[i].Param = ActOnParamDeclarator(S, ParamD);
       }
     }
-  } else {
+  } 
+}
+
+Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
+  assert(getCurFunctionDecl() == 0 && "Function parsing confused");
+  assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
+         "Not a function declarator!");
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+
+  if (FTI.hasPrototype) {
     // FIXME: Diagnose arguments without names in C. 
   }
   
diff --git a/test/Sema/function.c b/test/Sema/function.c
index de970a0..677f6a3 100644
--- a/test/Sema/function.c
+++ b/test/Sema/function.c
@@ -39,3 +39,7 @@
 int t14() {
   return; // expected-warning {{non-void function 't14' should return a value}}
 }
+
+// <rdar://problem/6097326>
+y(y) { return y; } // expected-warning{{parameter 'y' was not declared, defaulting to type 'int'}} \
+                   // expected-warning{{type specifier missing, defaults to 'int'}}
diff --git a/test/Sema/redefinition.c b/test/Sema/redefinition.c
index 5e79070..97e0473 100644
--- a/test/Sema/redefinition.c
+++ b/test/Sema/redefinition.c
@@ -3,3 +3,8 @@
 int f(int);
 int f(int a) { } // expected-error {{redefinition of 'f'}}
 
+// <rdar://problem/6097326>
+int foo(x) {
+  return 0;
+}
+int x = 1;