1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-19 06:55:23 +02:00

Empty versus no exception specification, bug 86943.

This commit is contained in:
Markus Schorn 2008-08-05 09:44:53 +00:00
parent fe9a0ddd82
commit 1aae35abf1
9 changed files with 71 additions and 49 deletions

View file

@ -5962,4 +5962,28 @@ public class AST2CPPTests extends AST2BaseTest {
public void testTypeIdForPtrToMember_Bug242197() throws Exception { public void testTypeIdForPtrToMember_Bug242197() throws Exception {
parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP); parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP);
} }
// void test1();
// void test2() throw ();
// void test3() throw (int);
public void testEmptyExceptionSpecification_Bug86943() throws Exception {
IASTTranslationUnit tu= parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP);
IASTSimpleDeclaration d= getDeclaration(tu, 0);
ICPPASTFunctionDeclarator fdtor= (ICPPASTFunctionDeclarator) d.getDeclarators()[0];
IASTTypeId[] specs= fdtor.getExceptionSpecification();
assertEquals(0, specs.length);
assertSame(ICPPASTFunctionDeclarator.NO_EXCEPTION_SPECIFICATION, specs);
d= getDeclaration(tu, 1);
fdtor= (ICPPASTFunctionDeclarator) d.getDeclarators()[0];
specs= fdtor.getExceptionSpecification();
assertEquals(0, specs.length);
assertNotSame(ICPPASTFunctionDeclarator.NO_EXCEPTION_SPECIFICATION, specs);
d= getDeclaration(tu, 2);
fdtor= (ICPPASTFunctionDeclarator) d.getDeclarators()[0];
specs= fdtor.getExceptionSpecification();
assertEquals(1, specs.length);
}
} }

View file

@ -31,7 +31,7 @@ public class ExceptionTest extends ChangeGeneratorTest {
@Override @Override
protected void setUp() throws Exception { protected void setUp() throws Exception {
source = "void foo(int parameter) throw (int){\n}\n\n"; //$NON-NLS-1$ source = "void foo(int parameter) throw (int){\n}\n\n"; //$NON-NLS-1$
expectedSource = "void foo(int parameter){\n}\n\n"; //$NON-NLS-1$ expectedSource = "void foo(int parameter) throw (){\n}\n\n"; //$NON-NLS-1$
super.setUp(); super.setUp();
} }

View file

@ -295,14 +295,15 @@ public class ASTStringUtil {
buffer.append("=0 "); //$NON-NLS-1$ buffer.append("=0 "); //$NON-NLS-1$
} }
final IASTTypeId[] exceptionTypeIds= cppFunctionDecl.getExceptionSpecification(); final IASTTypeId[] exceptionTypeIds= cppFunctionDecl.getExceptionSpecification();
if (exceptionTypeIds.length > 0) { if (exceptionTypeIds != ICPPASTFunctionDeclarator.NO_EXCEPTION_SPECIFICATION) {
buffer.append(Keywords.THROW).append(' '); buffer.append(Keywords.THROW).append(" ("); //$NON-NLS-1$
for (int i= 0; i < exceptionTypeIds.length; i++) { for (int i= 0; i < exceptionTypeIds.length; i++) {
if (i > 0) { if (i > 0) {
buffer.append(COMMA_SPACE); buffer.append(COMMA_SPACE);
} }
appendTypeIdString(buffer, exceptionTypeIds[i]); appendTypeIdString(buffer, exceptionTypeIds[i]);
} }
buffer.append(')');
} }
} }
} else if (declarator instanceof IASTFieldDeclarator) { } else if (declarator instanceof IASTFieldDeclarator) {

View file

@ -22,6 +22,12 @@ import org.eclipse.cdt.core.dom.ast.IASTTypeId;
*/ */
public interface ICPPASTFunctionDeclarator extends IASTStandardFunctionDeclarator { public interface ICPPASTFunctionDeclarator extends IASTStandardFunctionDeclarator {
/**
* Used as return value for {@link #getExceptionSpecification()}.
* @since 5.1
*/
public static final IASTTypeId[] NO_EXCEPTION_SPECIFICATION = {};
/** /**
* <code>EXCEPTION_TYPEID</code> represents the type IDs throws in the * <code>EXCEPTION_TYPEID</code> represents the type IDs throws in the
* exception specification. * exception specification.
@ -60,7 +66,9 @@ public interface ICPPASTFunctionDeclarator extends IASTStandardFunctionDeclarato
public void setPureVirtual(boolean isPureVirtual); public void setPureVirtual(boolean isPureVirtual);
/** /**
* Get the exception specification. * Returns an array of type-ids representing the exception specification. The return value
* {@link #NO_EXCEPTION_SPECIFICATION} indicates that no exceptions are specified, whereas
* {@link IASTTypeId#EMPTY_TYPEID_ARRAY} is used for an empty exception specification.
*/ */
public IASTTypeId[] getExceptionSpecification(); public IASTTypeId[] getExceptionSpecification();
@ -69,6 +77,13 @@ public interface ICPPASTFunctionDeclarator extends IASTStandardFunctionDeclarato
*/ */
public void addExceptionSpecificationTypeId(IASTTypeId typeId); public void addExceptionSpecificationTypeId(IASTTypeId typeId);
/**
* Configures the declarator with an empty exception specification (as opposed to having none).
*
* @since 5.1
*/
public void setEmptyExceptionSpecification();
/** /**
* Get function scope this node represents. Returns <code>null</code>, if this declarator does not * Get function scope this node represents. Returns <code>null</code>, if this declarator does not
* declare a function-prototype or function-definition. * declare a function-prototype or function-definition.

View file

@ -284,14 +284,12 @@ public class ArrayUtil {
* The position of the last non-null element in the array must also be known. * The position of the last non-null element in the array must also be known.
*/ */
public static Object[] removeNullsAfter(Class<?> c, Object[] array, int index) { public static Object[] removeNullsAfter(Class<?> c, Object[] array, int index) {
if( array == null || index < 0)
return (Object[]) Array.newInstance( c, 0 );
final int newLen= index+1; final int newLen= index+1;
if( array.length == newLen) if (array != null && array.length == newLen)
return array; return array;
Object[] newArray = (Object[]) Array.newInstance(c, newLen); Object[] newArray = (Object[]) Array.newInstance(c, newLen);
if (array != null && newLen > 0)
System.arraycopy(array, 0, newArray, 0, newLen); System.arraycopy(array, 0, newArray, 0, newLen);
return newArray; return newArray;
} }

View file

@ -29,7 +29,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements ICPPASTFunctionDeclarator { public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements ICPPASTFunctionDeclarator {
private IASTParameterDeclaration[] parameters = null; private IASTParameterDeclaration[] parameters = null;
private int parametersPos = -1; private int parametersPos = -1;
private IASTTypeId[] typeIds = null; private IASTTypeId[] typeIds = NO_EXCEPTION_SPECIFICATION;
private int typeIdsPos = -1; private int typeIdsPos = -1;
private boolean varArgs; private boolean varArgs;
@ -86,12 +86,13 @@ public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements ICPPAS
} }
public IASTTypeId[] getExceptionSpecification() { public IASTTypeId[] getExceptionSpecification() {
if (typeIds == null)
return IASTTypeId.EMPTY_TYPEID_ARRAY;
return typeIds= ArrayUtil.trimAt(IASTTypeId.class, typeIds, typeIdsPos); return typeIds= ArrayUtil.trimAt(IASTTypeId.class, typeIds, typeIdsPos);
} }
public void setEmptyExceptionSpecification() {
typeIds= IASTTypeId.EMPTY_TYPEID_ARRAY;
}
public void addExceptionSpecificationTypeId(IASTTypeId typeId) { public void addExceptionSpecificationTypeId(IASTTypeId typeId) {
if (typeId != null) { if (typeId != null) {
typeIds = (IASTTypeId[]) ArrayUtil.append(IASTTypeId.class, typeIds, ++typeIdsPos, typeId); typeIds = (IASTTypeId[]) ArrayUtil.append(IASTTypeId.class, typeIds, ++typeIdsPos, typeId);

View file

@ -170,9 +170,7 @@ import org.eclipse.cdt.internal.core.parser.token.TokenFactory;
public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
private static final int DEFAULT_PARM_LIST_SIZE = 4; private static final int DEFAULT_PARM_LIST_SIZE = 4;
private static final int DEFAULT_POINTEROPS_LIST_SIZE = 4; private static final int DEFAULT_POINTEROPS_LIST_SIZE = 4;
private static final int DEFAULT_SIZE_EXCEPTIONS_LIST = 2;
private static final int DEFAULT_CATCH_HANDLER_LIST_SIZE= 4; private static final int DEFAULT_CATCH_HANDLER_LIST_SIZE= 4;
private static final int DEFAULT_PARAMETER_LIST_SIZE= 4;
private static final ASTVisitor EMPTY_VISITOR = new ASTVisitor() {}; private static final ASTVisitor EMPTY_VISITOR = new ASTVisitor() {};
private static enum DtorStrategy {PREFER_FUNCTION, PREFER_NESTED} private static enum DtorStrategy {PREFER_FUNCTION, PREFER_NESTED}
@ -3434,10 +3432,9 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
IToken last = consume(IToken.tLPAREN); IToken last = consume(IToken.tLPAREN);
int startOffset= last.getOffset(); int startOffset= last.getOffset();
boolean seenParameter= false; boolean seenParameter= false;
boolean encounteredVarArgs= false;
List<IASTParameterDeclaration> parameters= null;
int endOffset= last.getEndOffset(); int endOffset= last.getEndOffset();
final ICPPASTFunctionDeclarator fc= createFunctionDeclarator();
paramLoop: while(true) { paramLoop: while(true) {
switch (LT(1)) { switch (LT(1)) {
case IToken.tRPAREN: case IToken.tRPAREN:
@ -3446,7 +3443,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
break paramLoop; break paramLoop;
case IToken.tELLIPSIS: case IToken.tELLIPSIS:
endOffset= consume().getEndOffset(); endOffset= consume().getEndOffset();
encounteredVarArgs = true; fc.setVarArgs(true);
break; break;
case IToken.tCOMMA: case IToken.tCOMMA:
endOffset= consume().getEndOffset(); endOffset= consume().getEndOffset();
@ -3457,10 +3454,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
throwBacktrack(startOffset, endOffset - startOffset); throwBacktrack(startOffset, endOffset - startOffset);
IASTParameterDeclaration pd = parameterDeclaration(); IASTParameterDeclaration pd = parameterDeclaration();
fc.addParameterDeclaration(pd);
endOffset = calculateEndOffset(pd); endOffset = calculateEndOffset(pd);
if (parameters == null)
parameters = new ArrayList<IASTParameterDeclaration>(DEFAULT_PARAMETER_LIST_SIZE);
parameters.add(pd);
seenParameter = true; seenParameter = true;
break; break;
} }
@ -3469,20 +3464,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
// Consume any number of __attribute__ tokens after the parameters // Consume any number of __attribute__ tokens after the parameters
__attribute_decl_seq(supportAttributeSpecifiers, false); __attribute_decl_seq(supportAttributeSpecifiers, false);
boolean isConst= false;
boolean isVolatile= false;
boolean isPureVirtual= false;
ArrayList<IASTTypeId> exceptionSpecIds= null;
// cv-qualifiers // cv-qualifiers
cvloop: while(true) { cvloop: while(true) {
switch(LT(1)) { switch(LT(1)) {
case IToken.t_const: case IToken.t_const:
isConst= true; fc.setConst(true);
endOffset= consume().getEndOffset(); endOffset= consume().getEndOffset();
break; break;
case IToken.t_volatile: case IToken.t_volatile:
isVolatile= true; fc.setVolatile(true);
endOffset= consume().getEndOffset(); endOffset= consume().getEndOffset();
break; break;
default: default:
@ -3492,7 +3482,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
// throws clause // throws clause
if (LT(1) == IToken.t_throw) { if (LT(1) == IToken.t_throw) {
exceptionSpecIds = new ArrayList<IASTTypeId>(DEFAULT_SIZE_EXCEPTIONS_LIST); fc.setEmptyExceptionSpecification();
consume(); // throw consume(); // throw
consume(IToken.tLPAREN); consume(IToken.tLPAREN);
@ -3509,7 +3499,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
int thoffset= LA(1).getOffset(); int thoffset= LA(1).getOffset();
IASTTypeId typeId= typeId(DeclarationOptions.TYPEID); IASTTypeId typeId= typeId(DeclarationOptions.TYPEID);
if (typeId != null) { if (typeId != null) {
exceptionSpecIds.add(typeId); fc.addExceptionSpecificationTypeId(typeId);
} else { } else {
int thendoffset= LA(1).getOffset(); int thendoffset= LA(1).getOffset();
if (thoffset == thendoffset) { if (thoffset == thendoffset) {
@ -3519,7 +3509,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
IASTProblemTypeId typeIdProblem = createTypeIDProblem(); IASTProblemTypeId typeIdProblem = createTypeIDProblem();
typeIdProblem.setProblem(p); typeIdProblem.setProblem(p);
((ASTNode) typeIdProblem).setOffsetAndLength(((ASTNode) p)); ((ASTNode) typeIdProblem).setOffsetAndLength(((ASTNode) p));
exceptionSpecIds.add(typeIdProblem); fc.addExceptionSpecificationTypeId(typeIdProblem);
} }
break; break;
} }
@ -3535,24 +3525,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
if (image.length == 1 && image[0] == '0') { if (image.length == 1 && image[0] == '0') {
consume(); // tASSIGN consume(); // tASSIGN
endOffset= consume().getEndOffset(); // tINTEGER endOffset= consume().getEndOffset(); // tINTEGER
isPureVirtual= true; fc.setPureVirtual(true);
} }
} }
final ICPPASTFunctionDeclarator fc= createFunctionDeclarator();
fc.setVarArgs(encounteredVarArgs);
fc.setConst(isConst);
fc.setVolatile(isVolatile);
fc.setPureVirtual(isPureVirtual);
if (parameters != null) {
for (IASTParameterDeclaration param : parameters) {
fc.addParameterDeclaration(param);
}
}
if (exceptionSpecIds != null)
for (IASTTypeId exception : exceptionSpecIds) {
fc.addExceptionSpecificationTypeId(exception);
}
((ASTNode) fc).setOffsetAndLength(startOffset, endOffset-startOffset); ((ASTNode) fc).setOffsetAndLength(startOffset, endOffset-startOffset);
return fc; return fc;
} }

View file

@ -146,7 +146,7 @@ public class DeclaratorWriter extends NodeWriter {
} }
protected void writeExceptionSpecification(ICPPASTFunctionDeclarator funcDec, IASTTypeId[] exceptions) { protected void writeExceptionSpecification(ICPPASTFunctionDeclarator funcDec, IASTTypeId[] exceptions) {
if(exceptions.length != 0) { if (exceptions != ICPPASTFunctionDeclarator.NO_EXCEPTION_SPECIFICATION) {
scribe.printSpace(); scribe.printSpace();
scribe.print(THROW); scribe.print(THROW);
scribe.print('('); scribe.print('(');

View file

@ -65,6 +65,13 @@ public class ModifiedASTDeclaratorWriter extends DeclaratorWriter {
@Override @Override
protected void writeExceptionSpecification(ICPPASTFunctionDeclarator funcDec, IASTTypeId[] exceptions ) { protected void writeExceptionSpecification(ICPPASTFunctionDeclarator funcDec, IASTTypeId[] exceptions ) {
IASTTypeId[] modifiedExceptions = modificationHelper.createModifiedChildArray(funcDec, exceptions, IASTTypeId.class); IASTTypeId[] modifiedExceptions = modificationHelper.createModifiedChildArray(funcDec, exceptions, IASTTypeId.class);
// it makes a difference whether the exception array is identical to
// ICPPASTFunctionDeclarator.NO_EXCEPTION_SPECIFICATION
if (modifiedExceptions.length == 0 &&
exceptions == ICPPASTFunctionDeclarator.NO_EXCEPTION_SPECIFICATION) {
modifiedExceptions= ICPPASTFunctionDeclarator.NO_EXCEPTION_SPECIFICATION;
}
super.writeExceptionSpecification(funcDec, modifiedExceptions); super.writeExceptionSpecification(funcDec, modifiedExceptions);
} }