[cfe-commits] r146447 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseInit.cpp test/Parser/MicrosoftExtensions.cpp test/SemaTemplate/ms-if-exists.cpp

Francois Pichet pichet2000 at gmail.com
Mon Dec 12 15:24:39 PST 2011


Author: fpichet
Date: Mon Dec 12 17:24:39 2011
New Revision: 146447

URL: http://llvm.org/viewvc/llvm-project?rev=146447&view=rev
Log:
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.

Modified:
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseInit.cpp
    cfe/trunk/test/Parser/MicrosoftExtensions.cpp
    cfe/trunk/test/SemaTemplate/ms-if-exists.cpp

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=146447&r1=146446&r2=146447&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Dec 12 17:24:39 2011
@@ -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);

Modified: cfe/trunk/lib/Parse/ParseInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseInit.cpp?rev=146447&r1=146446&r2=146447&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseInit.cpp (original)
+++ cfe/trunk/lib/Parse/ParseInit.cpp Mon Dec 12 17:24:39 2011
@@ -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;
+}

Modified: cfe/trunk/test/Parser/MicrosoftExtensions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/MicrosoftExtensions.cpp?rev=146447&r1=146446&r2=146447&view=diff
==============================================================================
--- cfe/trunk/test/Parser/MicrosoftExtensions.cpp (original)
+++ cfe/trunk/test/Parser/MicrosoftExtensions.cpp Mon Dec 12 17:24:39 2011
@@ -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

Modified: cfe/trunk/test/SemaTemplate/ms-if-exists.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/ms-if-exists.cpp?rev=146447&r1=146446&r2=146447&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/ms-if-exists.cpp (original)
+++ cfe/trunk/test/SemaTemplate/ms-if-exists.cpp Mon Dec 12 17:24:39 2011
@@ -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}}





More information about the cfe-commits mailing list