aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Parse/Parser.h4
-rw-r--r--lib/Parse/ParseDeclCXX.cpp67
-rw-r--r--lib/Parse/Parser.cpp4
-rw-r--r--test/Parser/MicrosoftExtensions.cpp27
4 files changed, 98 insertions, 4 deletions
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<IdentifierInfo *> &Names,
llvm::SmallVectorImpl<ExprTy *> &Constraints,
llvm::SmallVectorImpl<ExprTy *> &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 {