Implement the Microsoft __if_exists/if_not_exists extension in initializer-list.
Necessary to parse Microsoft ATL code.

Example: 
  int array[] = {
    0, 
    __if_exists(CLASS::Type) {2, }
    3
  };

will declare an array of 2 or 3 elements depending on if CLASS::Type exists or not.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146447 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index a608006..07d21bf 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1548,6 +1548,8 @@
   void ParseMicrosoftIfExistsExternalDeclaration();
   void ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
                                               AccessSpecifier& CurAS);
+  bool ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
+                                              bool &InitExprsOk);
   bool ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
                            SmallVectorImpl<Expr *> &Constraints,
                            SmallVectorImpl<Expr *> &Exprs);
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
index 33abc93..ba7a024 100644
--- a/lib/Parse/ParseInit.cpp
+++ b/lib/Parse/ParseInit.cpp
@@ -340,6 +340,17 @@
   bool InitExprsOk = true;
 
   while (1) {
+    // Handle Microsoft __if_exists/if_not_exists if necessary.
+    if (getLang().MicrosoftExt && (Tok.is(tok::kw___if_exists) ||
+        Tok.is(tok::kw___if_not_exists))) {
+      if (ParseMicrosoftIfExistsBraceInitializer(InitExprs, InitExprsOk)) {
+        if (Tok.isNot(tok::comma)) break;
+        ConsumeToken();
+      }
+      if (Tok.is(tok::r_brace)) break;
+      continue;
+    }
+
     // Parse: designation[opt] initializer
 
     // If we know that this cannot be a designation, just parse the nested
@@ -392,3 +403,66 @@
   return ExprError(); // an error occurred.
 }
 
+
+// Return true if a comma (or closing brace) is necessary after the
+// __if_exists/if_not_exists statement.
+bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
+                                                    bool &InitExprsOk) {
+  bool trailingComma = false;
+  IfExistsCondition Result;
+  if (ParseMicrosoftIfExistsCondition(Result))
+    return false;
+  
+  BalancedDelimiterTracker Braces(*this, tok::l_brace);
+  if (Braces.consumeOpen()) {
+    Diag(Tok, diag::err_expected_lbrace);
+    return false;
+  }
+
+  switch (Result.Behavior) {
+  case IEB_Parse:
+    // Parse the declarations below.
+    break;
+        
+  case IEB_Dependent:
+    Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists)
+      << Result.IsIfExists;
+    // Fall through to skip.
+      
+  case IEB_Skip:
+    Braces.skipToEnd();
+    return false;
+  }
+
+  while (Tok.isNot(tok::eof)) {
+    trailingComma = false;
+    // If we know that this cannot be a designation, just parse the nested
+    // initializer directly.
+    ExprResult SubElt;
+    if (MayBeDesignationStart(Tok.getKind(), PP))
+      SubElt = ParseInitializerWithPotentialDesignator();
+    else
+      SubElt = ParseInitializer();
+
+    if (Tok.is(tok::ellipsis))
+      SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken());
+    
+    // If we couldn't parse the subelement, bail out.
+    if (!SubElt.isInvalid())
+      InitExprs.push_back(SubElt.release());
+    else
+      InitExprsOk = false;
+
+    if (Tok.is(tok::comma)) {
+      ConsumeToken();
+      trailingComma = true;
+    }
+
+    if (Tok.is(tok::r_brace))
+      break;
+  }
+
+  Braces.consumeClose();
+
+  return !trailingComma;
+}
diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp
index 0c5459c..89394c3 100644
--- a/test/Parser/MicrosoftExtensions.cpp
+++ b/test/Parser/MicrosoftExtensions.cpp
@@ -215,6 +215,35 @@
   int var244;
 }
 
+int __if_exists_init_list() {
+
+  int array1[] = {

+    0, 

+    __if_exists(IF_EXISTS::Type) {2, }

+    3

+  };

+
+  int array2[] = {

+    0, 

+    __if_exists(IF_EXISTS::Type_not) { this wont compile }

+    3

+  };

+

+  int array3[] = {

+    0, 

+    __if_not_exists(IF_EXISTS::Type_not) {2, }

+    3

+  };

+
+  int array4[] = {

+    0, 

+    __if_not_exists(IF_EXISTS::Type) { this wont compile }

+    3

+  };

+
+}
+
+
 class IF_EXISTS_CLASS_TEST {
   __if_exists(IF_EXISTS::Type) {
     // __if_exists, __if_not_exists can nest
diff --git a/test/SemaTemplate/ms-if-exists.cpp b/test/SemaTemplate/ms-if-exists.cpp
index 8ac4e24..04f4a63 100644
--- a/test/SemaTemplate/ms-if-exists.cpp
+++ b/test/SemaTemplate/ms-if-exists.cpp
@@ -47,6 +47,12 @@
     int *i = t; // expected-error{{no viable conversion from 'HasFoo' to 'int *'}}
     { }
   }
+
+  int array2[] = {

+    0, 

+    __if_exists(T::bar) {2, }// expected-warning{{dependent __if_exists declarations are ignored}}

+    3

+  };

 }
 
 template void f(HasFoo); // expected-note{{in instantiation of function template specialization 'f<HasFoo>' requested here}}