}
}
+namespace {
+ struct CaseCompareFunctor {
+ bool operator()(const std::pair<llvm::APSInt, CaseStmt*> &LHS,
+ const llvm::APSInt &RHS) {
+ return LHS.first < RHS;
+ }
+ bool operator()(const llvm::APSInt &LHS,
+ const std::pair<llvm::APSInt, CaseStmt*> &RHS) {
+ return LHS < RHS.first;
+ }
+ };
+}
+
Action::StmtResult
Sema::FinishSwitchStmt(SourceLocation SwitchLoc, StmtTy *Switch, ExprTy *Body) {
Stmt *BodyStmt = (Stmt*)Body;
// Accumulate all of the case values in a vector so that we can sort them
// and detect duplicates. This vector contains the APInt for the case after
// it has been converted to the condition type.
- llvm::SmallVector<std::pair<llvm::APSInt, CaseStmt*>, 64> CaseVals;
+ typedef llvm::SmallVector<std::pair<llvm::APSInt, CaseStmt*>, 64> CaseValsTy;
+ CaseValsTy CaseVals;
// Keep track of any GNU case ranges we see. The APSInt is the low value.
std::vector<std::pair<llvm::APSInt, CaseStmt*> > CaseRanges;
if (!CaseRanges.empty()) {
// Sort all the case ranges by their low value so we can easily detect
// overlaps between ranges.
- std::stable_sort(CaseVals.begin(), CaseVals.end());
+ std::stable_sort(CaseRanges.begin(), CaseRanges.end());
// Scan the ranges, computing the high values and removing empty ranges.
std::vector<llvm::APSInt> HiVals;
}
// Rescan the ranges, looking for overlap with singleton values and other
- // ranges.
+ // ranges. Since the range list is sorted, we only need to compare case
+ // ranges with their neighbors.
for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) {
- //llvm::APSInt &CRLow = CaseRanges[i].first;
- //CaseStmt *CR = CaseRanges[i].second;
+ llvm::APSInt &CRLo = CaseRanges[i].first;
+ llvm::APSInt &CRHi = HiVals[i];
+ CaseStmt *CR = CaseRanges[i].second;
+
+ // Check to see whether the case range overlaps with any singleton cases.
+ CaseStmt *OverlapStmt = 0;
+ llvm::APSInt OverlapVal(32);
+
+ // Find the smallest value >= the lower bound. If I is in the case range,
+ // then we have overlap.
+ CaseValsTy::iterator I = std::lower_bound(CaseVals.begin(),
+ CaseVals.end(), CRLo,
+ CaseCompareFunctor());
+ if (I != CaseVals.end() && I->first < CRHi) {
+ OverlapVal = I->first; // Found overlap with scalar.
+ OverlapStmt = I->second;
+ }
+
+ // Find the smallest value bigger than the upper bound.
+ I = std::upper_bound(I, CaseVals.end(), CRHi, CaseCompareFunctor());
+ if (I != CaseVals.begin() && (I-1)->first >= CRLo) {
+ OverlapVal = (I-1)->first; // Found overlap with scalar.
+ OverlapStmt = (I-1)->second;
+ }
+
+ // Check to see if this case stmt overlaps with the subsequent case range.
+ if (i && CRLo <= HiVals[i-1]) {
+ OverlapVal = HiVals[i-1]; // Found overlap with range.
+ OverlapStmt = CaseRanges[i-1].second;
+ }
- // FIXME: TODO.
+ if (OverlapStmt) {
+ // If we have a duplicate, report it.
+ Diag(CR->getLHS()->getLocStart(),
+ diag::err_duplicate_case, OverlapVal.toString());
+ Diag(OverlapStmt->getLHS()->getLocStart(),
+ diag::err_duplicate_case_prev);
+ // FIXME: We really want to remove the bogus case stmt from the substmt,
+ // but we have no way to do this right now.
+ CaseListIsErroneous = true;
+ }
}
}
void f (int z) {
while (z) {
- default: z--; // expected-error {{statement not in switch}}
+ default: z--; // expected-error {{statement not in switch}}
}
}
void foo(int X) {
switch (X) {
- case 42: ; // expected-error {{previous case value}}
- case 5000000000LL: // expected-warning {{overflow}}
- case 42: // expected-error {{duplicate case value}}
+ case 42: ; // expected-error {{previous case value}}
+ case 5000000000LL: // expected-warning {{overflow}}
+ case 42: // expected-error {{duplicate case value}}
;
- case 100 ... 99: ; // expected-warning {{empty case range}}
+ case 100 ... 99: ; // expected-warning {{empty case range}}
+
+ case 43: ; // expected-error {{previous case value}}
+ case 43 ... 45: ; // expected-error {{duplicate case value}}
+
+ case 100 ... 20000:; // expected-error {{previous case value}}
+ case 15000 ... 40000000:; // expected-error {{duplicate case value}}
}
}
void test3(void) {
+ // empty switch;
switch (0);
}