[cfe-commits] [PATCH] Fix diagnostic reporting of previous default statement.
sashan
sashan at zenskg.net
Thu Dec 30 01:00:18 PST 2010
On Thu Dec 23 07:40:49 2010, Douglas Gregor wrote:
>
> On Dec 22, 2010, at 9:25 PM, sashan wrote:
>
> >>
> >>
> >> Comparing just based on the line number won't work, since the two cases could
> >> be in different files, or could appear on the same line.
> >> SourceManager::isBeforeInTranslationUnit() is the appropriate way to compare
> >> two source locations.
> >>
> >> That said, I don't think this is the right solution to the problem. I think
> >> that, instead, we should be processing (and probably also storing) the list of
> >> case/default statements in source order rather than reverse source order, as
> >> we currently are. That would address both the problem you're seeing and the
> >> other problems I had previously alluded to, where we get diagnostics about
> >> case values in the opposite order we expect.
> >>
> >> - Doug
> >
> > Hi Doug
> >
> > Thanks for the feedback. I've attached another patch to address the issue. The
> > patch inserts the switch cases in source order using
> > SourceManager::isBeforeInTranslation unit to determine the order they should be
> > inserted in the list. As a result it fixes the diagnostic error/warning messages
> > in the case of multiple labels in a switch statement, and the overflow warning
> > you alluded to previously. It passes the clang tests.
> >
> > Other than that there are few questions about the attached patch that I'm not
> > sure about as well as the driving philosophy behind some of the code in clang
> > that maybe you can answer.
> >
> > 1. I've used dyn_cast to determine if the switch case is a DefaultStmt or a
> > SwitchStmt. The reason for this is so I can call the DefaultStmt::getDefaultLoc
> > or CaseStmt::getCaseLoc. I believe that it would be better to make a virtual
> > function in the base class, SwitchCase::getSCLoc, to handle this.
>
>
> The dyn_cast is fine here. We don't want a virtual because we're slowly
> eliminating virtuals from the AST.
>
> Your newer patch is technically correct. However, it has severe performance
> implications for switch statements with many cases, because
> SwitchStmt::addSwitchCase() has gone from O(1) to O(N).
>
> I had said before:
>
> >> That said, I don't think this is the right solution to the problem. I think
> >> that, instead, we should be processing (and probably also storing) the list
> >> of case/default statements in source order rather than reverse source
> >> order, as we currently are.
>
>
> It's still not the right solution to look at the source locations. Just
> reverse the list and we'll have the cases in source order.
>
Reversing the list was what I originally (see
http://lists.cs.uiuc.edu/pipermail/cfe-dev/2010-December/012387.html) did but it
doesn't work for this sort of statement:
default:
default:;
Anyway I've attached a patch that effectively reverses the list.
-------------- next part --------------
>From 2c13bc5ae5166831f0318a79828464259b6ca030 Mon Sep 17 00:00:00 2001
From: sashan <sashan at zenskg.net>
Date: Thu, 30 Dec 2010 19:43:36 +1100
Subject: [PATCH] Store the case/default stmts at the end of the list.
Previous code would prepend the case/default statements to the front of the
list. This change reverses the ordering by placing them at the end of the list.
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index b3523a1..538783e 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -738,6 +738,7 @@ class SwitchStmt : public Stmt {
Stmt* SubExprs[END_EXPR];
// This points to a linked list of case and default statements.
SwitchCase *FirstCase;
+ SwitchCase *LastCase;
SourceLocation SwitchLoc;
/// If the SwitchStmt is a switch on an enum value, this records whether
@@ -786,11 +787,7 @@ public:
SubExprs[BODY] = S;
SwitchLoc = SL;
}
- void addSwitchCase(SwitchCase *SC) {
- assert(!SC->getNextSwitchCase() && "case/default already added to a switch");
- SC->setNextSwitchCase(FirstCase);
- FirstCase = SC;
- }
+ void addSwitchCase(SwitchCase *SC);
/// Set a flag in the SwitchStmt indicating that if the 'switch (X)' is a
/// switch over an enum value then all cases have been explicitly covered.
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index acd77be..2b0087a 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -77,6 +77,7 @@ void Stmt::addStmtClass(StmtClass s) {
++getStmtInfoTableEntry(s).Counter;
}
+
static bool StatSwitch = false;
bool Stmt::CollectingStats(bool Enable) {
@@ -530,13 +531,25 @@ void ForStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
}
SwitchStmt::SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond)
- : Stmt(SwitchStmtClass), FirstCase(0), AllEnumCasesCovered(0)
+ : Stmt(SwitchStmtClass), FirstCase(0), LastCase(0),
+ AllEnumCasesCovered(0)
{
setConditionVariable(C, Var);
SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
SubExprs[BODY] = NULL;
}
+void SwitchStmt::addSwitchCase(SwitchCase *SC) {
+ assert(!SC->getNextSwitchCase() && "case/default already added to a switch");
+ if (!FirstCase) {
+ FirstCase = SC;
+ LastCase = SC;
+ } else {
+ LastCase->setNextSwitchCase(SC);
+ LastCase = SC;
+ }
+}
+
VarDecl *SwitchStmt::getConditionVariable() const {
if (!SubExprs[VAR])
return 0;
--
1.7.3.4
More information about the cfe-commits
mailing list