Better error location reporting for non-affine expressions.
Pass op token location where necessary so that errors on non-affine expressions
are reported with accurate/meaningful location pointers.
Before:
/tmp/parser-affine-map-single.mlir:2:39: error: non-affine expression: at least one of the multiply operands has to be either a constant or symbolic
#hello_world = (i, j) [s0, s1] -> (i*j, j)
^
After:
/tmp/parser-affine-map-single.mlir:2:37: error: non-affine expression: at least one of the multiply operands has to be either a constant or symbolic
#hello_world = (i, j) [s0, s1] -> (i*j, j)
^
PiperOrigin-RevId: 205458508
diff --git a/lib/Parser/Parser.cpp b/lib/Parser/Parser.cpp
index b8bae40..da936db 100644
--- a/lib/Parser/Parser.cpp
+++ b/lib/Parser/Parser.cpp
@@ -691,14 +691,15 @@
AffineExpr *parseBareIdExpr();
AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
- AffineExpr *rhs);
+ AffineExpr *rhs, SMLoc opLoc);
AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
AffineExpr *rhs);
AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
AffineLowPrecOp llhsOp);
AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
- AffineHighPrecOp llhsOp);
+ AffineHighPrecOp llhsOp,
+ SMLoc llhsOpLoc);
private:
// TODO(bondhugula): could just use an vector/ArrayRef and scan the numbers.
@@ -710,37 +711,39 @@
};
} // end anonymous namespace
-/// Create an affine binary high precedence op expression (mul's, div's, mod)
+/// Create an affine binary high precedence op expression (mul's, div's, mod).
+/// opLoc is the location of the op token to be used to report errors
+/// for non-conforming expressions.
AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
AffineExpr *lhs,
- AffineExpr *rhs) {
+ AffineExpr *rhs, SMLoc opLoc) {
// TODO: make the error location info accurate.
switch (op) {
case Mul:
if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
- emitError("non-affine expression: at least one of the multiply "
- "operands has to be either a constant or symbolic");
+ emitError(opLoc, "non-affine expression: at least one of the multiply "
+ "operands has to be either a constant or symbolic");
return nullptr;
}
return builder.getMulExpr(lhs, rhs);
case FloorDiv:
if (!rhs->isSymbolicOrConstant()) {
- emitError("non-affine expression: right operand of floordiv "
- "has to be either a constant or symbolic");
+ emitError(opLoc, "non-affine expression: right operand of floordiv "
+ "has to be either a constant or symbolic");
return nullptr;
}
return builder.getFloorDivExpr(lhs, rhs);
case CeilDiv:
if (!rhs->isSymbolicOrConstant()) {
- emitError("non-affine expression: right operand of ceildiv "
- "has to be either a constant or symbolic");
+ emitError(opLoc, "non-affine expression: right operand of ceildiv "
+ "has to be either a constant or symbolic");
return nullptr;
}
return builder.getCeilDivExpr(lhs, rhs);
case Mod:
if (!rhs->isSymbolicOrConstant()) {
- emitError("non-affine expression: right operand of mod "
- "has to be either a constant or symbolic");
+ emitError(opLoc, "non-affine expression: right operand of mod "
+ "has to be either a constant or symbolic");
return nullptr;
}
return builder.getModExpr(lhs, rhs);
@@ -809,29 +812,31 @@
/// All affine binary ops are left associative.
/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
-/// null.
-AffineExpr *
-AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
- AffineHighPrecOp llhsOp) {
+/// null. llhsOpLoc is the location of the llhsOp token that will be used to
+/// report an error for non-conforming expressions.
+AffineExpr *AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
+ AffineHighPrecOp llhsOp,
+ SMLoc llhsOpLoc) {
AffineExpr *lhs = parseAffineOperandExpr(llhs);
if (!lhs)
return nullptr;
// Found an LHS. Parse the remaining expression.
+ auto opLoc = getToken().getLoc();
if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
if (llhs) {
- AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
+ AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
if (!expr)
return nullptr;
- return parseAffineHighPrecOpExpr(expr, op);
+ return parseAffineHighPrecOpExpr(expr, op, opLoc);
}
// No LLHS, get RHS
- return parseAffineHighPrecOpExpr(lhs, op);
+ return parseAffineHighPrecOpExpr(lhs, op, opLoc);
}
// This is the last operand in this expression.
if (llhs)
- return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
+ return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
// No llhs, 'lhs' itself is the expression.
return lhs;
@@ -989,10 +994,11 @@
// No LLHS, get RHS and form the expression.
return parseAffineLowPrecOpExpr(lhs, lOp);
}
+ auto opLoc = getToken().getLoc();
if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
// We have a higher precedence op here. Get the rhs operand for the llhs
// through parseAffineHighPrecOpExpr.
- AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp);
+ AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
if (!highRes)
return nullptr;