[clang] [OpenACC] Better handle error overloaded ops in ForStmtChecker (PR #211005)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 21 07:01:37 PDT 2026
https://github.com/erichkeane created https://github.com/llvm/llvm-project/pull/211005
The OpenACC 'loop' constructs do a bunch of checking on the contents of a ForStmt. However, in cases of overloaded operators, some of the checking we assumed happened (like operators having a certain number of
args) doesn't hold in the case of errors. This patch adds some
guards to make sure we error-out if the number of args doesn't match what we're expecting everywhere I could find it.
Fixes: #210958
>From c8ee94d470a4af34f565773c20b18f4e0ba54a0d Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Tue, 21 Jul 2026 06:56:48 -0700
Subject: [PATCH] [OpenACC] Better handle error overloaded ops in
ForStmtChecker
The OpenACC 'loop' constructs do a bunch of checking on the contents of
a ForStmt. However, in cases of overloaded operators, some of the
checking we assumed happened (like operators having a certain number of
args) doesn't hold in the case of errors. This patch adds some
guards to make sure we error-out if the number of args doesn't match
what we're expecting everywhere I could find it.
Fixes: #210958
---
clang/lib/Sema/SemaOpenACC.cpp | 16 +++++++++++++++-
clang/test/SemaOpenACC/loop-construct.cpp | 15 +++++++++++++++
2 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 79edb8093c368..362bae5eebef6 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -1345,6 +1345,8 @@ bool SemaOpenACC::ForStmtBeginChecker::checkForInit(const Stmt *InitStmt,
// Allow assignment operator call.
if (CE->getOperator() != OO_Equal)
return DiagLoopVar();
+ if (CE->getNumArgs() < 1)
+ return DiagLoopVar();
const Expr *LHS = CE->getArg(0)->IgnoreParenImpCasts();
if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
@@ -1437,6 +1439,9 @@ bool SemaOpenACC::ForStmtBeginChecker::checkForCond(const Stmt *CondStmt,
if (!CE->isComparisonOp() || CE->getOperator() == OO_Spaceship)
return DiagCondVar();
+ if (CE->getNumArgs() < 1)
+ DiagCondVar();
+
// Same logic here: Assign it to the LHS, unless the LHS comes back null or
// not equal to the init var.
CondVar = getDeclFromExpr(CE->getArg(0));
@@ -1506,6 +1511,11 @@ bool isValidForIncRHSAssign(const ValueDecl *InitVar, const Expr *RHS) {
OverloadedOperatorKind Op = CE->getOperator();
if (Op != OO_Plus && Op != OO_Minus)
return false;
+ // Despite Plus/Minus otherwise only being possible with 2 arguments, error
+ // recovery will sometimes leave us with only 1 here, so fail out if we
+ // don't have the correct number of args.
+ if (CE->getNumArgs() != 2)
+ return false;
return isValid(InitVar, CE->getArg(0), CE->getArg(1), Op == OO_Plus);
}
@@ -1565,6 +1575,9 @@ bool SemaOpenACC::ForStmtBeginChecker::checkForInc(const Stmt *IncStmt,
}
IncVar = getDeclFromExpr(BO->getLHS());
} else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(IncStmt)) {
+ if (CE->getNumArgs() < 1)
+ return DiagIncVar();
+
switch (CE->getOperator()) {
default:
return DiagIncVar();
@@ -1576,7 +1589,8 @@ bool SemaOpenACC::ForStmtBeginChecker::checkForInc(const Stmt *IncStmt,
case OO_Equal:
// For assignment we also allow InitVar = InitVar + N, InitVar = N +
// InitVar, and InitVar = InitVar - N; BUT only if 'N' is integral.
- if (!isValidForIncRHSAssign(InitVar, CE->getArg(1)))
+ if (CE->getNumArgs() != 2 ||
+ !isValidForIncRHSAssign(InitVar, CE->getArg(1)))
return DiagIncVar();
break;
}
diff --git a/clang/test/SemaOpenACC/loop-construct.cpp b/clang/test/SemaOpenACC/loop-construct.cpp
index 0282258023baf..a64376b31e390 100644
--- a/clang/test/SemaOpenACC/loop-construct.cpp
+++ b/clang/test/SemaOpenACC/loop-construct.cpp
@@ -439,3 +439,18 @@ void allowTrivialAssignStep(int N) {
for (auto Itr = Col.begin(); Itr != Col.end(); Itr = N - Itr);
}
+namespace gh210958 {
+// expected-error at +1{{overloaded 'operator-' must have at least one parameter of class or enumeration type}}
+void operator-();
+
+void foo() {
+#pragma acc loop
+ // expected-error at +5{{unknown type name 'I'}}
+ // expected-error at +4{{OpenACC 'loop' construct must have a terminating condition}}
+ // expected-note at -3{{'loop' construct is here}}
+ // expected-error at +2{{OpenACC 'loop' variable must monotonically increase or decrease ('++', '--', or compound assignment)}}
+ // expected-note at -5{{'loop' construct is here}}
+ for (I i = 0; i <= 2; i = -i);
+};
+
+}
More information about the cfe-commits
mailing list