From: Francois Pichet Date: Wed, 25 May 2011 10:19:49 +0000 (+0000) Subject: Add support for Microsoft __if_exists, __if_not_exists extension at class scope. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=563a645de82231a55e221fe655b7188bf8369662;p=clang 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 --- diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 0d65f43e90..bb7b61752f 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1310,7 +1310,9 @@ private: StmtResult FuzzyParseMicrosoftAsmStatement(SourceLocation AsmLoc); bool ParseMicrosoftIfExistsCondition(bool& Result); void ParseMicrosoftIfExistsStatement(StmtVector &Stmts); - void ParseMicrosoftIfExistsDeclaration(); + void ParseMicrosoftIfExistsExternalDeclaration(); + void ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, + AccessSpecifier& CurAS); bool ParseAsmOperandsOpt(llvm::SmallVectorImpl &Names, llvm::SmallVectorImpl &Constraints, llvm::SmallVectorImpl &Exprs); 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(); +} diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index a706f439a1..f209723dc0 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -656,7 +656,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::kw___if_exists: case tok::kw___if_not_exists: - ParseMicrosoftIfExistsDeclaration(); + ParseMicrosoftIfExistsExternalDeclaration(); return DeclGroupPtrTy(); default: @@ -1474,7 +1474,7 @@ bool Parser::ParseMicrosoftIfExistsCondition(bool& Result) { return false; } -void Parser::ParseMicrosoftIfExistsDeclaration() { +void Parser::ParseMicrosoftIfExistsExternalDeclaration() { bool Result; if (ParseMicrosoftIfExistsCondition(Result)) return; diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp index adf93b62d1..3a72ea0234 100644 --- a/test/Parser/MicrosoftExtensions.cpp +++ b/test/Parser/MicrosoftExtensions.cpp @@ -168,7 +168,7 @@ __interface MicrosoftInterface { __int64 x7 = __int64(0); - +namespace If_exists_test { class IF_EXISTS { private: @@ -210,6 +210,31 @@ __if_not_exists(IF_EXISTS::Type_not) { int var244; } +class IF_EXISTS_CLASS_TEST { + __if_exists(IF_EXISTS::Type) { + // __if_exists, __if_not_exists can nest + __if_not_exists(IF_EXISTS::Type_not) { + int var123; + } + int var23; + } + + __if_exists(IF_EXISTS::Type_not) { + this wont compile. + } + + __if_not_exists(IF_EXISTS::Type) { + this wont compile. + } + + __if_not_exists(IF_EXISTS::Type_not) { + int var244; + } +}; + +} + + int __identifier(generic) = 3; class inline_definition_pure_spec {