summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-10-09 02:04:54 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-10-09 02:04:54 +0000
commitd2d3fbf13186aa57a70b726b300cb4ea2c2bcb89 (patch)
tree2e412aa3acfd6f3f53f71defb34e38a4fa81cdc8 /lib/Sema/SemaExpr.cpp
parent254170520fef51111331fb5a22c75ebfef881483 (diff)
downloadclang-d2d3fbf13186aa57a70b726b300cb4ea2c2bcb89.tar.gz
[c++20] P1152R4: warn on any simple-assignment to a volatile lvalue
whose value is not ignored. We don't warn on all the cases that are deprecated: specifically, we choose to not warn for now if there are parentheses around the assignment but its value is not actually used. This seems like a more defensible rule, particularly for cases like sizeof(v = a), where the parens are part of the operand rather than the sizeof syntax. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@374135 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r--lib/Sema/SemaExpr.cpp51
1 files changed, 43 insertions, 8 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index b691668da8..23d3171505 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -3801,6 +3801,16 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
QualType ExprTy = E->getType();
assert(!ExprTy->isReferenceType());
+ bool IsUnevaluatedOperand =
+ (ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf ||
+ ExprKind == UETT_PreferredAlignOf);
+ if (IsUnevaluatedOperand) {
+ ExprResult Result = CheckUnevaluatedOperand(E);
+ if (Result.isInvalid())
+ return true;
+ E = Result.get();
+ }
+
if (ExprKind == UETT_VecStep)
return CheckVecStepTraitOperandType(*this, ExprTy, E->getExprLoc(),
E->getSourceRange());
@@ -3838,9 +3848,8 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
// The operand for sizeof and alignof is in an unevaluated expression context,
// so side effects could result in unintended consequences.
- if ((ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf ||
- ExprKind == UETT_PreferredAlignOf) &&
- !inTemplateInstantiation() && E->HasSideEffects(Context, false))
+ if (IsUnevaluatedOperand && !inTemplateInstantiation() &&
+ E->HasSideEffects(Context, false))
Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
if (CheckObjCTraitOperandConstraints(*this, ExprTy, E->getExprLoc(),
@@ -3939,8 +3948,6 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType,
}
static bool CheckAlignOfExpr(Sema &S, Expr *E, UnaryExprOrTypeTrait ExprKind) {
- E = E->IgnoreParens();
-
// Cannot know anything else if the expression is dependent.
if (E->isTypeDependent())
return false;
@@ -3952,9 +3959,10 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E, UnaryExprOrTypeTrait ExprKind) {
}
ValueDecl *D = nullptr;
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ Expr *Inner = E->IgnoreParens();
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Inner)) {
D = DRE->getDecl();
- } else if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+ } else if (MemberExpr *ME = dyn_cast<MemberExpr>(Inner)) {
D = ME->getMemberDecl();
}
@@ -11944,7 +11952,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
// A simple-assignment whose left operand is of a volatile-qualified
// type is deprecated unless the assignment is either a discarded-value
// expression or an unevaluated operand
- // FIXME: Implement checks for this.
+ ExprEvalContexts.back().VolatileAssignmentLHSs.push_back(LHSExpr);
} else {
// C++2a [expr.ass]p6:
// [Compound-assignment] expressions are deprecated if E1 has
@@ -15082,6 +15090,26 @@ void Sema::WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec) {
Rec.PossibleDerefs.clear();
}
+/// Check whether E, which is either a discarded-value expression or an
+/// unevaluated operand, is a simple-assignment to a volatlie-qualified lvalue,
+/// and if so, remove it from the list of volatile-qualified assignments that
+/// we are going to warn are deprecated.
+void Sema::CheckUnusedVolatileAssignment(Expr *E) {
+ if (!E->getType().isVolatileQualified() || !getLangOpts().CPlusPlus2a)
+ return;
+
+ // Note: ignoring parens here is not justified by the standard rules, but
+ // ignoring parentheses seems like a more reasonable approach, and this only
+ // drives a deprecation warning so doesn't affect conformance.
+ if (auto *BO = dyn_cast<BinaryOperator>(E->IgnoreParenImpCasts())) {
+ if (BO->getOpcode() == BO_Assign) {
+ auto &LHSs = ExprEvalContexts.back().VolatileAssignmentLHSs;
+ LHSs.erase(std::remove(LHSs.begin(), LHSs.end(), BO->getLHS()),
+ LHSs.end());
+ }
+ }
+}
+
void Sema::PopExpressionEvaluationContext() {
ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
unsigned NumTypos = Rec.NumTypos;
@@ -15116,6 +15144,13 @@ void Sema::PopExpressionEvaluationContext() {
WarnOnPendingNoDerefs(Rec);
+ // Warn on any volatile-qualified simple-assignments that are not discarded-
+ // value expressions nor unevaluated operands (those cases get removed from
+ // this list by CheckUnusedVolatileAssignment).
+ for (auto *BO : Rec.VolatileAssignmentLHSs)
+ Diag(BO->getBeginLoc(), diag::warn_deprecated_simple_assign_volatile)
+ << BO->getType();
+
// When are coming out of an unevaluated context, clear out any
// temporaries that we may have created as part of the evaluation of
// the expression in that context: they aren't relevant because they