Skip to content

Commit 91c2333

Browse files
KaiYGtclin914
andcommitted
Revert "Ignore trailing NullStmts in StmtExprs for GCC compatibility."
This reverts commit b1e511b. #160243 Reverting because the GCC C front end is incorrect. Co-authored-by: Jim Lin <[email protected]>
1 parent d2625a4 commit 91c2333

File tree

11 files changed

+42
-127
lines changed

11 files changed

+42
-127
lines changed

clang/include/clang/AST/Stmt.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,26 +1831,6 @@ class CompoundStmt final
18311831
return const_reverse_body_iterator(body_begin());
18321832
}
18331833

1834-
// Get the Stmt that StmtExpr would consider to be the result of this
1835-
// compound statement. This is used by StmtExpr to properly emulate the GCC
1836-
// compound expression extension, which ignores trailing NullStmts when
1837-
// getting the result of the expression.
1838-
// i.e. ({ 5;;; })
1839-
// ^^ ignored
1840-
// If we don't find something that isn't a NullStmt, just return the last
1841-
// Stmt.
1842-
Stmt *getStmtExprResult() {
1843-
for (auto *B : llvm::reverse(body())) {
1844-
if (!isa<NullStmt>(B))
1845-
return B;
1846-
}
1847-
return body_back();
1848-
}
1849-
1850-
const Stmt *getStmtExprResult() const {
1851-
return const_cast<CompoundStmt *>(this)->getStmtExprResult();
1852-
}
1853-
18541834
SourceLocation getBeginLoc() const { return LBraceLoc; }
18551835
SourceLocation getEndLoc() const { return RBraceLoc; }
18561836

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4157,7 +4157,7 @@ bool Compiler<Emitter>::VisitStmtExpr(const StmtExpr *E) {
41574157
StmtExprScope<Emitter> SS(this);
41584158

41594159
const CompoundStmt *CS = E->getSubStmt();
4160-
const Stmt *Result = CS->getStmtExprResult();
4160+
const Stmt *Result = CS->body_back();
41614161
for (const Stmt *S : CS->body()) {
41624162
if (S != Result) {
41634163
if (!this->visitStmt(S))

clang/lib/AST/ComputeDependence.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ ExprDependence clang::computeDependence(StmtExpr *E, unsigned TemplateDepth) {
178178
auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
179179
// Propagate dependence of the result.
180180
if (const auto *CompoundExprResult =
181-
dyn_cast_or_null<ValueStmt>(E->getSubStmt()->getStmtExprResult()))
181+
dyn_cast_or_null<ValueStmt>(E->getSubStmt()->body_back()))
182182
if (const Expr *ResultExpr = CompoundExprResult->getExprStmt())
183183
D |= ResultExpr->getDependence();
184184
// Note: we treat a statement-expression in a dependent context as always

clang/lib/CodeGen/CGStmt.cpp

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -582,48 +582,45 @@ CodeGenFunction::EmitCompoundStmtWithoutScope(const CompoundStmt &S,
582582
bool GetLast,
583583
AggValueSlot AggSlot) {
584584

585-
const Stmt *ExprResult = S.getStmtExprResult();
586-
assert((!GetLast || (GetLast && ExprResult)) &&
587-
"If GetLast is true then the CompoundStmt must have a StmtExprResult");
585+
for (CompoundStmt::const_body_iterator I = S.body_begin(),
586+
E = S.body_end() - GetLast;
587+
I != E; ++I)
588+
EmitStmt(*I);
588589

589590
Address RetAlloca = Address::invalid();
590-
591-
for (auto *CurStmt : S.body()) {
592-
if (GetLast && ExprResult == CurStmt) {
593-
// We have to special case labels here. They are statements, but when put
594-
// at the end of a statement expression, they yield the value of their
595-
// subexpression. Handle this by walking through all labels we encounter,
596-
// emitting them before we evaluate the subexpr.
597-
// Similar issues arise for attributed statements.
598-
while (!isa<Expr>(ExprResult)) {
599-
if (const auto *LS = dyn_cast<LabelStmt>(ExprResult)) {
600-
EmitLabel(LS->getDecl());
601-
ExprResult = LS->getSubStmt();
602-
} else if (const auto *AS = dyn_cast<AttributedStmt>(ExprResult)) {
603-
// FIXME: Update this if we ever have attributes that affect the
604-
// semantics of an expression.
605-
ExprResult = AS->getSubStmt();
606-
} else {
607-
llvm_unreachable("unknown value statement");
608-
}
591+
if (GetLast) {
592+
// We have to special case labels here. They are statements, but when put
593+
// at the end of a statement expression, they yield the value of their
594+
// subexpression. Handle this by walking through all labels we encounter,
595+
// emitting them before we evaluate the subexpr.
596+
// Similar issues arise for attributed statements.
597+
const Stmt *LastStmt = S.body_back();
598+
while (!isa<Expr>(LastStmt)) {
599+
if (const auto *LS = dyn_cast<LabelStmt>(LastStmt)) {
600+
EmitLabel(LS->getDecl());
601+
LastStmt = LS->getSubStmt();
602+
} else if (const auto *AS = dyn_cast<AttributedStmt>(LastStmt)) {
603+
// FIXME: Update this if we ever have attributes that affect the
604+
// semantics of an expression.
605+
LastStmt = AS->getSubStmt();
606+
} else {
607+
llvm_unreachable("unknown value statement");
609608
}
609+
}
610610

611-
EnsureInsertPoint();
611+
EnsureInsertPoint();
612612

613-
const Expr *E = cast<Expr>(ExprResult);
614-
QualType ExprTy = E->getType();
615-
if (hasAggregateEvaluationKind(ExprTy)) {
616-
EmitAggExpr(E, AggSlot);
617-
} else {
618-
// We can't return an RValue here because there might be cleanups at
619-
// the end of the StmtExpr. Because of that, we have to emit the result
620-
// here into a temporary alloca.
621-
RetAlloca = CreateMemTemp(ExprTy);
622-
EmitAnyExprToMem(E, RetAlloca, Qualifiers(),
623-
/*IsInit*/ false);
624-
}
613+
const Expr *E = cast<Expr>(LastStmt);
614+
QualType ExprTy = E->getType();
615+
if (hasAggregateEvaluationKind(ExprTy)) {
616+
EmitAggExpr(E, AggSlot);
625617
} else {
626-
EmitStmt(CurStmt);
618+
// We can't return an RValue here because there might be cleanups at
619+
// the end of the StmtExpr. Because of that, we have to emit the result
620+
// here into a temporary alloca.
621+
RetAlloca = CreateMemTemp(ExprTy);
622+
EmitAnyExprToMem(E, RetAlloca, Qualifiers(),
623+
/*IsInit*/ false);
627624
}
628625
}
629626

clang/lib/Parse/ParseStmt.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,16 +1079,10 @@ bool Parser::ConsumeNullStmt(StmtVector &Stmts) {
10791079
StmtResult Parser::handleExprStmt(ExprResult E, ParsedStmtContext StmtCtx) {
10801080
bool IsStmtExprResult = false;
10811081
if ((StmtCtx & ParsedStmtContext::InStmtExpr) != ParsedStmtContext()) {
1082-
// For GCC compatibility we skip past NullStmts.
1083-
unsigned LookAhead = 0;
1084-
while (GetLookAheadToken(LookAhead).is(tok::semi)) {
1085-
++LookAhead;
1086-
}
1087-
// Then look to see if the next two tokens close the statement expression;
1088-
// if so, this expression statement is the last statement in a statement
1089-
// expression.
1090-
IsStmtExprResult = GetLookAheadToken(LookAhead).is(tok::r_brace) &&
1091-
GetLookAheadToken(LookAhead + 1).is(tok::r_paren);
1082+
// Look ahead to see if the next two tokens close the statement expression;
1083+
// if so, this expression statement is the last statement in a
1084+
// statment expression.
1085+
IsStmtExprResult = Tok.is(tok::r_brace) && NextToken().is(tok::r_paren);
10921086
}
10931087

10941088
if (IsStmtExprResult)

clang/lib/Sema/SemaExpr.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16185,9 +16185,7 @@ ExprResult Sema::BuildStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
1618516185
QualType Ty = Context.VoidTy;
1618616186
bool StmtExprMayBindToTemp = false;
1618716187
if (!Compound->body_empty()) {
16188-
// For GCC compatibility we get the last Stmt excluding trailing NullStmts.
16189-
if (const auto *LastStmt =
16190-
dyn_cast<ValueStmt>(Compound->getStmtExprResult())) {
16188+
if (const auto *LastStmt = dyn_cast<ValueStmt>(Compound->body_back())) {
1619116189
if (const Expr *Value = LastStmt->getExprStmt()) {
1619216190
StmtExprMayBindToTemp = true;
1619316191
Ty = Value->getType();

clang/lib/Sema/TreeTransform.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8080,14 +8080,13 @@ TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S,
80808080
getSema().resetFPOptions(
80818081
S->getStoredFPFeatures().applyOverrides(getSema().getLangOpts()));
80828082

8083-
const Stmt *ExprResult = S->getStmtExprResult();
80848083
bool SubStmtInvalid = false;
80858084
bool SubStmtChanged = false;
80868085
SmallVector<Stmt*, 8> Statements;
80878086
for (auto *B : S->body()) {
80888087
StmtResult Result = getDerived().TransformStmt(
8089-
B, IsStmtExpr && B == ExprResult ? StmtDiscardKind::StmtExprResult
8090-
: StmtDiscardKind::Discarded);
8088+
B, IsStmtExpr && B == S->body_back() ? StmtDiscardKind::StmtExprResult
8089+
: StmtDiscardKind::Discarded);
80918090

80928091
if (Result.isInvalid()) {
80938092
// Immediately fail if this was a DeclStmt, since it's very

clang/test/AST/ast-dump-stmt.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -399,14 +399,4 @@ void TestMiscStmts(void) {
399399
// CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:13> 'int' 10
400400
// CHECK-NEXT: ImplicitCastExpr
401401
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:17> 'int' lvalue Var 0x{{[^ ]*}} 'a' 'int'
402-
({int a = 10; a;;; });
403-
// CHECK-NEXT: StmtExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:23> 'int'
404-
// CHECK-NEXT: CompoundStmt
405-
// CHECK-NEXT: DeclStmt
406-
// CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:5, col:13> col:9 used a 'int' cinit
407-
// CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:13> 'int' 10
408-
// CHECK-NEXT: ImplicitCastExpr
409-
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:17> 'int' lvalue Var 0x{{[^ ]*}} 'a' 'int'
410-
// CHECK-NEXT: NullStmt
411-
// CHECK-NEXT: NullStmt
412402
}

clang/test/CodeGen/exprs.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,3 @@ void f18(void) {
193193
}
194194
// CHECK-LABEL: define{{.*}} void @f18()
195195
// CHECK: call i32 @returns_int()
196-
197-
// Ensure the right stmt is returned
198-
int f19(void) {
199-
return ({ 3;;4;; });
200-
}
201-
// CHECK-LABEL: define{{.*}} i32 @f19()
202-
// CHECK: [[T:%.*]] = alloca i32
203-
// CHECK: store i32 4, ptr [[T]]
204-
// CHECK: [[L:%.*]] = load i32, ptr [[T]]
205-
// CHECK: ret i32 [[L]]

clang/test/Sema/statements.c

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -118,21 +118,3 @@ void test_pr22849(void) {
118118
SIZE = sizeof(({unsigned long __ptr; __ptr;}))
119119
};
120120
}
121-
122-
// GCC ignores empty statements at the end of compound expressions where the
123-
// result type is concerned.
124-
void test13(void) {
125-
int a;
126-
a = ({ 1; });
127-
a = ({1;; });
128-
a = ({int x = 1; (void)x; }); // expected-error {{assigning to 'int' from incompatible type 'void'}}
129-
a = ({int x = 1; (void)x;; }); // expected-error {{assigning to 'int' from incompatible type 'void'}}
130-
}
131-
132-
void test14(void) { return ({}); }
133-
void test15(void) {
134-
return ({;;;; });
135-
}
136-
void test16(void) {
137-
return ({test:;; });
138-
}

0 commit comments

Comments
 (0)