Better constant expression acyclic check error messages
Makes constant expression acyclic check error messages look like
type acyclic check.
ex:
enum E {
A = D,
B,
C,
D
}
previous cycle print:
A at ...
B at ...
C at ...
D at ...
new cycle print:
D in A at ...
A in B at ...
B in C at ...
C in D at ...
Test: mma
Test: local test with moved lookups
Change-Id: I091792d4de049509708cb91331e8504e0edf14b9
diff --git a/ConstantExpression.cpp b/ConstantExpression.cpp
index a593025..5388acf 100644
--- a/ConstantExpression.cpp
+++ b/ConstantExpression.cpp
@@ -440,6 +440,10 @@
return this->cast<size_t>();
}
+bool ConstantExpression::isReferenceConstantExpression() const {
+ return false;
+}
+
std::vector<ConstantExpression*> ConstantExpression::getConstantExpressions() {
const auto& constRet = static_cast<const ConstantExpression*>(this)->getConstantExpressions();
std::vector<ConstantExpression*> ret(constRet.size());
@@ -514,18 +518,24 @@
return OK;
}
-ConstantExpression::CheckAcyclicStatus::CheckAcyclicStatus(status_t status,
- const ConstantExpression* cycleEnd)
- : status(status), cycleEnd(cycleEnd) {
+ConstantExpression::CheckAcyclicStatus::CheckAcyclicStatus(
+ status_t status, const ConstantExpression* cycleEnd,
+ const ReferenceConstantExpression* lastReference)
+ : status(status), cycleEnd(cycleEnd), lastReference(lastReference) {
CHECK(cycleEnd == nullptr || status != OK);
+ CHECK((cycleEnd == nullptr) == (lastReference == nullptr));
}
ConstantExpression::CheckAcyclicStatus ConstantExpression::checkAcyclic(
std::unordered_set<const ConstantExpression*>* visited,
std::unordered_set<const ConstantExpression*>* stack) const {
if (stack->find(this) != stack->end()) {
+ CHECK(isReferenceConstantExpression())
+ << "Only reference constant expression could be the cycle end";
+
std::cerr << "ERROR: Cyclic declaration:\n";
- return CheckAcyclicStatus(UNKNOWN_ERROR, this);
+ return CheckAcyclicStatus(UNKNOWN_ERROR, this,
+ static_cast<const ReferenceConstantExpression*>(this));
}
if (visited->find(this) != visited->end()) return CheckAcyclicStatus(OK);
@@ -548,18 +558,18 @@
if (err.cycleEnd == nullptr) return err;
// Only ReferenceConstantExpression has references,
- // mExpr is defined explicitly before evaluation
+ CHECK(isReferenceConstantExpression())
+ << "Only reference constant expression could have refereneces";
- std::cerr << " ";
- if (!mTrivialDescription) {
- std::cerr << " '" << mExpr << "' ";
- };
- std::cerr << "at " << nextRef->location() << "\n";
+ // mExpr is defined explicitly before evaluation
+ std::cerr << " '" << err.lastReference->mExpr << "' in '" << mExpr << "' at "
+ << nextRef->location() << "\n";
if (err.cycleEnd == this) {
return CheckAcyclicStatus(err.status);
}
- return err;
+ return CheckAcyclicStatus(err.status, err.cycleEnd,
+ static_cast<const ReferenceConstantExpression*>(this));
}
}
@@ -608,6 +618,10 @@
mTrivialDescription = mExpr.empty();
}
+bool ReferenceConstantExpression::isReferenceConstantExpression() const {
+ return true;
+}
+
std::vector<const ConstantExpression*> ReferenceConstantExpression::getConstantExpressions() const {
// Returns reference instead
return {};