diff options
Diffstat (limited to 'source/slang')
| -rw-r--r-- | source/slang/slang-check-expr.cpp | 34 | ||||
| -rw-r--r-- | source/slang/slang-check-impl.h | 17 | ||||
| -rw-r--r-- | source/slang/slang-check-stmt.cpp | 5 | ||||
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 5 |
4 files changed, 60 insertions, 1 deletions
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index d2f338e65..425548518 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -3229,6 +3229,40 @@ Expr* SemanticsExprVisitor::visitInvokeExpr(InvokeExpr* expr) if (auto newExpr = convertToLogicOperatorExpr(expr)) return newExpr; + // Check for comma operator usage and emit warning if not in for-loop side effect context + // Skip warning in Slang 2026+ mode where parentheses create tuples + if (!isSlang2026OrLater(this)) + { + bool exprIsInfixExpr = false; + InfixExpr* infixExpr = nullptr; + if (auto candidateInfixExpr = as<InfixExpr>(expr)) + { + exprIsInfixExpr = true; + infixExpr = candidateInfixExpr; + } + + bool functionExprIsVarExpr = false; + VarExpr* varExpr = nullptr; + if (exprIsInfixExpr) + { + if (auto candidateVarExpr = as<VarExpr>(infixExpr->functionExpr)) + { + functionExprIsVarExpr = true; + varExpr = candidateVarExpr; + } + } + + if (functionExprIsVarExpr && varExpr->name && varExpr->name->text == ",") + { + // Allow comma operators in for-loop side effects and expand expressions without + // warning + if (!getInForLoopSideEffect() && !m_parentExpandExpr) + { + getSink()->diagnose(infixExpr, Diagnostics::commaOperatorUsedInExpression); + } + } + } + expr->functionExpr = CheckTerm(expr->functionExpr); if (auto baseType = as<DeclRefType>(expr->functionExpr->type)) diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h index 2675ecee0..48b06eb9f 100644 --- a/source/slang/slang-check-impl.h +++ b/source/slang/slang-check-impl.h @@ -1069,6 +1069,18 @@ public: return result; } + // Setup the flag to indicate we're in a for-loop side effect context where comma operators are + // allowed + SemanticsContext withInForLoopSideEffect() + { + SemanticsContext result(*this); + result.m_inForLoopSideEffect = true; + return result; + } + + bool getInForLoopSideEffect() { return m_inForLoopSideEffect; } + + TryClauseType getEnclosingTryClauseType() { return m_enclosingTryClauseType; } SemanticsContext withEnclosingTryClauseType(TryClauseType tryClauseType) @@ -1202,6 +1214,11 @@ protected: // 3. the logic expression is in an array size declaration. bool m_shouldShortCircuitLogicExpr = true; + // Flag to track when we're in a for-loop side effect expression where comma operators are + // allowed + bool m_inForLoopSideEffect = false; + + ExpandExpr* m_parentExpandExpr = nullptr; OrderedHashSet<Type*>* m_capturedTypePacks = nullptr; diff --git a/source/slang/slang-check-stmt.cpp b/source/slang/slang-check-stmt.cpp index bf8ddc94e..8c9e24d48 100644 --- a/source/slang/slang-check-stmt.cpp +++ b/source/slang/slang-check-stmt.cpp @@ -281,7 +281,10 @@ void SemanticsStmtVisitor::visitForStmt(ForStmt* stmt) } if (stmt->sideEffectExpression) { - stmt->sideEffectExpression = CheckExpr(stmt->sideEffectExpression); + // Use special context for for-loop side effect to allow comma operators without warning + SemanticsContext sideEffectContext = withInForLoopSideEffect(); + SemanticsExprVisitor subExprVisitor(sideEffectContext); + stmt->sideEffectExpression = subExprVisitor.CheckExpr(stmt->sideEffectExpression); } subContext.checkStmt(stmt->statement); diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index e9c8acfe3..284cb634c 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -2512,6 +2512,11 @@ DIAGNOSTIC( Warning, methodNeverMutates, "method marked `[mutable]` but never modifies `this`") +DIAGNOSTIC( + 41024, + Warning, + commaOperatorUsedInExpression, + "comma operator used in expression (may be unintended)") DIAGNOSTIC( 41024, |
