Add support for Microsoft __if_exists and __if_not_exists construct inside function definition.
Allow to include or exclude code depending on if a symbol exists or not. Just like a #ifdef but for C/C++ symbols.

More doc: http://msdn.microsoft.com/en-us/library/x7wy9xh3(v=VS.100).aspx

Support at class and namespace scopes will be added later.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131014 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index f0ab531..12ab5e2 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -741,6 +741,12 @@
       continue;
     }
 
+    if (getLang().Microsoft && (Tok.is(tok::kw___if_exists) ||
+        Tok.is(tok::kw___if_not_exists))) {
+      ParseMicrosoftIfExistsStatement(Stmts);
+      continue;
+    }
+
     StmtResult R;
     if (Tok.isNot(tok::kw___extension__)) {
       R = ParseStatementOrDeclaration(Stmts, false);
@@ -2000,3 +2006,67 @@
 
   return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.take());
 }
+
+void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
+  assert((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists)) &&
+         "Expected '__if_exists' or '__if_not_exists'");
+  Token Condition = Tok;
+  SourceLocation IfExistsLoc = ConsumeToken();
+
+  SourceLocation LParenLoc = Tok.getLocation();
+  if (Tok.isNot(tok::l_paren)) {
+    Diag(Tok, diag::err_expected_lparen_after) << IfExistsLoc;
+    SkipUntil(tok::semi);
+    return;
+  }
+  ConsumeParen(); // eat the '('.
+  
+  // Parse nested-name-specifier.
+  CXXScopeSpec SS;
+  ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+
+  // Check nested-name specifier.
+  if (SS.isInvalid()) {
+    SkipUntil(tok::semi);
+    return;
+  }
+
+  // Parse the unqualified-id. 
+  UnqualifiedId Name;
+  if (ParseUnqualifiedId(SS, false, true, true, ParsedType(), Name)) {
+    SkipUntil(tok::semi);
+    return;
+  }
+
+  if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid())
+    return;
+
+  if (Tok.isNot(tok::l_brace)) {
+    Diag(Tok, diag::err_expected_lbrace);
+    return;
+  }
+  ConsumeBrace();
+
+  // Check if the symbol exists.
+  bool Exist = Actions.CheckMicrosoftIfExistsSymbol(SS, Name);
+
+  // If the condition is false skip the tokens until the '}'
+  if ((Condition.is(tok::kw___if_exists) && !Exist) ||
+      (Condition.is(tok::kw___if_not_exists) && Exist)) {
+    SkipUntil(tok::r_brace, false);
+    return;
+  }
+
+  // Condition is true, parse the statements.
+  while (Tok.isNot(tok::r_brace)) {
+    StmtResult R = ParseStatementOrDeclaration(Stmts, false);
+    if (R.isUsable())
+      Stmts.push_back(R.release());
+  }
+
+  if (Tok.isNot(tok::r_brace)) {
+    Diag(Tok, diag::err_expected_rbrace);
+    return;
+  }
+  ConsumeBrace();
+}