diff options
author | Douglas Gregor <dgregor@apple.com> | 2008-11-05 04:29:56 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2008-11-05 04:29:56 +0000 |
commit | 7ad8390f7992ab7f19b1460c5f0b9d96f165c4e9 (patch) | |
tree | 93d1b7ba4d514152f8dc77e32c6cc1c80a746e0d /lib/Parse/ParseDeclCXX.cpp | |
parent | e839b15d7d18c3f63ce0aea885d704ef663a05e9 (diff) |
Initial implementation of parsing, semantic analysis, and AST-building
for constructor initializations, e.g.,
class A { };
class B : public A {
int m;
public:
B() : A(), m(17) { };
};
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58749 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 97 |
1 files changed, 96 insertions, 1 deletions
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 7d03c59113..57fa193e75 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -435,7 +435,8 @@ Parser::DeclTy *Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { } // function-definition: - if (Tok.is(tok::l_brace)) { + if (Tok.is(tok::l_brace) + || (DeclaratorInfo.isFunctionDeclarator() && Tok.is(tok::colon))) { if (!DeclaratorInfo.isFunctionDeclarator()) { Diag(Tok, diag::err_func_def_no_params); ConsumeBrace(); @@ -638,3 +639,97 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, Actions.ActOnFinishCXXClassDef(TagDecl); } + +/// ParseConstructorInitializer - Parse a C++ constructor initializer, +/// which explicitly initializes the members or base classes of a +/// class (C++ [class.base.init]). For example, the three initializers +/// after the ':' in the Derived constructor below: +/// +/// @code +/// class Base { }; +/// class Derived : Base { +/// int x; +/// float f; +/// public: +/// Derived(float f) : Base(), x(17), f(f) { } +/// }; +/// @endcode +/// +/// [C++] ctor-initializer: +/// ':' mem-initializer-list +/// +/// [C++] mem-initializer-list: +/// mem-initializer +/// mem-initializer , mem-initializer-list +void Parser::ParseConstructorInitializer(DeclTy *ConstructorDecl) { + assert(Tok.is(tok::colon) && "Constructor initializer always starts with ':'"); + + SourceLocation ColonLoc = ConsumeToken(); + + llvm::SmallVector<MemInitTy*, 4> MemInitializers; + + do { + MemInitResult MemInit = ParseMemInitializer(ConstructorDecl); + if (!MemInit.isInvalid) + MemInitializers.push_back(MemInit.Val); + + if (Tok.is(tok::comma)) + ConsumeToken(); + else if (Tok.is(tok::l_brace)) + break; + else { + // Skip over garbage, until we get to '{'. Don't eat the '{'. + SkipUntil(tok::l_brace, true, true); + break; + } + } while (true); + + Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc, + &MemInitializers[0], MemInitializers.size()); +} + +/// ParseMemInitializer - Parse a C++ member initializer, which is +/// part of a constructor initializer that explicitly initializes one +/// member or base class (C++ [class.base.init]). See +/// ParseConstructorInitializer for an example. +/// +/// [C++] mem-initializer: +/// mem-initializer-id '(' expression-list[opt] ')' +/// +/// [C++] mem-initializer-id: +/// '::'[opt] nested-name-specifier[opt] class-name +/// identifier +Parser::MemInitResult Parser::ParseMemInitializer(DeclTy *ConstructorDecl) { + // FIXME: parse '::'[opt] nested-name-specifier[opt] + + if (Tok.isNot(tok::identifier)) { + Diag(Tok.getLocation(), diag::err_expected_member_or_base_name); + return true; + } + + // Get the identifier. This may be a member name or a class name, + // but we'll let the semantic analysis determine which it is. + IdentifierInfo *II = Tok.getIdentifierInfo(); + SourceLocation IdLoc = ConsumeToken(); + + // Parse the '('. + if (Tok.isNot(tok::l_paren)) { + Diag(Tok.getLocation(), diag::err_expected_lparen); + return true; + } + SourceLocation LParenLoc = ConsumeParen(); + + // Parse the optional expression-list. + ExprListTy ArgExprs; + CommaLocsTy CommaLocs; + if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) { + SkipUntil(tok::r_paren); + return true; + } + + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + + return Actions.ActOnMemInitializer(ConstructorDecl, CurScope, II, IdLoc, + LParenLoc, &ArgExprs[0], ArgExprs.size(), + &CommaLocs[0], RParenLoc); +} |