aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorIlya Mirsky <ilya.mirsky@ericsson.com>2021-01-17 18:02:44 -0600
committereinvbri <vince.a.bridgers@ericsson.com>2021-02-03 07:50:50 -0600
commite48f444751cf781c42934b242b81f549da77bad0 (patch)
tree54f1de226da8680bb8b3147364c5f8692581cd2a /clang/lib/Sema/SemaChecking.cpp
parente635feb15a91e6eeb77876031be2811e63d542f3 (diff)
downloadllvm-e48f444751cf781c42934b242b81f549da77bad0.zip
llvm-e48f444751cf781c42934b242b81f549da77bad0.tar.gz
llvm-e48f444751cf781c42934b242b81f549da77bad0.tar.bz2
[Sema] Fix -Warray-bounds false negative when casting an out-of-bounds array item
Patch by Ilya Mirsky! Fixes: http://llvm.org/PR44343 Reviewed By: rsmith Differential Revision: https://reviews.llvm.org/D71714
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r--clang/lib/Sema/SemaChecking.cpp111
1 files changed, 56 insertions, 55 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 2d3d36f..17dd5c9 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -14387,62 +14387,63 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
PDiag(diag::note_array_declared_here) << ND);
}
-void Sema::CheckArrayAccess(const Expr *expr) {
- int AllowOnePastEnd = 0;
- while (expr) {
- expr = expr->IgnoreParenImpCasts();
- switch (expr->getStmtClass()) {
- case Stmt::ArraySubscriptExprClass: {
- const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(expr);
- CheckArrayAccess(ASE->getBase(), ASE->getIdx(), ASE,
- AllowOnePastEnd > 0);
- expr = ASE->getBase();
- break;
- }
- case Stmt::MemberExprClass: {
- expr = cast<MemberExpr>(expr)->getBase();
- break;
- }
- case Stmt::OMPArraySectionExprClass: {
- const OMPArraySectionExpr *ASE = cast<OMPArraySectionExpr>(expr);
- if (ASE->getLowerBound())
- CheckArrayAccess(ASE->getBase(), ASE->getLowerBound(),
- /*ASE=*/nullptr, AllowOnePastEnd > 0);
- return;
- }
- case Stmt::UnaryOperatorClass: {
- // Only unwrap the * and & unary operators
- const UnaryOperator *UO = cast<UnaryOperator>(expr);
- expr = UO->getSubExpr();
- switch (UO->getOpcode()) {
- case UO_AddrOf:
- AllowOnePastEnd++;
- break;
- case UO_Deref:
- AllowOnePastEnd--;
- break;
- default:
- return;
- }
- break;
- }
- case Stmt::ConditionalOperatorClass: {
- const ConditionalOperator *cond = cast<ConditionalOperator>(expr);
- if (const Expr *lhs = cond->getLHS())
- CheckArrayAccess(lhs);
- if (const Expr *rhs = cond->getRHS())
- CheckArrayAccess(rhs);
- return;
- }
- case Stmt::CXXOperatorCallExprClass: {
- const auto *OCE = cast<CXXOperatorCallExpr>(expr);
- for (const auto *Arg : OCE->arguments())
- CheckArrayAccess(Arg);
- return;
- }
- default:
- return;
+void Sema::CheckArrayAccess(const Expr *expr, int AllowOnePastEnd) {
+ if (!expr)
+ return;
+
+ expr = expr->IgnoreParenCasts();
+ switch (expr->getStmtClass()) {
+ case Stmt::ArraySubscriptExprClass: {
+ const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(expr);
+ CheckArrayAccess(ASE->getBase(), ASE->getIdx(), ASE, AllowOnePastEnd > 0);
+ CheckArrayAccess(ASE->getBase(), AllowOnePastEnd);
+ return;
+ }
+ case Stmt::MemberExprClass: {
+ expr = cast<MemberExpr>(expr)->getBase();
+ CheckArrayAccess(expr, /*AllowOnePastEnd=*/0);
+ return;
+ }
+ case Stmt::OMPArraySectionExprClass: {
+ const OMPArraySectionExpr *ASE = cast<OMPArraySectionExpr>(expr);
+ if (ASE->getLowerBound())
+ CheckArrayAccess(ASE->getBase(), ASE->getLowerBound(),
+ /*ASE=*/nullptr, AllowOnePastEnd > 0);
+ return;
+ }
+ case Stmt::UnaryOperatorClass: {
+ // Only unwrap the * and & unary operators
+ const UnaryOperator *UO = cast<UnaryOperator>(expr);
+ expr = UO->getSubExpr();
+ switch (UO->getOpcode()) {
+ case UO_AddrOf:
+ AllowOnePastEnd++;
+ break;
+ case UO_Deref:
+ AllowOnePastEnd--;
+ break;
+ default:
+ return;
}
+ CheckArrayAccess(expr, AllowOnePastEnd);
+ return;
+ }
+ case Stmt::ConditionalOperatorClass: {
+ const ConditionalOperator *cond = cast<ConditionalOperator>(expr);
+ if (const Expr *lhs = cond->getLHS())
+ CheckArrayAccess(lhs, AllowOnePastEnd);
+ if (const Expr *rhs = cond->getRHS())
+ CheckArrayAccess(rhs, AllowOnePastEnd);
+ return;
+ }
+ case Stmt::CXXOperatorCallExprClass: {
+ const auto *OCE = cast<CXXOperatorCallExpr>(expr);
+ for (const auto *Arg : OCE->arguments())
+ CheckArrayAccess(Arg);
+ return;
+ }
+ default:
+ return;
}
}