Refine volatile handling, specifically, we must have the canonical
type to look at the volatile specifier. I found these all from just
hand auditing the code.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85967 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 265823e..a8ea752 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -698,7 +698,7 @@
/// with location to warn on and the source range[s] to report with the
/// warning.
bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
- SourceRange &R2) const {
+ SourceRange &R2, ASTContext &Ctx) const {
// Don't warn if the expr is type dependent. The type could end up
// instantiating to void.
if (isTypeDependent())
@@ -711,7 +711,7 @@
return true;
case ParenExprClass:
return cast<ParenExpr>(this)->getSubExpr()->
- isUnusedResultAWarning(Loc, R1, R2);
+ isUnusedResultAWarning(Loc, R1, R2, Ctx);
case UnaryOperatorClass: {
const UnaryOperator *UO = cast<UnaryOperator>(this);
@@ -724,17 +724,18 @@
return false; // Not a warning.
case UnaryOperator::Deref:
// Dereferencing a volatile pointer is a side-effect.
- if (getType().isVolatileQualified())
+ if (Ctx.getCanonicalType(getType()).isVolatileQualified())
return false;
break;
case UnaryOperator::Real:
case UnaryOperator::Imag:
// accessing a piece of a volatile complex is a side-effect.
- if (UO->getSubExpr()->getType().isVolatileQualified())
+ if (Ctx.getCanonicalType(UO->getSubExpr()->getType())
+ .isVolatileQualified())
return false;
break;
case UnaryOperator::Extension:
- return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx);
}
Loc = UO->getOperatorLoc();
R1 = UO->getSubExpr()->getSourceRange();
@@ -744,8 +745,8 @@
const BinaryOperator *BO = cast<BinaryOperator>(this);
// Consider comma to have side effects if the LHS or RHS does.
if (BO->getOpcode() == BinaryOperator::Comma)
- return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2) ||
- BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2);
+ return (BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx) ||
+ BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
if (BO->isAssignmentOp())
return false;
@@ -762,15 +763,15 @@
// warning, warn about them.
const ConditionalOperator *Exp = cast<ConditionalOperator>(this);
if (Exp->getLHS() &&
- Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2))
+ Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx))
return true;
- return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2);
+ return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx);
}
case MemberExprClass:
// If the base pointer or element is to a volatile pointer/field, accessing
// it is a side effect.
- if (getType().isVolatileQualified())
+ if (Ctx.getCanonicalType(getType()).isVolatileQualified())
return false;
Loc = cast<MemberExpr>(this)->getMemberLoc();
R1 = SourceRange(Loc, Loc);
@@ -780,7 +781,7 @@
case ArraySubscriptExprClass:
// If the base pointer or element is to a volatile pointer/field, accessing
// it is a side effect.
- if (getType().isVolatileQualified())
+ if (Ctx.getCanonicalType(getType()).isVolatileQualified())
return false;
Loc = cast<ArraySubscriptExpr>(this)->getRBracketLoc();
R1 = cast<ArraySubscriptExpr>(this)->getLHS()->getSourceRange();
@@ -838,7 +839,7 @@
const CompoundStmt *CS = cast<StmtExpr>(this)->getSubStmt();
if (!CS->body_empty())
if (const Expr *E = dyn_cast<Expr>(CS->body_back()))
- return E->isUnusedResultAWarning(Loc, R1, R2);
+ return E->isUnusedResultAWarning(Loc, R1, R2, Ctx);
Loc = cast<StmtExpr>(this)->getLParenLoc();
R1 = getSourceRange();
@@ -856,20 +857,20 @@
// If this is a cast to void, check the operand. Otherwise, the result of
// the cast is unused.
if (getType()->isVoidType())
- return cast<CastExpr>(this)->getSubExpr()
- ->isUnusedResultAWarning(Loc, R1, R2);
+ return (cast<CastExpr>(this)->getSubExpr()
+ ->isUnusedResultAWarning(Loc, R1, R2, Ctx));
Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc();
R1 = cast<CXXFunctionalCastExpr>(this)->getSubExpr()->getSourceRange();
return true;
case ImplicitCastExprClass:
// Check the operand, since implicit casts are inserted by Sema
- return cast<ImplicitCastExpr>(this)
- ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ return (cast<ImplicitCastExpr>(this)
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
case CXXDefaultArgExprClass:
- return cast<CXXDefaultArgExpr>(this)
- ->getExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ return (cast<CXXDefaultArgExpr>(this)
+ ->getExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
case CXXNewExprClass:
// FIXME: In theory, there might be new expressions that don't have side
@@ -877,11 +878,11 @@
case CXXDeleteExprClass:
return false;
case CXXBindTemporaryExprClass:
- return cast<CXXBindTemporaryExpr>(this)
- ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ return (cast<CXXBindTemporaryExpr>(this)
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
case CXXExprWithTemporariesClass:
- return cast<CXXExprWithTemporaries>(this)
- ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ return (cast<CXXExprWithTemporaries>(this)
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
}
}
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index c70d05e..7862c57 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -167,7 +167,7 @@
bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
bool VisitDeclRefExpr(DeclRefExpr *E) {
- if (E->getType().isVolatileQualified())
+ if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
return true;
return false;
}
@@ -197,7 +197,7 @@
bool VisitUnaryPreDec(UnaryOperator *E) { return true; }
bool VisitUnaryPostDec(UnaryOperator *E) { return true; }
bool VisitUnaryDeref(UnaryOperator *E) {
- if (E->getType().isVolatileQualified())
+ if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
return true;
return Visit(E->getSubExpr());
}
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 06a17ff..95f073c 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -71,16 +71,17 @@
const Expr *Init = D.getInit();
QualType T = D.getType();
+ bool isVolatile = getContext().getCanonicalType(T).isVolatileQualified();
if (T->isReferenceType()) {
ErrorUnsupported(Init, "global variable that binds to a reference");
} else if (!hasAggregateLLVMType(T)) {
llvm::Value *V = EmitScalarExpr(Init);
- EmitStoreOfScalar(V, DeclPtr, T.isVolatileQualified(), T);
+ EmitStoreOfScalar(V, DeclPtr, isVolatile, T);
} else if (T->isAnyComplexType()) {
- EmitComplexExprIntoAddr(Init, DeclPtr, T.isVolatileQualified());
+ EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
} else {
- EmitAggExpr(Init, DeclPtr, T.isVolatileQualified());
+ EmitAggExpr(Init, DeclPtr, isVolatile);
if (const RecordType *RT = T->getAs<RecordType>()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 8e445de..4f8aef4 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -417,17 +417,18 @@
Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
D.getNameAsString());
+ bool isVolatile = (getContext().getCanonicalType(D.getType())
+ .isVolatileQualified());
if (Ty->isReferenceType()) {
RValue RV = EmitReferenceBindingToExpr(Init, Ty, /*IsInitializer=*/true);
EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Ty);
} else if (!hasAggregateLLVMType(Init->getType())) {
llvm::Value *V = EmitScalarExpr(Init);
- EmitStoreOfScalar(V, Loc, D.getType().isVolatileQualified(),
- D.getType());
+ EmitStoreOfScalar(V, Loc, isVolatile, D.getType());
} else if (Init->getType()->isAnyComplexType()) {
- EmitComplexExprIntoAddr(Init, Loc, D.getType().isVolatileQualified());
+ EmitComplexExprIntoAddr(Init, Loc, isVolatile);
} else {
- EmitAggExpr(Init, Loc, D.getType().isVolatileQualified());
+ EmitAggExpr(Init, Loc, isVolatile);
}
}
@@ -556,6 +557,7 @@
assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) &&
"Invalid argument to EmitParmDecl");
QualType Ty = D.getType();
+ CanQualType CTy = getContext().getCanonicalType(Ty);
llvm::Value *DeclPtr;
if (!Ty->isConstantSizeType()) {
@@ -572,7 +574,7 @@
DeclPtr->setName(Name.c_str());
// Store the initial value into the alloca.
- EmitStoreOfScalar(Arg, DeclPtr, Ty.isVolatileQualified(), Ty);
+ EmitStoreOfScalar(Arg, DeclPtr, CTy.isVolatileQualified(), Ty);
} else {
// Otherwise, if this is an aggregate, just use the input pointer.
DeclPtr = Arg;
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 4bff8c4..96b58d8 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -1648,9 +1648,10 @@
/// expression is cheap enough and side-effect-free enough to evaluate
/// unconditionally instead of conditionally. This is used to convert control
/// flow into selects in some cases.
-static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E) {
+static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E,
+ CodeGenFunction &CGF) {
if (const ParenExpr *PE = dyn_cast<ParenExpr>(E))
- return isCheapEnoughToEvaluateUnconditionally(PE->getSubExpr());
+ return isCheapEnoughToEvaluateUnconditionally(PE->getSubExpr(), CGF);
// TODO: Allow anything we can constant fold to an integer or fp constant.
if (isa<IntegerLiteral>(E) || isa<CharacterLiteral>(E) ||
@@ -1661,7 +1662,9 @@
// X and Y are local variables.
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
- if (VD->hasLocalStorage() && !VD->getType().isVolatileQualified())
+ if (VD->hasLocalStorage() && !(CGF.getContext()
+ .getCanonicalType(VD->getType())
+ .isVolatileQualified()))
return true;
return false;
@@ -1690,8 +1693,9 @@
// If this is a really simple expression (like x ? 4 : 5), emit this as a
// select instead of as control flow. We can only do this if it is cheap and
// safe to evaluate the LHS and RHS unconditionally.
- if (E->getLHS() && isCheapEnoughToEvaluateUnconditionally(E->getLHS()) &&
- isCheapEnoughToEvaluateUnconditionally(E->getRHS())) {
+ if (E->getLHS() && isCheapEnoughToEvaluateUnconditionally(E->getLHS(),
+ CGF) &&
+ isCheapEnoughToEvaluateUnconditionally(E->getRHS(), CGF)) {
llvm::Value *CondV = CGF.EvaluateExprAsBool(E->getCond());
llvm::Value *LHS = Visit(E->getLHS());
llvm::Value *RHS = Visit(E->getRHS());
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 893f1ed..9bb2196 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -517,7 +517,7 @@
//===--------------------------------------------------------------------===//
Qualifiers MakeQualifiers(QualType T) {
- Qualifiers Quals = T.getQualifiers();
+ Qualifiers Quals = getContext().getCanonicalType(T).getQualifiers();
Quals.setObjCGCAttr(getContext().getObjCGCAttrKind(T));
return Quals;
}
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 1453424..6a65bd1 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -70,7 +70,7 @@
SourceLocation Loc;
SourceRange R1, R2;
- if (!E->isUnusedResultAWarning(Loc, R1, R2))
+ if (!E->isUnusedResultAWarning(Loc, R1, R2, Context))
return;
// Okay, we have an unused result. Depending on what the base expression is,