A minor tweak to the new volatile lvalue warning: don't warn on "(void)x", where "x" refers to a local variable. This should silence a useless warning in compiler-rt and other places.

llvm-svn: 157414
This commit is contained in:
Eli Friedman 2012-05-24 21:05:41 +00:00
parent d65dbd8e6a
commit f92f6454ef
2 changed files with 24 additions and 25 deletions

View File

@ -1883,43 +1883,40 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
return true; return true;
} }
case CStyleCastExprClass: { case CStyleCastExprClass: {
// Ignore an explicit cast to void, as long as the operand isn't a // Ignore an explicit cast to void unless the operand is a non-trivial
// volatile lvalue. // volatile lvalue.
const CStyleCastExpr *CE = cast<CStyleCastExpr>(this); const CastExpr *CE = cast<CastExpr>(this);
if (CE->getCastKind() == CK_ToVoid) { if (CE->getCastKind() == CK_ToVoid) {
if (CE->getSubExpr()->isGLValue() && if (CE->getSubExpr()->isGLValue() &&
CE->getSubExpr()->getType().isVolatileQualified()) CE->getSubExpr()->getType().isVolatileQualified()) {
return CE->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, const DeclRefExpr *DRE =
R1, R2, Ctx); dyn_cast<DeclRefExpr>(CE->getSubExpr()->IgnoreParens());
if (!(DRE && isa<VarDecl>(DRE->getDecl()) &&
cast<VarDecl>(DRE->getDecl())->hasLocalStorage())) {
return CE->getSubExpr()->isUnusedResultAWarning(WarnE, Loc,
R1, R2, Ctx);
}
}
return false; return false;
} }
WarnE = this;
Loc = CE->getLParenLoc();
R1 = CE->getSubExpr()->getSourceRange();
return true;
}
case CXXFunctionalCastExprClass: {
// Ignore an explicit cast to void, as long as the operand isn't a
// volatile lvalue.
const CXXFunctionalCastExpr *CE = cast<CXXFunctionalCastExpr>(this);
if (CE->getCastKind() == CK_ToVoid) {
if (CE->getSubExpr()->isGLValue() &&
CE->getSubExpr()->getType().isVolatileQualified())
return CE->getSubExpr()->isUnusedResultAWarning(WarnE, Loc,
R1, R2, Ctx);
return false;
}
// If this is a cast to a constructor conversion, check the operand. // If this is a cast to a constructor conversion, check the operand.
// Otherwise, the result of the cast is unused. // Otherwise, the result of the cast is unused.
if (CE->getCastKind() == CK_ConstructorConversion) if (CE->getCastKind() == CK_ConstructorConversion)
return CE->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); return CE->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
WarnE = this; WarnE = this;
Loc = CE->getTypeBeginLoc(); if (const CXXFunctionalCastExpr *CXXCE =
R1 = CE->getSubExpr()->getSourceRange(); dyn_cast<CXXFunctionalCastExpr>(this)) {
Loc = CXXCE->getTypeBeginLoc();
R1 = CXXCE->getSubExpr()->getSourceRange();
} else {
const CStyleCastExpr *CStyleCE = cast<CStyleCastExpr>(this);
Loc = CStyleCE->getLParenLoc();
R1 = CStyleCE->getSubExpr()->getSourceRange();
}
return true; return true;
} }
case ImplicitCastExprClass: { case ImplicitCastExprClass: {
const CastExpr *ICE = cast<ImplicitCastExpr>(this); const CastExpr *ICE = cast<ImplicitCastExpr>(this);

View File

@ -30,5 +30,7 @@ namespace derefvolatile {
void f(volatile char* x) { void f(volatile char* x) {
*x; // expected-warning {{expression result unused; assign into a variable to force a volatile load}} *x; // expected-warning {{expression result unused; assign into a variable to force a volatile load}}
(void)*x; // expected-warning {{expression result unused; assign into a variable to force a volatile load}} (void)*x; // expected-warning {{expression result unused; assign into a variable to force a volatile load}}
volatile char y = 10;
(void)y; // don't warn here, because it's a common pattern.
} }
} }