Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 134052)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -1758,6 +1737,12 @@
                                              IdentifierInfo *FirstIdent,
                                              SourceLocation FirstIdentLoc,
                                              Declarator &D);
+  void ParseParameterDeclarationClause(
+         Declarator &D,
+         ParsedAttributes &attrs,
+         llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> &ParamInfo,
+         SourceLocation &EllipsisLoc,
+         bool RequiresArg = false);
   void ParseBracketDeclarator(Declarator &D);
 
   //===--------------------------------------------------------------------===//
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp	(revision 134052)
+++ lib/Parse/ParseDecl.cpp	(working copy)
@@ -3643,34 +3643,16 @@
 /// declarator D up to a paren, which indicates that we are parsing function
 /// arguments.
 ///
-/// If AttrList is non-null, then the caller parsed those arguments immediately
+/// If attrs is non-null, then the caller parsed those arguments immediately
 /// after the open paren - they should be considered to be the first argument of
 /// a parameter.  If RequiresArg is true, then the first argument of the
 /// function is required to be present and required to not be an identifier
 /// list.
 ///
-/// This method also handles this portion of the grammar:
-///       parameter-type-list: [C99 6.7.5]
-///         parameter-list
-///         parameter-list ',' '...'
-/// [C++]   parameter-list '...'
+/// For C++, after the parameter-list, it also parses cv-qualifier-seq[opt],
+/// (C++0x) ref-qualifier[opt], exception-specification[opt], and
+/// (C++0x) trailing-return-type[opt].
 ///
-///       parameter-list: [C99 6.7.5]
-///         parameter-declaration
-///         parameter-list ',' parameter-declaration
-///
-///       parameter-declaration: [C99 6.7.5]
-///         declaration-specifiers declarator
-/// [C++]   declaration-specifiers declarator '=' assignment-expression
-/// [GNU]   declaration-specifiers declarator attributes
-///         declaration-specifiers abstract-declarator[opt]
-/// [C++]   declaration-specifiers abstract-declarator[opt]
-///           '=' assignment-expression
-/// [GNU]   declaration-specifiers abstract-declarator[opt] attributes
-///
-/// For C++, after the parameter-list, it also parses "cv-qualifier-seq[opt]",
-/// C++0x "ref-qualifier[opt]" and "exception-specification[opt]".
-///
 /// [C++0x] exception-specification:
 ///           dynamic-exception-specification
 ///           noexcept-specification
@@ -3683,75 +3665,7 @@
 
   ParsedType TrailingReturnType;
 
-  // This parameter list may be empty.
-  if (Tok.is(tok::r_paren)) {
-    if (RequiresArg)
-      Diag(Tok, diag::err_argument_required_after_attribute);
-
-    SourceLocation EndLoc = ConsumeParen();  // Eat the closing ')'.
-
-    // cv-qualifier-seq[opt].
-    DeclSpec DS(AttrFactory);
-    SourceLocation RefQualifierLoc;
-    bool RefQualifierIsLValueRef = true;
-    ExceptionSpecificationType ESpecType = EST_None;
-    SourceRange ESpecRange;
-    llvm::SmallVector<ParsedType, 2> DynamicExceptions;
-    llvm::SmallVector<SourceRange, 2> DynamicExceptionRanges;
-    ExprResult NoexceptExpr;
-    if (getLang().CPlusPlus) {
-      MaybeParseCXX0XAttributes(attrs);
-
-      ParseTypeQualifierListOpt(DS, false /*no attributes*/);
-      if (!DS.getSourceRange().getEnd().isInvalid())
-        EndLoc = DS.getSourceRange().getEnd();
-
-      // Parse ref-qualifier[opt]
-      if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) {
-        if (!getLang().CPlusPlus0x)
-          Diag(Tok, diag::ext_ref_qualifier);
-
-        RefQualifierIsLValueRef = Tok.is(tok::amp);
-        RefQualifierLoc = ConsumeToken();
-        EndLoc = RefQualifierLoc;
-      }
-
-      // Parse exception-specification[opt].
-      ESpecType = MaybeParseExceptionSpecification(ESpecRange,
-                                                   DynamicExceptions,
-                                                   DynamicExceptionRanges,
-                                                   NoexceptExpr);
-      if (ESpecType != EST_None)
-        EndLoc = ESpecRange.getEnd();
-
-      // Parse trailing-return-type.
-      if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) {
-        TrailingReturnType = ParseTrailingReturnType().get();
-      }
-    }
-
-    // Remember that we parsed a function type, and remember the attributes.
-    // int() -> no prototype, no '...'.
-    D.AddTypeInfo(DeclaratorChunk::getFunction(/*prototype*/getLang().CPlusPlus,
-                                               /*variadic*/ false,
-                                               SourceLocation(),
-                                               /*arglist*/ 0, 0,
-                                               DS.getTypeQualifiers(),
-                                               RefQualifierIsLValueRef,
-                                               RefQualifierLoc,
-                                               ESpecType, ESpecRange.getBegin(),
-                                               DynamicExceptions.data(),
-                                               DynamicExceptionRanges.data(),
-                                               DynamicExceptions.size(),
-                                               NoexceptExpr.isUsable() ?
-                                                 NoexceptExpr.get() : 0,
-                                               LParenLoc, EndLoc, D,
-                                               TrailingReturnType),
-                  attrs, EndLoc);
-    return;
-  }
-
-  // Alternatively, this parameter list may be an identifier list form for a
+  // This parameter list may be an identifier list form for a
   // K&R-style function:  void foo(a,b,c)
   if (!getLang().CPlusPlus && Tok.is(tok::identifier)
       && !TryAltiVecVectorToken()) {
@@ -3790,150 +3704,17 @@
     }
   }
 
-  // Finally, a normal, non-empty parameter type list.
-
-  // Build up an array of information about the parsed arguments.
-  llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
-
   // Enter function-declaration scope, limiting any declarators to the
   // function prototype scope, including parameter declarators.
   ParseScope PrototypeScope(this,
                             Scope::FunctionPrototypeScope|Scope::DeclScope);
 
-  bool IsVariadic = false;
+  // Build up an array of information about the parsed arguments.
+  llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
+  // Remember where we see an ellipsis, if any.
   SourceLocation EllipsisLoc;
-  while (1) {
-    if (Tok.is(tok::ellipsis)) {
-      IsVariadic = true;
-      EllipsisLoc = ConsumeToken();     // Consume the ellipsis.
-      break;
-    }
+  ParseParameterDeclarationClause(D, attrs, ParamInfo, EllipsisLoc, RequiresArg);
 
-    // Parse the declaration-specifiers.
-    // Just use the ParsingDeclaration "scope" of the declarator.
-    DeclSpec DS(AttrFactory);
-	
-    // Skip any Microsoft attributes before a param.
-    if (getLang().Microsoft && Tok.is(tok::l_square))
-      ParseMicrosoftAttributes(DS.getAttributes());
-
-    SourceLocation DSStart = Tok.getLocation();
-
-    // If the caller parsed attributes for the first argument, add them now.
-    // Take them so that we only apply the attributes to the first parameter.
-    DS.takeAttributesFrom(attrs);
-
-    ParseDeclarationSpecifiers(DS);
-
-    // Parse the declarator.  This is "PrototypeContext", because we must
-    // accept either 'declarator' or 'abstract-declarator' here.
-    Declarator ParmDecl(DS, Declarator::PrototypeContext);
-    ParseDeclarator(ParmDecl);
-
-    // Parse GNU attributes, if present.
-    MaybeParseGNUAttributes(ParmDecl);
-
-    // Remember this parsed parameter in ParamInfo.
-    IdentifierInfo *ParmII = ParmDecl.getIdentifier();
-
-    // DefArgToks is used when the parsing of default arguments needs
-    // to be delayed.
-    CachedTokens *DefArgToks = 0;
-
-    // If no parameter was specified, verify that *something* was specified,
-    // otherwise we have a missing type and identifier.
-    if (DS.isEmpty() && ParmDecl.getIdentifier() == 0 &&
-        ParmDecl.getNumTypeObjects() == 0) {
-      // Completely missing, emit error.
-      Diag(DSStart, diag::err_missing_param);
-    } else {
-      // Otherwise, we have something.  Add it and let semantic analysis try
-      // to grok it and add the result to the ParamInfo we are building.
-
-      // Inform the actions module about the parameter declarator, so it gets
-      // added to the current scope.
-      Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
-
-      // Parse the default argument, if any. We parse the default
-      // arguments in all dialects; the semantic analysis in
-      // ActOnParamDefaultArgument will reject the default argument in
-      // C.
-      if (Tok.is(tok::equal)) {
-        SourceLocation EqualLoc = Tok.getLocation();
-
-        // Parse the default argument
-        if (D.getContext() == Declarator::MemberContext) {
-          // If we're inside a class definition, cache the tokens
-          // corresponding to the default argument. We'll actually parse
-          // them when we see the end of the class definition.
-          // FIXME: Templates will require something similar.
-          // FIXME: Can we use a smart pointer for Toks?
-          DefArgToks = new CachedTokens;
-
-          if (!ConsumeAndStoreUntil(tok::comma, tok::r_paren, *DefArgToks,
-                                    /*StopAtSemi=*/true,
-                                    /*ConsumeFinalToken=*/false)) {
-            delete DefArgToks;
-            DefArgToks = 0;
-            Actions.ActOnParamDefaultArgumentError(Param);
-          } else {
-            // Mark the end of the default argument so that we know when to
-            // stop when we parse it later on.
-            Token DefArgEnd;
-            DefArgEnd.startToken();
-            DefArgEnd.setKind(tok::cxx_defaultarg_end);
-            DefArgEnd.setLocation(Tok.getLocation());
-            DefArgToks->push_back(DefArgEnd);
-            Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc,
-                                                (*DefArgToks)[1].getLocation());
-          }
-        } else {
-          // Consume the '='.
-          ConsumeToken();
-
-          // The argument isn't actually potentially evaluated unless it is 
-          // used.
-          EnterExpressionEvaluationContext Eval(Actions,
-                                              Sema::PotentiallyEvaluatedIfUsed);
-
-          ExprResult DefArgResult(ParseAssignmentExpression());
-          if (DefArgResult.isInvalid()) {
-            Actions.ActOnParamDefaultArgumentError(Param);
-            SkipUntil(tok::comma, tok::r_paren, true, true);
-          } else {
-            // Inform the actions module about the default argument
-            Actions.ActOnParamDefaultArgument(Param, EqualLoc,
-                                              DefArgResult.take());
-          }
-        }
-      }
-
-      ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
-                                          ParmDecl.getIdentifierLoc(), Param,
-                                          DefArgToks));
-    }
-
-    // If the next token is a comma, consume it and keep reading arguments.
-    if (Tok.isNot(tok::comma)) {
-      if (Tok.is(tok::ellipsis)) {
-        IsVariadic = true;
-        EllipsisLoc = ConsumeToken();     // Consume the ellipsis.
-        
-        if (!getLang().CPlusPlus) {
-          // We have ellipsis without a preceding ',', which is ill-formed
-          // in C. Complain and provide the fix.
-          Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)
-            << FixItHint::CreateInsertion(EllipsisLoc, ", ");
-        }
-      }
-      
-      break;
-    }
-
-    // Consume the comma.
-    ConsumeToken();
-  }
-
   // If we have the closing ')', eat it.
   SourceLocation EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
 
@@ -3954,7 +3735,7 @@
       if (!DS.getSourceRange().getEnd().isInvalid())
         EndLoc = DS.getSourceRange().getEnd();
 
-    // Parse ref-qualifier[opt]
+    // Parse ref-qualifier[opt].
     if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) {
       if (!getLang().CPlusPlus0x)
         Diag(Tok, diag::ext_ref_qualifier);
@@ -3976,7 +3757,7 @@
     if (ESpecType != EST_None)
       EndLoc = ESpecRange.getEnd();
 
-    // Parse trailing-return-type.
+    // Parse trailing-return-type[opt].
     if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) {
       TrailingReturnType = ParseTrailingReturnType().get();
     }
@@ -3986,7 +3767,10 @@
   PrototypeScope.Exit();
 
   // Remember that we parsed a function type, and remember the attributes.
-  D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic,
+  // No parameter list means no prototype?
+  D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/(ParamInfo.size()) ?
+                                               (true) : (getLang().CPlusPlus),
+                                             /*isVariadic=*/EllipsisLoc.isValid(),
                                              EllipsisLoc,
                                              ParamInfo.data(), ParamInfo.size(),
                                              DS.getTypeQualifiers(),
@@ -4080,6 +3864,187 @@
                 attrs, RLoc);
 }
 
+/// ParseParameterDeclarationClause - Parse a (possibly empty) parameter-list
+/// after the opening parenthesis. This function will not parse a K&R-style
+/// identifier list.
+///
+/// FIXME: Should the name indicate that it may consume nothing?
+///
+/// D is the declarator being parsed.  If attrs is non-null, then the caller
+/// parsed those arguments immediately after the open paren - they should be
+/// considered to be the first argument of a parameter.  If RequiresArg is true,
+/// then the first argument of the function is required to be present.
+///
+/// After returning, ParamInfo will hold the parsed parameters. EllipsisLoc will
+/// be the location of the ellipsis, if any was parsed.
+///
+///       parameter-type-list: [C99 6.7.5]
+///         parameter-list
+///         parameter-list ',' '...'
+/// [C++]   parameter-list '...'
+///
+///       parameter-list: [C99 6.7.5]
+///         parameter-declaration
+///         parameter-list ',' parameter-declaration
+///
+///       parameter-declaration: [C99 6.7.5]
+///         declaration-specifiers declarator
+/// [C++]   declaration-specifiers declarator '=' assignment-expression
+/// [GNU]   declaration-specifiers declarator attributes
+///         declaration-specifiers abstract-declarator[opt]
+/// [C++]   declaration-specifiers abstract-declarator[opt]
+///           '=' assignment-expression
+/// [GNU]   declaration-specifiers abstract-declarator[opt] attributes
+///
+void Parser::ParseParameterDeclarationClause(
+       Declarator &D,
+       ParsedAttributes &attrs,
+       llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> &ParamInfo,
+       SourceLocation &EllipsisLoc,
+       bool RequiresArg) {
+
+  if (Tok.is(tok::r_paren)) {
+    if (RequiresArg)
+      Diag(Tok, diag::err_argument_required_after_attribute);
+    return;
+  }
+
+  while (1) {
+    if (Tok.is(tok::ellipsis)) {
+      EllipsisLoc = ConsumeToken();     // Consume the ellipsis.
+      break;
+    }
+
+    // Parse the declaration-specifiers.
+    // Just use the ParsingDeclaration "scope" of the declarator.
+    DeclSpec DS(AttrFactory);
+	
+    // Skip any Microsoft attributes before a param.
+    if (getLang().Microsoft && Tok.is(tok::l_square))
+      ParseMicrosoftAttributes(DS.getAttributes());
+
+    SourceLocation DSStart = Tok.getLocation();
+
+    // If the caller parsed attributes for the first argument, add them now.
+    // Take them so that we only apply the attributes to the first parameter.
+    // FIXME: If we saw an ellipsis first, this code is not reached. Are the
+    // attributes lost? Should they even be allowed?
+    // FIXME: If we can leave the attributes in the token stream somehow, we can
+    // get rid of two parameters (attrs, RequiresArg) and this statement
+    DS.takeAttributesFrom(attrs);
+
+    ParseDeclarationSpecifiers(DS);
+
+    // Parse the declarator.  This is "PrototypeContext", because we must
+    // accept either 'declarator' or 'abstract-declarator' here.
+    Declarator ParmDecl(DS, Declarator::PrototypeContext);
+    ParseDeclarator(ParmDecl);
+
+    // Parse GNU attributes, if present.
+    MaybeParseGNUAttributes(ParmDecl);
+
+    // Remember this parsed parameter in ParamInfo.
+    IdentifierInfo *ParmII = ParmDecl.getIdentifier();
+
+    // DefArgToks is used when the parsing of default arguments needs
+    // to be delayed.
+    CachedTokens *DefArgToks = 0;
+
+    // If no parameter was specified, verify that *something* was specified,
+    // otherwise we have a missing type and identifier.
+    if (DS.isEmpty() && ParmDecl.getIdentifier() == 0 &&
+        ParmDecl.getNumTypeObjects() == 0) {
+      // Completely missing, emit error.
+      Diag(DSStart, diag::err_missing_param);
+    } else {
+      // Otherwise, we have something.  Add it and let semantic analysis try
+      // to grok it and add the result to the ParamInfo we are building.
+
+      // Inform the actions module about the parameter declarator, so it gets
+      // added to the current scope.
+      Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
+
+      // Parse the default argument, if any. We parse the default
+      // arguments in all dialects; the semantic analysis in
+      // ActOnParamDefaultArgument will reject the default argument in
+      // C.
+      if (Tok.is(tok::equal)) {
+        SourceLocation EqualLoc = Tok.getLocation();
+
+        // Parse the default argument
+        if (D.getContext() == Declarator::MemberContext) {
+          // If we're inside a class definition, cache the tokens
+          // corresponding to the default argument. We'll actually parse
+          // them when we see the end of the class definition.
+          // FIXME: Templates will require something similar.
+          // FIXME: Can we use a smart pointer for Toks?
+          DefArgToks = new CachedTokens;
+
+          if (!ConsumeAndStoreUntil(tok::comma, tok::r_paren, *DefArgToks,
+                                    /*StopAtSemi=*/true,
+                                    /*ConsumeFinalToken=*/false)) {
+            delete DefArgToks;
+            DefArgToks = 0;
+            Actions.ActOnParamDefaultArgumentError(Param);
+          } else {
+            // Mark the end of the default argument so that we know when to
+            // stop when we parse it later on.
+            Token DefArgEnd;
+            DefArgEnd.startToken();
+            DefArgEnd.setKind(tok::cxx_defaultarg_end);
+            DefArgEnd.setLocation(Tok.getLocation());
+            DefArgToks->push_back(DefArgEnd);
+            Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc,
+                                                (*DefArgToks)[1].getLocation());
+          }
+        } else {
+          // Consume the '='.
+          ConsumeToken();
+
+          // The argument isn't actually potentially evaluated unless it is 
+          // used.
+          EnterExpressionEvaluationContext Eval(Actions,
+                                              Sema::PotentiallyEvaluatedIfUsed);
+
+          ExprResult DefArgResult(ParseAssignmentExpression());
+          if (DefArgResult.isInvalid()) {
+            Actions.ActOnParamDefaultArgumentError(Param);
+            SkipUntil(tok::comma, tok::r_paren, true, true);
+          } else {
+            // Inform the actions module about the default argument
+            Actions.ActOnParamDefaultArgument(Param, EqualLoc,
+                                              DefArgResult.take());
+          }
+        }
+      }
+
+      ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
+                                          ParmDecl.getIdentifierLoc(), Param,
+                                          DefArgToks));
+    }
+
+    // If the next token is a comma, consume it and keep reading arguments.
+    if (Tok.isNot(tok::comma)) {
+      if (Tok.is(tok::ellipsis)) {
+        EllipsisLoc = ConsumeToken();     // Consume the ellipsis.
+        
+        if (!getLang().CPlusPlus) {
+          // We have ellipsis without a preceding ',', which is ill-formed
+          // in C. Complain and provide the fix.
+          Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)
+            << FixItHint::CreateInsertion(EllipsisLoc, ", ");
+        }
+      }
+      
+      break;
+    }
+
+    // Consume the comma.
+    ConsumeToken();
+  }
+
+}
+
 /// [C90]   direct-declarator '[' constant-expression[opt] ']'
 /// [C99]   direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
 /// [C99]   direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
