Delay parsing of default arguments of member functions until the class
is completely defined (C++ [class.mem]p2).

Reverse the order in which we process the definitions of member
functions specified inline. This way, we'll get diagnostics in the
order in which the member functions were declared in the class.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61103 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 824847a..a9712fe 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -31,13 +31,13 @@
 
   // Consume the tokens and store them for later parsing.
 
-  getCurTopClassStack().push(LexedMethod(FnD));
-  TokensTy &Toks = getCurTopClassStack().top().Toks;
+  getCurTopClassStack().MethodDefs.push_back(LexedMethod(FnD));
+  CachedTokens &Toks = getCurTopClassStack().MethodDefs.back().Toks;
 
   // We may have a constructor initializer here.
   if (Tok.is(tok::colon)) {
     // Consume everything up to (and including) the left brace.
-    if (!ConsumeAndStoreUntil(tok::l_brace, Toks, tok::semi)) {
+    if (!ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks, tok::semi)) {
       // We didn't find the left-brace we expected after the
       // constructor initializer. 
       if (Tok.is(tok::semi)) {
@@ -45,7 +45,7 @@
         // don't try to parse this method later.
         Diag(Tok.getLocation(), diag::err_expected_lbrace);
         ConsumeAnyToken();
-        getCurTopClassStack().pop();
+        getCurTopClassStack().MethodDefs.pop_back();
         return FnD;
       }
     }
@@ -56,17 +56,66 @@
     ConsumeBrace();
   }
   // Consume everything up to (and including) the matching right brace.
-  ConsumeAndStoreUntil(tok::r_brace, Toks);
+  ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
 
   return FnD;
 }
 
+/// ParseLexedMethodDeclarations - We finished parsing the member
+/// specification of a top (non-nested) C++ class. Now go over the
+/// stack of method declarations with some parts for which parsing was
+/// delayed (such as default arguments) and parse them.
+void Parser::ParseLexedMethodDeclarations() {
+  for (; !getCurTopClassStack().MethodDecls.empty();
+       getCurTopClassStack().MethodDecls.pop_front()) {
+    LateParsedMethodDeclaration &LM = getCurTopClassStack().MethodDecls.front();
+    
+    // Start the delayed C++ method declaration
+    Actions.ActOnStartDelayedCXXMethodDeclaration(CurScope, LM.Method);
+
+    // Introduce the parameters into scope and parse their default
+    // arguments.
+    ParseScope PrototypeScope(this, Scope::FnScope|Scope::DeclScope);
+    for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
+      // Introduce the parameter into scope.
+      Actions.ActOnDelayedCXXMethodParameter(CurScope, LM.DefaultArgs[I].Param);
+
+      if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
+        // Parse the default argument from its saved token stream.
+        Toks->push_back(Tok); // So that the current token doesn't get lost
+        PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false);
+
+        // Consume the previously-pushed token.
+        ConsumeAnyToken();
+
+        // Consume the '='.
+        assert(Tok.is(tok::equal) && "Default argument not starting with '='");
+        SourceLocation EqualLoc = ConsumeToken();
+
+        OwningExprResult DefArgResult(ParseAssignmentExpression());
+        if (DefArgResult.isInvalid())
+          Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param);
+        else
+          Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc,
+                                            DefArgResult.release());
+        delete Toks;
+        LM.DefaultArgs[I].Toks = 0;
+      }
+    }
+    PrototypeScope.Exit();
+
+    // Finish the delayed C++ method declaration.
+    Actions.ActOnFinishDelayedCXXMethodDeclaration(CurScope, LM.Method);
+  }
+}
+
 /// ParseLexedMethodDefs - We finished parsing the member specification of a top
 /// (non-nested) C++ class. Now go over the stack of lexed methods that were
 /// collected during its parsing and parse them all.
 void Parser::ParseLexedMethodDefs() {
-  for (; !getCurTopClassStack().empty(); getCurTopClassStack().pop()) {
-    LexedMethod &LM = getCurTopClassStack().top();
+  for (; !getCurTopClassStack().MethodDefs.empty(); 
+       getCurTopClassStack().MethodDefs.pop_front()) {
+    LexedMethod &LM = getCurTopClassStack().MethodDefs.front();
 
     assert(!LM.Toks.empty() && "Empty body!");
     // Append the current token at the end of the new token stream so that it
@@ -92,21 +141,26 @@
 }
 
 /// ConsumeAndStoreUntil - Consume and store the token at the passed token
-/// container until the token 'T' is reached (which gets consumed/stored too).
+/// container until the token 'T' is reached (which gets
+/// consumed/stored too, if ConsumeFinalToken). 
 /// If EarlyAbortIf is specified, then we will stop early if we find that
 /// token at the top level.
-/// Returns true if token 'T' was found.
+/// Returns true if token 'T1' or 'T2' was found.
 /// NOTE: This is a specialized version of Parser::SkipUntil.
-bool Parser::ConsumeAndStoreUntil(tok::TokenKind T, TokensTy &Toks,
-                                  tok::TokenKind EarlyAbortIf) {
+bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
+                                  CachedTokens &Toks,
+                                  tok::TokenKind EarlyAbortIf,
+                                  bool ConsumeFinalToken) {
   // We always want this function to consume at least one token if the first
   // token isn't T and if not at EOF.
   bool isFirstTokenConsumed = true;
   while (1) {
     // If we found one of the tokens, stop and return true.
-    if (Tok.is(T)) {
-      Toks.push_back(Tok);
-      ConsumeAnyToken();
+    if (Tok.is(T1) || Tok.is(T2)) {
+      if (ConsumeFinalToken) {
+        Toks.push_back(Tok);
+        ConsumeAnyToken();
+      }
       return true;
     }
 
@@ -123,19 +177,19 @@
       // Recursively consume properly-nested parens.
       Toks.push_back(Tok);
       ConsumeParen();
-      ConsumeAndStoreUntil(tok::r_paren, Toks);
+      ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks);
       break;
     case tok::l_square:
       // Recursively consume properly-nested square brackets.
       Toks.push_back(Tok);
       ConsumeBracket();
-      ConsumeAndStoreUntil(tok::r_square, Toks);
+      ConsumeAndStoreUntil(tok::r_square, tok::unknown, Toks);
       break;
     case tok::l_brace:
       // Recursively consume properly-nested braces.
       Toks.push_back(Tok);
       ConsumeBrace();
-      ConsumeAndStoreUntil(tok::r_brace, Toks);
+      ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
       break;
 
     // Okay, we found a ']' or '}' or ')', which we think should be balanced.