1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 10:16:03 +02:00

Error recovery within enumeration, bug 72685.

This commit is contained in:
Markus Schorn 2008-07-14 10:45:58 +00:00
parent bfa93d84d0
commit d95322ff16
4 changed files with 163 additions and 88 deletions

View file

@ -213,4 +213,33 @@ public class FaultToleranceTests extends AST2BaseTest {
} }
} }
} }
// enum _T { I J, K }; // missing comma
// int i;
public void testEnumProblem() throws Exception {
final String comment= getAboveComment();
for (ParserLanguage lang : ParserLanguage.values()) {
IASTTranslationUnit tu= parse(comment, lang, false, false);
IASTSimpleDeclaration e= getDeclaration(tu, 0);
IASTProblemDeclaration p= getDeclaration(tu, 1);
assertEquals("J, K };", p.getRawSignature());
IASTSimpleDeclaration s= getDeclaration(tu, 2);
assertEquals("int i;", s.getRawSignature());
}
}
// class A {
// enum _T { I J, K }; // missing comma
// int i;
// };
public void testEnumError_Bug72685() throws Exception {
final String comment= getAboveComment();
IASTTranslationUnit tu= parse(comment, ParserLanguage.CPP, false, false);
IASTCompositeTypeSpecifier ct= getCompositeType(tu, 0);
IASTSimpleDeclaration e= getDeclaration(ct, 0);
IASTProblemDeclaration p= getDeclaration(ct, 1);
assertEquals("J, K };", p.getRawSignature());
IASTSimpleDeclaration s= getDeclaration(ct, 2);
assertEquals("int i;", s.getRawSignature());
}
} }

View file

@ -237,6 +237,14 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
ASTNode node = (ASTNode) n; ASTNode node = (ASTNode) n;
return node.getOffset() + node.getLength(); return node.getOffset() + node.getLength();
} }
protected void setRange(IASTNode n, IASTNode from) {
((ASTNode) n).setOffsetAndLength((ASTNode) from);
}
protected void setRange(IASTNode n, int offset, int endOffset) {
((ASTNode) n).setOffsetAndLength(offset, endOffset-offset);
}
protected void adjustLength(IASTNode n, IASTNode endNode) { protected void adjustLength(IASTNode n, IASTNode endNode) {
final int endOffset= calculateEndOffset(endNode); final int endOffset= calculateEndOffset(endNode);
@ -505,7 +513,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
protected IASTProblemDeclaration skipProblemDeclaration(int offset) { protected IASTProblemDeclaration skipProblemDeclaration(int offset) {
failParse(); failParse();
declarationMark= null; declarationMark= null;
int endOffset = skipToSemiOrClosingBrace(offset); int endOffset = skipToSemiOrClosingBrace(offset, false);
IASTProblem problem= createProblem(IProblem.SYNTAX_ERROR, offset, endOffset-offset); IASTProblem problem= createProblem(IProblem.SYNTAX_ERROR, offset, endOffset-offset);
return createProblemDeclaration(problem); return createProblemDeclaration(problem);
} }
@ -513,12 +521,18 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
protected IASTProblemStatement skipProblemStatement(int offset) { protected IASTProblemStatement skipProblemStatement(int offset) {
failParse(); failParse();
declarationMark= null; declarationMark= null;
int endOffset = skipToSemiOrClosingBrace(offset); int endOffset = skipToSemiOrClosingBrace(offset, false);
IASTProblem problem= createProblem(IProblem.SYNTAX_ERROR, offset, endOffset-offset); IASTProblem problem= createProblem(IProblem.SYNTAX_ERROR, offset, endOffset-offset);
return createProblemStatement(problem); return createProblemStatement(problem);
} }
private int skipToSemiOrClosingBrace(int offset) { private IASTProblem skipProblemEnumerator(int offset) {
failParse();
final int endOffset= skipToSemiOrClosingBrace(offset, true);
return createProblem(IProblem.SYNTAX_ERROR, offset, endOffset-offset);
}
private int skipToSemiOrClosingBrace(int offset, boolean eatBrace) {
failParse(); failParse();
declarationMark= null; declarationMark= null;
int depth= 0; int depth= 0;
@ -541,9 +555,12 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
break; break;
case IToken.tRBRACE: case IToken.tRBRACE:
if (--depth <= 0) { if (--depth <= 0) {
if (depth == 0 || offset == endOffset) { if (depth == 0 || offset == endOffset || eatBrace) {
endOffset= consume().getEndOffset(); // consume closing brace endOffset= consume().getEndOffset(); // consume closing brace
} }
if (LTcatchEOF(1) == IToken.tSEMI) {
endOffset= consume().getEndOffset();
}
break loop; break loop;
} }
break; break;
@ -1240,88 +1257,80 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
* @throws BacktrackException request a backtrack * @throws BacktrackException request a backtrack
*/ */
protected IASTEnumerationSpecifier enumSpecifier() throws BacktrackException, EndOfFileException { protected IASTEnumerationSpecifier enumSpecifier() throws BacktrackException, EndOfFileException {
IToken mark = mark(); final IToken mark= mark();
IASTName name = null; final int offset= consume().getOffset();
int startOffset = consume().getOffset(); // t_enum
IASTName name;
if (LT(1) == IToken.tIDENTIFIER) { if (LT(1) == IToken.tIDENTIFIER) {
name = createName(identifier()); name= createName(identifier());
} else } else {
name = createName(); name= createName();
if (LT(1) == IToken.tLBRACE) {
IASTEnumerationSpecifier result = createEnumerationSpecifier();
((ASTNode) result).setOffset(startOffset);
result.setName(name);
consume(); // IToken.tLBRACE
enumLoop: while (true) {
switch (LT(1)) {
case IToken.tRBRACE:
case IToken.tEOC:
break enumLoop;
}
IASTName enumeratorName = null;
int lastOffset = 0;
if (LT(1) == IToken.tIDENTIFIER) {
enumeratorName = createName(identifier());
lastOffset = calculateEndOffset(enumeratorName);
} else {
IToken la = LA(1);
throwBacktrack(la.getOffset(), la.getLength());
return null; // line is never reached, hint for the parser
}
IASTExpression initialValue = null;
if (LT(1) == IToken.tASSIGN) {
consume();
initialValue = constantExpression();
lastOffset = calculateEndOffset(initialValue);
}
IASTEnumerationSpecifier.IASTEnumerator enumerator = null;
if (LT(1) == IToken.tRBRACE) {
enumerator = createEnumerator();
enumerator.setName(enumeratorName);
((ASTNode) enumerator).setOffsetAndLength(
((ASTNode) enumeratorName).getOffset(), lastOffset
- ((ASTNode) enumeratorName).getOffset());
if (initialValue != null) {
enumerator.setValue(initialValue);
}
result.addEnumerator(enumerator);
break;
}
switch (LT(1)) {
case IToken.tCOMMA:
case IToken.tEOC:
consume();
break;
default:
throwBacktrack(mark.getOffset(), mark.getLength());
}
enumerator = createEnumerator();
enumerator.setName(enumeratorName);
((ASTNode) enumerator).setOffsetAndLength(
((ASTNode) enumeratorName).getOffset(), lastOffset
- ((ASTNode) enumeratorName).getOffset());
if (initialValue != null) {
enumerator.setValue(initialValue);
}
result.addEnumerator(enumerator);
}
int lastOffset = consume().getEndOffset();
((ASTNode) result).setLength(lastOffset - startOffset);
return result;
} }
// enumSpecifierAbort
backup(mark); if (LT(1) != IToken.tLBRACE) {
throwBacktrack(mark.getOffset(), mark.getLength()); backup(mark);
return null; throwBacktrack(mark);
}
final IASTEnumerationSpecifier result= createEnumerationSpecifier();
result.setName(name);
boolean needComma= false;
int endOffset= consume().getEndOffset(); // IToken.tLBRACE
int problemOffset= endOffset;
try {
loop: while (true) {
switch (LTcatchEOF(1)) {
case 0: // eof
endOffset= eofOffset;
break loop;
case IToken.tRBRACE:
endOffset= consume().getEndOffset();
break loop;
case IToken.tEOC:
break loop;
case IToken.tCOMMA:
if (!needComma) {
problemOffset= LA(1).getOffset();
throw backtrack;
}
endOffset= consume().getEndOffset();
needComma= false;
continue loop;
case IToken.tIDENTIFIER:
case IToken.tCOMPLETION:
problemOffset= LA(1).getOffset();
if (needComma)
throw backtrack;
final IASTEnumerator enumerator= createEnumerator();
final IASTName etorName= createName(identifier());
enumerator.setName(etorName);
endOffset= calculateEndOffset(etorName);
setRange(enumerator, problemOffset, endOffset);
result.addEnumerator(enumerator);
if (LTcatchEOF(1) == IToken.tASSIGN) {
problemOffset= consume().getOffset();
final IASTExpression value= constantExpression();
enumerator.setValue(value);
adjustLength(enumerator, value);
endOffset= calculateEndOffset(value);
}
needComma= true;
continue loop;
default:
problemOffset= LA(1).getOffset();
throw backtrack;
}
}
} catch (EndOfFileException eof) {
throwBacktrack(createProblem(IProblem.SYNTAX_ERROR, problemOffset, eofOffset-problemOffset), result);
} catch (BacktrackException bt) {
IASTProblem problem= skipProblemEnumerator(problemOffset);
throwBacktrack(problem, result);
}
setRange(result, offset, endOffset);
return result;
} }
protected abstract IASTStatement statement() throws EndOfFileException, BacktrackException; protected abstract IASTStatement statement() throws EndOfFileException, BacktrackException;

View file

@ -417,8 +417,17 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
dtor= e.declarator; dtor= e.declarator;
} }
backup( e.currToken ); backup( e.currToken );
} catch (BacktrackException e) {
IASTNode node= e.getNodeBeforeProblem();
if (node instanceof IASTDeclSpecifier) {
IASTSimpleDeclaration d= createSimpleDeclaration();
d.setDeclSpecifier((IASTDeclSpecifier) node);
setRange(d, node);
throwBacktrack(e.getProblem(), d);
}
throw e;
} }
IASTDeclarator[] declarators= {dtor}; IASTDeclarator[] declarators= {dtor};
while (LTcatchEOF(1) == IToken.tCOMMA) { while (LTcatchEOF(1) == IToken.tCOMMA) {
consume(); consume();
@ -989,6 +998,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
IToken identifier= null; IToken identifier= null;
IASTDeclSpecifier result= null; IASTDeclSpecifier result= null;
IASTExpression typeofExpression= null; IASTExpression typeofExpression= null;
IASTProblem problem= null;
boolean encounteredRawType= false; boolean encounteredRawType= false;
boolean encounteredTypename= false; boolean encounteredTypename= false;
@ -1174,8 +1184,13 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
try { try {
result= enumSpecifier(); result= enumSpecifier();
} catch (BacktrackException bt) { } catch (BacktrackException bt) {
// this is an elaborated class specifier if (bt.getNodeBeforeProblem() instanceof IASTDeclSpecifier) {
result= elaboratedTypeSpecifier(); result= (IASTDeclSpecifier) bt.getNodeBeforeProblem();
problem = bt.getProblem();
break declSpecifiers;
} else {
result= elaboratedTypeSpecifier();
}
} }
endOffset= calculateEndOffset(result); endOffset= calculateEndOffset(result);
encounteredTypename= true; encounteredTypename= true;
@ -1240,6 +1255,9 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
} }
} }
((ASTNode) result).setOffsetAndLength(offset, endOffset - offset); ((ASTNode) result).setOffsetAndLength(offset, endOffset - offset);
if (problem != null)
throwBacktrack(problem, result);
return result; return result;
} }

View file

@ -2284,6 +2284,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
declSpec= (ICPPASTDeclSpecifier) e.declSpec; declSpec= (ICPPASTDeclSpecifier) e.declSpec;
dtor= e.declarator; dtor= e.declarator;
backup(e.currToken); backup(e.currToken);
} catch (BacktrackException e) {
IASTNode node= e.getNodeBeforeProblem();
if (node instanceof ICPPASTDeclSpecifier && validWithoutDtor(declOption, (ICPPASTDeclSpecifier) node)) {
IASTSimpleDeclaration d= createSimpleDeclaration();
d.setDeclSpecifier((IASTDeclSpecifier) node);
setRange(d, node);
throwBacktrack(e.getProblem(), d);
}
throw e;
} }
IASTDeclarator[] declarators= {dtor}; IASTDeclarator[] declarators= {dtor};
@ -2570,6 +2579,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
ITokenDuple identifier= null; ITokenDuple identifier= null;
ICPPASTDeclSpecifier result= null; ICPPASTDeclSpecifier result= null;
IASTExpression typeofExpression= null; IASTExpression typeofExpression= null;
IASTProblem problem= null;
boolean isTypename = false; boolean isTypename = false;
boolean encounteredRawType= false; boolean encounteredRawType= false;
@ -2779,7 +2789,13 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
try { try {
result= (ICPPASTDeclSpecifier) enumSpecifier(); result= (ICPPASTDeclSpecifier) enumSpecifier();
} catch (BacktrackException bt) { } catch (BacktrackException bt) {
result= elaboratedTypeSpecifier(); if (bt.getNodeBeforeProblem() instanceof ICPPASTDeclSpecifier) {
result= (ICPPASTDeclSpecifier) bt.getNodeBeforeProblem();
problem= bt.getProblem();
break declSpecifiers;
} else {
result= elaboratedTypeSpecifier();
}
} }
endOffset= calculateEndOffset(result); endOffset= calculateEndOffset(result);
encounteredTypename= true; encounteredTypename= true;
@ -2843,6 +2859,9 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
} }
} }
((ASTNode) result).setOffsetAndLength(offset, endOffset - offset); ((ASTNode) result).setOffsetAndLength(offset, endOffset - offset);
if (problem != null) {
throwBacktrack(problem, result);
}
return result; return result;
} }