[PATCH] D57086: Ignore trailing NullStmts in StmtExprs for GCC compatibility

Dominic Ferreira via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 22 22:50:27 PST 2019


domdom created this revision.
domdom added reviewers: lattner, rsmith.
Herald added a subscriber: cfe-commits.

Ignore trailing NullStmts in compound expressions when determining the result type and value. This is to match the GCC behavior which ignores semicolons at the end of compound expressions.


Repository:
  rC Clang

https://reviews.llvm.org/D57086

Files:
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/statements.c


Index: clang/test/Sema/statements.c
===================================================================
--- clang/test/Sema/statements.c
+++ clang/test/Sema/statements.c
@@ -119,3 +119,17 @@
     SIZE = sizeof(({unsigned long __ptr; __ptr;}))
   };
 }
+
+// GCC ignores empty statements at the end of compound expressions where the
+// result type is concerned.
+void test13() {
+  int a;
+  a = ({1;});
+  a = ({1;;});
+  a = ({int x = 1; (void)x;}); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+  a = ({int x = 1; (void)x;;}); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+}
+
+void test14() { return ({}); }
+void test15() { return ({;;;;}); }
+void test16() { return ({test:;;}); }
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -13320,11 +13320,22 @@
   // More semantic analysis is needed.
 
   // If there are sub-stmts in the compound stmt, take the type of the last one
-  // as the type of the stmtexpr.
+  // as the type of the stmtexpr. For GCC compatibility this excludes trailing
+  // NullStmts
   QualType Ty = Context.VoidTy;
   bool StmtExprMayBindToTemp = false;
   if (!Compound->body_empty()) {
-    Stmt *LastStmt = Compound->body_back();
+    // GCC ignores empty statements at the end of compound expressions
+    // i.e. ({ 5;;; })
+    //           ^^ ignored
+    // This code skips past these NullStmts
+    Stmt *LastStmt = nullptr;
+    for (Stmt *I : llvm::make_range(Compound->body_rbegin(),
+                                    Compound->body_rend())) {
+      LastStmt = I;
+      if (!isa<NullStmt>(LastStmt))
+        break;
+    }
     LabelStmt *LastLabelStmt = nullptr;
     // If LastStmt is a label, skip down through into the body.
     while (LabelStmt *Label = dyn_cast<LabelStmt>(LastStmt)) {
Index: clang/lib/Parse/ParseStmt.cpp
===================================================================
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -959,10 +959,18 @@
 
 bool Parser::isExprValueDiscarded() {
   if (Actions.isCurCompoundStmtAStmtExpr()) {
-    // Look to see if the next two tokens close the statement expression;
-    // if so, this expression statement is the last statement in a
-    // statment expression.
-    return Tok.isNot(tok::r_brace) || NextToken().isNot(tok::r_paren);
+    // For gcc compatibility we skip past NullStmts
+    int lookahead = 0;
+    while(GetLookAheadToken(lookahead).is(tok::semi)) {
+      lookahead++;
+    }
+
+    // Then look to see if the next two tokens close the statement expression;
+    // if so, this expression statement is the last statement in a statment
+    // expression.
+
+    return GetLookAheadToken(lookahead).isNot(tok::r_brace) ||
+           GetLookAheadToken(lookahead + 1).isNot(tok::r_paren);
   }
   return true;
 }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D57086.183037.patch
Type: text/x-patch
Size: 2937 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20190123/c5f8e2e3/attachment.bin>


More information about the cfe-commits mailing list