diff options
Diffstat (limited to 'clang/lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index d3b34b922d8..5087b92d0b3 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1929,6 +1929,12 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { // Each iteration of this loop reads one member-declaration. + if (getLang().Microsoft && (Tok.is(tok::kw___if_exists) || + Tok.is(tok::kw___if_not_exists))) { + ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS); + continue; + } + // Check for extraneous top-level semicolon. if (Tok.is(tok::semi)) { Diag(Tok, diag::ext_extra_struct_semi) @@ -2528,3 +2534,64 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs, ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); } } + +void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, + AccessSpecifier& CurAS) { + bool Result; + if (ParseMicrosoftIfExistsCondition(Result)) + return; + + if (Tok.isNot(tok::l_brace)) { + Diag(Tok, diag::err_expected_lbrace); + return; + } + ConsumeBrace(); + + // Condition is false skip all inside the {}. + if (!Result) { + SkipUntil(tok::r_brace, false); + return; + } + + // Condition is true, parse the declaration. + while (Tok.isNot(tok::r_brace)) { + + // __if_exists, __if_not_exists can nest. + if ((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists))) { + ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS); + continue; + } + + // Check for extraneous top-level semicolon. + if (Tok.is(tok::semi)) { + Diag(Tok, diag::ext_extra_struct_semi) + << DeclSpec::getSpecifierName((DeclSpec::TST)TagType) + << FixItHint::CreateRemoval(Tok.getLocation()); + ConsumeToken(); + continue; + } + + AccessSpecifier AS = getAccessSpecifierIfPresent(); + if (AS != AS_none) { + // Current token is a C++ access specifier. + CurAS = AS; + SourceLocation ASLoc = Tok.getLocation(); + ConsumeToken(); + if (Tok.is(tok::colon)) + Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation()); + else + Diag(Tok, diag::err_expected_colon); + ConsumeToken(); + continue; + } + + // Parse all the comma separated declarators. + ParseCXXClassMemberDeclaration(CurAS); + } + + if (Tok.isNot(tok::r_brace)) { + Diag(Tok, diag::err_expected_rbrace); + return; + } + ConsumeBrace(); +} |