[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