]> granicus.if.org Git - clang/commitdiff
Add support for Microsoft __if_exists, __if_not_exists extension at class scope.
authorFrancois Pichet <pichet2000@gmail.com>
Wed, 25 May 2011 10:19:49 +0000 (10:19 +0000)
committerFrancois Pichet <pichet2000@gmail.com>
Wed, 25 May 2011 10:19:49 +0000 (10:19 +0000)
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

include/clang/Parse/Parser.h
lib/Parse/ParseDeclCXX.cpp
lib/Parse/Parser.cpp
test/Parser/MicrosoftExtensions.cpp

index 0d65f43e907f341cc962f1471ce8db33e6362e48..bb7b61752fa36defe1d18797ae6a7600712ec394 100644 (file)
@@ -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);
index d3b34b922d879ffb63d6e91f47af3fbf10bb99e2..5087b92d0b356282ffd5310107e5648c26431327 100644 (file)
@@ -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();
+}
index a706f439a1f8a8d2c9cf106c3625bdc49b065ce7..f209723dc063ed98e7ab43313fb584fa84d84588 100644 (file)
@@ -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;
index adf93b62d1ab2446ad9257202937abe1b487a0a7..3a72ea0234c92c4f3af59f586771ed7fe346e1b2 100644 (file)
@@ -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 {