fix some problems handling stmtexprs with labels (PR2374), and

improve 'expression unused' diagnostics for stmtexprs.

llvm-svn: 54098
This commit is contained in:
Chris Lattner 2008-07-26 19:51:01 +00:00
parent 06afbebbdd
commit 944d306371
3 changed files with 31 additions and 7 deletions

View File

@ -347,10 +347,18 @@ bool Expr::hasLocalSideEffect() const {
return true;
case ObjCMessageExprClass:
return true;
case StmtExprClass:
// TODO: check the inside of the statement expression
return true;
case StmtExprClass: {
// Statement exprs don't logically have side effects themselves, but are
// sometimes used in macros in ways that give them a type that is unused.
// For example ({ blah; foo(); }) will end up with a type if foo has a type.
// however, if the result of the stmt expr is dead, we don't want to emit a
// warning.
const CompoundStmt *CS = cast<StmtExpr>(this)->getSubStmt();
if (!CS->body_empty())
if (const Expr *E = dyn_cast<Expr>(CS->body_back()))
return E->hasLocalSideEffect();
return false;
}
case CastExprClass:
// If this is a cast to void, check the operand. Otherwise, the result of
// the cast is unused.

View File

@ -2334,9 +2334,15 @@ Sema::ExprResult Sema::ActOnStmtExpr(SourceLocation LPLoc, StmtTy *substmt,
// as the type of the stmtexpr.
QualType Ty = Context.VoidTy;
if (!Compound->body_empty())
if (Expr *LastExpr = dyn_cast<Expr>(Compound->body_back()))
if (!Compound->body_empty()) {
Stmt *LastStmt = Compound->body_back();
// If LastStmt is a label, skip down through into the body.
while (LabelStmt *Label = dyn_cast<LabelStmt>(LastStmt))
LastStmt = Label->getSubStmt();
if (Expr *LastExpr = dyn_cast<Expr>(LastStmt))
Ty = LastExpr->getType();
}
return new StmtExpr(Compound, Ty, LPLoc, RPLoc);
}

View File

@ -1,4 +1,4 @@
// RUN: clang %s -fsyntax-only
// RUN: clang %s -fsyntax-only -verify
typedef unsigned __uint32_t;
@ -10,3 +10,13 @@ __extension__ ({ register __uint32_t __X = (x); \
int test(int _x) {
return (__byte_swap_int_var(_x));
}
// PR2374
int test2() { return ({L:5;}); }
int test3() { return ({ {5;} }); } // expected-error {{incompatible type returning 'void', expected 'int'}}\
// expected-warning {{expression result unused}}
int test4() { return ({ ({5;}); }); }
int test5() { return ({L1: L2: L3: 5;}); }
int test6() { return ({5;}); }
void test7() { ({5;}); } // expected-warning {{expression result unused}}