[cfe-commits] r116311 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Frontend/ASTUnit.cpp lib/Parse/ParseCXXInlineMethods.cpp lib/Parse/ParseDeclCXX.cpp test/CXX/class/class.mem/p1b.cpp test/SemaCXX/default2.cpp

Douglas Gregor dgregor at apple.com
Tue Oct 12 09:25:54 PDT 2010


Author: dgregor
Date: Tue Oct 12 11:25:54 2010
New Revision: 116311

URL: http://llvm.org/viewvc/llvm-project?rev=116311&view=rev
Log:
Parse default arguments within member functions in source order, from
Manuel Klimek! Fixes PR7715.

Added:
    cfe/trunk/test/CXX/class/class.mem/p1b.cpp   (with props)
Modified:
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Frontend/ASTUnit.cpp
    cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/test/SemaCXX/default2.cpp

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=116311&r1=116310&r2=116311&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Oct 12 11:25:54 2010
@@ -566,7 +566,44 @@
   //===--------------------------------------------------------------------===//
   // Lexing and parsing of C++ inline methods.
 
-  struct LexedMethod {
+  struct ParsingClass;
+
+  /// [class.mem]p1: "... the class is regarded as complete within
+  /// - function bodies
+  /// - default arguments
+  /// - exception-specifications (TODO: C++0x)
+  /// - and brace-or-equal-initializers (TODO: C++0x)
+  /// for non-static data members (including such things in nested classes)."
+  /// LateParsedDeclarations build the tree of those elements so they can
+  /// be parsed after parsing the top-level class.
+  class LateParsedDeclaration {
+  public:
+    virtual ~LateParsedDeclaration();
+
+    virtual void ParseLexedMethodDeclarations();
+    virtual void ParseLexedMethodDefs();
+  };
+
+  /// Inner node of the LateParsedDeclaration tree that parses
+  /// all its members recursively.
+  class LateParsedClass : public LateParsedDeclaration {
+  public:
+    LateParsedClass(Parser *P, ParsingClass *C);
+    virtual ~LateParsedClass();
+
+    virtual void ParseLexedMethodDeclarations();
+    virtual void ParseLexedMethodDefs();
+
+  private:
+    Parser *Self;
+    ParsingClass *Class;
+  };
+
+  /// Contains the lexed tokens of a member function definition
+  /// which needs to be parsed at the end of the class declaration
+  /// after parsing all other member declarations.
+  struct LexedMethod : public LateParsedDeclaration {
+    Parser *Self;
     Decl *D;
     CachedTokens Toks;
 
@@ -575,7 +612,10 @@
     /// othewise, it is a member function declaration.
     bool TemplateScope;
 
-    explicit LexedMethod(Decl *MD) : D(MD), TemplateScope(false) {}
+    explicit LexedMethod(Parser* P, Decl *MD)
+      : Self(P), D(MD), TemplateScope(false) {}
+
+    virtual void ParseLexedMethodDefs();
   };
 
   /// LateParsedDefaultArgument - Keeps track of a parameter that may
@@ -601,9 +641,13 @@
   /// contains at least one entity whose parsing needs to be delayed
   /// until the class itself is completely-defined, such as a default
   /// argument (C++ [class.mem]p2).
-  struct LateParsedMethodDeclaration {
-    explicit LateParsedMethodDeclaration(Decl *M)
-      : Method(M), TemplateScope(false) { }
+  struct LateParsedMethodDeclaration : public LateParsedDeclaration {
+    explicit LateParsedMethodDeclaration(Parser *P, Decl *M)
+      : Self(P), Method(M), TemplateScope(false) { }
+
+    virtual void ParseLexedMethodDeclarations();
+
+    Parser* Self;
 
     /// Method - The method declaration.
     Decl *Method;
@@ -621,17 +665,12 @@
     llvm::SmallVector<LateParsedDefaultArgument, 8> DefaultArgs;
   };
 
-  /// LateParsedMethodDecls - During parsing of a top (non-nested) C++
-  /// class, its method declarations that contain parts that won't be
+  /// LateParsedDeclarationsContainer - During parsing of a top (non-nested)
+  /// C++ class, its method declarations that contain parts that won't be
   /// parsed until after the definiton is completed (C++ [class.mem]p2),
-  /// the method declarations will be stored here with the tokens that
-  /// will be parsed to create those entities.
-  typedef std::list<LateParsedMethodDeclaration> LateParsedMethodDecls;
-
-  /// LexedMethodsForTopClass - During parsing of a top (non-nested) C++ class,
-  /// its inline method definitions and the inline method definitions of its
-  /// nested classes are lexed and stored here.
-  typedef std::list<LexedMethod> LexedMethodsForTopClass;
+  /// the method declarations and possibly attached inline definitions
+  /// will be stored here with the tokens that will be parsed to create those entities.
+  typedef llvm::SmallVector<LateParsedDeclaration*, 2> LateParsedDeclarationsContainer;
 
   /// \brief Representation of a class that has been parsed, including
   /// any member function declarations or definitions that need to be
@@ -653,16 +692,10 @@
     /// \brief The class or class template whose definition we are parsing.
     Decl *TagOrTemplate;
 
-    /// MethodDecls - Method declarations that contain pieces whose
-    /// parsing will be delayed until the class is fully defined.
-    LateParsedMethodDecls MethodDecls;
-
-    /// MethodDefs - Methods whose definitions will be parsed once the
-    /// class has been fully defined.
-    LexedMethodsForTopClass MethodDefs;
-
-    /// \brief Nested classes inside this class.
-    llvm::SmallVector<ParsingClass*, 4> NestedClasses;
+    /// LateParsedDeclarations - Method declarations, inline definitions and
+    /// nested classes that contain pieces whose parsing will be delayed until
+    /// the top-level class is fully defined.
+    LateParsedDeclarationsContainer LateParsedDeclarations;
   };
 
   /// \brief The stack of classes that is currently being
@@ -868,7 +901,9 @@
   Decl *ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D,
                                      const ParsedTemplateInfo &TemplateInfo);
   void ParseLexedMethodDeclarations(ParsingClass &Class);
+  void ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM);
   void ParseLexedMethodDefs(ParsingClass &Class);
+  void ParseLexedMethodDef(LexedMethod &LM);
   bool ConsumeAndStoreUntil(tok::TokenKind T1,
                             CachedTokens &Toks,
                             bool StopAtSemi = true,

Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=116311&r1=116310&r2=116311&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Tue Oct 12 11:25:54 2010
@@ -807,6 +807,7 @@
     SavedMainFileBuffer = 0;
   }
   
+  StoredDiagnostics.clear();
   Clang.takeSourceManager();
   Clang.takeFileManager();
   Invocation.reset(Clang.takeInvocation());

Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=116311&r1=116310&r2=116311&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Tue Oct 12 11:25:54 2010
@@ -45,10 +45,10 @@
 
   // Consume the tokens and store them for later parsing.
 
-  getCurrentClass().MethodDefs.push_back(LexedMethod(FnD));
-  getCurrentClass().MethodDefs.back().TemplateScope
-    = getCurScope()->isTemplateParamScope();
-  CachedTokens &Toks = getCurrentClass().MethodDefs.back().Toks;
+  LexedMethod* LM = new LexedMethod(this, FnD);
+  getCurrentClass().LateParsedDeclarations.push_back(LM);
+  LM->TemplateScope = getCurScope()->isTemplateParamScope();
+  CachedTokens &Toks = LM->Toks;
 
   tok::TokenKind kind = Tok.getKind();
   // We may have a constructor initializer or function-try-block here.
@@ -62,7 +62,8 @@
         // don't try to parse this method later.
         Diag(Tok.getLocation(), diag::err_expected_lbrace);
         ConsumeAnyToken();
-        getCurrentClass().MethodDefs.pop_back();
+        delete getCurrentClass().LateParsedDeclarations.back();
+        getCurrentClass().LateParsedDeclarations.pop_back();
         return FnD;
       }
     }
@@ -86,13 +87,40 @@
   return FnD;
 }
 
+Parser::LateParsedDeclaration::~LateParsedDeclaration() {}
+void Parser::LateParsedDeclaration::ParseLexedMethodDeclarations() {}
+void Parser::LateParsedDeclaration::ParseLexedMethodDefs() {}
+
+Parser::LateParsedClass::LateParsedClass(Parser *P, ParsingClass *C)
+  : Self(P), Class(C) {}
+
+Parser::LateParsedClass::~LateParsedClass() {
+  Self->DeallocateParsedClasses(Class);
+}
+
+void Parser::LateParsedClass::ParseLexedMethodDeclarations() {
+  Self->ParseLexedMethodDeclarations(*Class);
+}
+
+void Parser::LateParsedClass::ParseLexedMethodDefs() {
+  Self->ParseLexedMethodDefs(*Class);
+}
+
+void Parser::LateParsedMethodDeclaration::ParseLexedMethodDeclarations() {
+  Self->ParseLexedMethodDeclaration(*this);
+}
+
+void Parser::LexedMethod::ParseLexedMethodDefs() {
+  Self->ParseLexedMethodDef(*this);
+}
+
 /// 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(ParsingClass &Class) {
   bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
-  ParseScope TemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
+  ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
   if (HasTemplateScope)
     Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
 
@@ -104,80 +132,79 @@
   if (HasClassScope)
     Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate);
 
-  for (; !Class.MethodDecls.empty(); Class.MethodDecls.pop_front()) {
-    LateParsedMethodDeclaration &LM = Class.MethodDecls.front();
+  for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
+    Class.LateParsedDeclarations[i]->ParseLexedMethodDeclarations();
+  }
 
-    // If this is a member template, introduce the template parameter scope.
-    ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
-    if (LM.TemplateScope)
-      Actions.ActOnReenterTemplateScope(getCurScope(), LM.Method);
-
-    // Start the delayed C++ method declaration
-    Actions.ActOnStartDelayedCXXMethodDeclaration(getCurScope(), LM.Method);
-
-    // Introduce the parameters into scope and parse their default
-    // arguments.
-    ParseScope PrototypeScope(this,
-                              Scope::FunctionPrototypeScope|Scope::DeclScope);
-    for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
-      // Introduce the parameter into scope.
-      Actions.ActOnDelayedCXXMethodParameter(getCurScope(), LM.DefaultArgs[I].Param);
-
-      if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
-        // Save the current token position.
-        SourceLocation origLoc = Tok.getLocation();
-
-        // 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);
+  if (HasClassScope)
+    Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate);
+}
 
-        // Consume the previously-pushed token.
-        ConsumeAnyToken();
+void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
+  // If this is a member template, introduce the template parameter scope.
+  ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
+  if (LM.TemplateScope)
+    Actions.ActOnReenterTemplateScope(getCurScope(), LM.Method);
+
+  // Start the delayed C++ method declaration
+  Actions.ActOnStartDelayedCXXMethodDeclaration(getCurScope(), LM.Method);
+
+  // Introduce the parameters into scope and parse their default
+  // arguments.
+  ParseScope PrototypeScope(this,
+                            Scope::FunctionPrototypeScope|Scope::DeclScope);
+  for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
+    // Introduce the parameter into scope.
+    Actions.ActOnDelayedCXXMethodParameter(getCurScope(), LM.DefaultArgs[I].Param);
+
+    if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
+      // Save the current token position.
+      SourceLocation origLoc = Tok.getLocation();
+
+      // 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();
+
+      // The argument isn't actually potentially evaluated unless it is
+      // used.
+      EnterExpressionEvaluationContext Eval(Actions,
+                                            Sema::PotentiallyEvaluatedIfUsed);
+
+      ExprResult DefArgResult(ParseAssignmentExpression());
+      if (DefArgResult.isInvalid())
+        Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param);
+      else {
+        if (Tok.is(tok::cxx_defaultarg_end))
+          ConsumeToken();
+        else
+          Diag(Tok.getLocation(), diag::err_default_arg_unparsed);
+        Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc,
+                                          DefArgResult.take());
+      }
 
-        // Consume the '='.
-        assert(Tok.is(tok::equal) && "Default argument not starting with '='");
-        SourceLocation EqualLoc = 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(LM.DefaultArgs[I].Param);
-        else {
-          if (Tok.is(tok::cxx_defaultarg_end))
-            ConsumeToken();
-          else
-            Diag(Tok.getLocation(), diag::err_default_arg_unparsed);
-          Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc,
-                                            DefArgResult.take());
-        }
-
-        assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
-                                                           Tok.getLocation()) &&
-               "ParseAssignmentExpression went over the default arg tokens!");
-        // There could be leftover tokens (e.g. because of an error).
-        // Skip through until we reach the original token position.
-        while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
-          ConsumeAnyToken();
+      assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
+                                                         Tok.getLocation()) &&
+             "ParseAssignmentExpression went over the default arg tokens!");
+      // There could be leftover tokens (e.g. because of an error).
+      // Skip through until we reach the original token position.
+      while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
+        ConsumeAnyToken();
 
-        delete Toks;
-        LM.DefaultArgs[I].Toks = 0;
-      }
+      delete Toks;
+      LM.DefaultArgs[I].Toks = 0;
     }
-    PrototypeScope.Exit();
-
-    // Finish the delayed C++ method declaration.
-    Actions.ActOnFinishDelayedCXXMethodDeclaration(getCurScope(), LM.Method);
   }
+  PrototypeScope.Exit();
 
-  for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I)
-    ParseLexedMethodDeclarations(*Class.NestedClasses[I]);
-
-  if (HasClassScope)
-    Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate);
+  // Finish the delayed C++ method declaration.
+  Actions.ActOnFinishDelayedCXXMethodDeclaration(getCurScope(), LM.Method);
 }
 
 /// ParseLexedMethodDefs - We finished parsing the member specification of a top
@@ -185,7 +212,7 @@
 /// collected during its parsing and parse them all.
 void Parser::ParseLexedMethodDefs(ParsingClass &Class) {
   bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
-  ParseScope TemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
+  ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
   if (HasTemplateScope)
     Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
 
@@ -193,73 +220,72 @@
   ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
                         HasClassScope);
 
-  for (; !Class.MethodDefs.empty(); Class.MethodDefs.pop_front()) {
-    LexedMethod &LM = Class.MethodDefs.front();
+  for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
+    Class.LateParsedDeclarations[i]->ParseLexedMethodDefs();
+  }
+}
 
-    // If this is a member template, introduce the template parameter scope.
-    ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
-    if (LM.TemplateScope)
-      Actions.ActOnReenterTemplateScope(getCurScope(), LM.D);
-
-    // Save the current token position.
-    SourceLocation origLoc = Tok.getLocation();
-
-    assert(!LM.Toks.empty() && "Empty body!");
-    // Append the current token at the end of the new token stream so that it
-    // doesn't get lost.
-    LM.Toks.push_back(Tok);
-    PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false);
-
-    // Consume the previously pushed token.
-    ConsumeAnyToken();
-    assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
-           && "Inline method not starting with '{', ':' or 'try'");
-
-    // Parse the method body. Function body parsing code is similar enough
-    // to be re-used for method bodies as well.
-    ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
-    Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D);
+void Parser::ParseLexedMethodDef(LexedMethod &LM) {
+  // If this is a member template, introduce the template parameter scope.
+  ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
+  if (LM.TemplateScope)
+    Actions.ActOnReenterTemplateScope(getCurScope(), LM.D);
+
+  // Save the current token position.
+  SourceLocation origLoc = Tok.getLocation();
+
+  assert(!LM.Toks.empty() && "Empty body!");
+  // Append the current token at the end of the new token stream so that it
+  // doesn't get lost.
+  LM.Toks.push_back(Tok);
+  PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false);
+
+  // Consume the previously pushed token.
+  ConsumeAnyToken();
+  assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
+         && "Inline method not starting with '{', ':' or 'try'");
+
+  // Parse the method body. Function body parsing code is similar enough
+  // to be re-used for method bodies as well.
+  ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
+  Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D);
+
+  if (Tok.is(tok::kw_try)) {
+    ParseFunctionTryBlock(LM.D);
+    assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
+                                                         Tok.getLocation()) &&
+           "ParseFunctionTryBlock went over the cached tokens!");
+    // There could be leftover tokens (e.g. because of an error).
+    // Skip through until we reach the original token position.
+    while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
+      ConsumeAnyToken();
+    return;
+  }
+  if (Tok.is(tok::colon)) {
+    ParseConstructorInitializer(LM.D);
 
-    if (Tok.is(tok::kw_try)) {
-      ParseFunctionTryBlock(LM.D);
-      assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
-                                                           Tok.getLocation()) &&
-             "ParseFunctionTryBlock went over the cached tokens!");
-      // There could be leftover tokens (e.g. because of an error).
-      // Skip through until we reach the original token position.
-      while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
-        ConsumeAnyToken();
-      continue;
+    // Error recovery.
+    if (!Tok.is(tok::l_brace)) {
+      Actions.ActOnFinishFunctionBody(LM.D, 0);
+      return;
     }
-    if (Tok.is(tok::colon)) {
-      ParseConstructorInitializer(LM.D);
-
-      // Error recovery.
-      if (!Tok.is(tok::l_brace)) {
-        Actions.ActOnFinishFunctionBody(LM.D, 0);
-        continue;
-      }
-    } else
-      Actions.ActOnDefaultCtorInitializers(LM.D);
+  } else
+    Actions.ActOnDefaultCtorInitializers(LM.D);
 
-    ParseFunctionStatementBody(LM.D);
+  ParseFunctionStatementBody(LM.D);
 
-    if (Tok.getLocation() != origLoc) {
-      // Due to parsing error, we either went over the cached tokens or
-      // there are still cached tokens left. If it's the latter case skip the
-      // leftover tokens.
-      // Since this is an uncommon situation that should be avoided, use the
-      // expensive isBeforeInTranslationUnit call.
-      if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(),
-                                                          origLoc))
-        while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
-          ConsumeAnyToken();
+  if (Tok.getLocation() != origLoc) {
+    // Due to parsing error, we either went over the cached tokens or
+    // there are still cached tokens left. If it's the latter case skip the
+    // leftover tokens.
+    // Since this is an uncommon situation that should be avoided, use the
+    // expensive isBeforeInTranslationUnit call.
+    if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(),
+                                                        origLoc))
+      while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
+        ConsumeAnyToken();
 
-    }
   }
-
-  for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I)
-    ParseLexedMethodDefs(*Class.NestedClasses[I]);
 }
 
 /// ConsumeAndStoreUntil - Consume and store the token at the passed token

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=116311&r1=116310&r2=116311&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue Oct 12 11:25:54 2010
@@ -1203,9 +1203,8 @@
       if (!LateMethod) {
         // Push this method onto the stack of late-parsed method
         // declarations.
-        getCurrentClass().MethodDecls.push_back(
-                                LateParsedMethodDeclaration(ThisDecl));
-        LateMethod = &getCurrentClass().MethodDecls.back();
+        LateMethod = new LateParsedMethodDeclaration(this, ThisDecl);
+        getCurrentClass().LateParsedDeclarations.push_back(LateMethod);
         LateMethod->TemplateScope = getCurScope()->isTemplateParamScope();
 
         // Add all of the parameters prior to this one (they don't
@@ -1911,8 +1910,8 @@
 /// \brief Deallocate the given parsed class and all of its nested
 /// classes.
 void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) {
-  for (unsigned I = 0, N = Class->NestedClasses.size(); I != N; ++I)
-    DeallocateParsedClasses(Class->NestedClasses[I]);
+  for (unsigned I = 0, N = Class->LateParsedDeclarations.size(); I != N; ++I)
+    delete Class->LateParsedDeclarations[I];
   delete Class;
 }
 
@@ -1938,13 +1937,12 @@
   }
   assert(!ClassStack.empty() && "Missing top-level class?");
 
-  if (Victim->MethodDecls.empty() && Victim->MethodDefs.empty() &&
-      Victim->NestedClasses.empty()) {
+  if (Victim->LateParsedDeclarations.empty()) {
     // The victim is a nested class, but we will not need to perform
     // any processing after the definition of this class since it has
     // no members whose handling was delayed. Therefore, we can just
     // remove this nested class.
-    delete Victim;
+    DeallocateParsedClasses(Victim);
     return;
   }
 
@@ -1952,7 +1950,7 @@
   // after the top-level class is completely defined. Therefore, add
   // it to the list of nested classes within its parent.
   assert(getCurScope()->isClassScope() && "Nested class outside of class scope?");
-  ClassStack.top()->NestedClasses.push_back(Victim);
+  ClassStack.top()->LateParsedDeclarations.push_back(new LateParsedClass(this, Victim));
   Victim->TemplateScope = getCurScope()->getParent()->isTemplateParamScope();
 }
 

Added: cfe/trunk/test/CXX/class/class.mem/p1b.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.mem/p1b.cpp?rev=116311&view=auto
==============================================================================
--- cfe/trunk/test/CXX/class/class.mem/p1b.cpp (added)
+++ cfe/trunk/test/CXX/class/class.mem/p1b.cpp Tue Oct 12 11:25:54 2010
@@ -0,0 +1,46 @@
+// The first run checks that the correct errors are generated,
+// implicitly checking the order of default argument parsing:
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// The second run checks the order of inline method definitions:
+// RUN: not %clang_cc1 -fsyntax-only %s 2> %t
+// RUN: FileCheck %s < %t
+
+class A {
+public:
+  void a1() {
+    B b = B();
+  }
+
+  class B;
+  void a2(B b = B()); // expected-error{{use of default argument to function 'B' that is declared later in class 'B'}}
+
+  void a3(int a = 42);
+
+  // CHEKC: error: use of undeclared identifier 'first'
+  void a4(int a = first); // expected-error{{use of undeclared identifier 'first'}}
+
+  class B {
+  public:
+    B(int b = 42) { // expected-note{{default argument declared here}}
+      A a;
+      a.a3();
+      a.a6();
+    }
+
+    void b1(A a = A()); // expected-error{{use of default argument to function 'A' that is declared later in class 'A'}}
+
+    // CHECK: error: use of undeclared identifier 'second'
+    void b2(int a = second); // expected-error{{use of undeclared identifier 'second'}}
+  };
+
+  void a5() {
+    B b = B();
+  }
+
+  void a6(B b = B());
+
+  A(int a = 42); // expected-note{{default argument declared here}}
+
+  // CHECK: error: use of undeclared identifier 'third'
+  void a7(int a = third); // expected-error{{use of undeclared identifier 'third'}}
+};

Propchange: cfe/trunk/test/CXX/class/class.mem/p1b.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/CXX/class/class.mem/p1b.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/CXX/class/class.mem/p1b.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/test/SemaCXX/default2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/default2.cpp?rev=116311&r1=116310&r2=116311&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/default2.cpp (original)
+++ cfe/trunk/test/SemaCXX/default2.cpp Tue Oct 12 11:25:54 2010
@@ -68,8 +68,11 @@
              Nested* self = this, // expected-error{{invalid use of 'this' outside of a nonstatic member function}}
              int m); // expected-error{{missing default argument on parameter 'm'}}
     static int c;
+    Nested(int i = 42);
   };
 
+  int mem7(Nested n = Nested());
+
   static int b; 
 }; 
 





More information about the cfe-commits mailing list