diff options
author | Francois Pichet <pichet2000@gmail.com> | 2011-05-25 10:19:49 +0000 |
---|---|---|
committer | Francois Pichet <pichet2000@gmail.com> | 2011-05-25 10:19:49 +0000 |
commit | 563a645de82231a55e221fe655b7188bf8369662 (patch) | |
tree | 54d18fbde16c35c24aed5402131ab09238c6d721 /lib/Parse/ParseDeclCXX.cpp | |
parent | d1e015eb441910937c74d489970322a3a3491a67 (diff) |
Add support for Microsoft __if_exists, __if_not_exists extension at class scope.
Example:
typedef int TYPE;
class C {
__if_exists(TYPE) {
TYPE a;
}
__if_not_exists(TYPE) {
this will never be parsed.
}
};
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132052 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index d3b34b922d..5087b92d0b 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/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(); +} |