1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-18 22:45: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 {
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
protected void setUp() throws Exception {
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();
}

View file

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

View file

@ -22,6 +22,12 @@ import org.eclipse.cdt.core.dom.ast.IASTTypeId;
*/
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
* exception specification.
@ -60,7 +66,9 @@ public interface ICPPASTFunctionDeclarator extends IASTStandardFunctionDeclarato
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();
@ -69,6 +77,13 @@ public interface ICPPASTFunctionDeclarator extends IASTStandardFunctionDeclarato
*/
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
* 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.
*/
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;
if( array.length == newLen)
if (array != null && array.length == newLen)
return array;
Object[] newArray = (Object[]) Array.newInstance(c, newLen);
if (array != null && newLen > 0)
System.arraycopy(array, 0, newArray, 0, newLen);
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 {
private IASTParameterDeclaration[] parameters = null;
private int parametersPos = -1;
private IASTTypeId[] typeIds = null;
private IASTTypeId[] typeIds = NO_EXCEPTION_SPECIFICATION;
private int typeIdsPos = -1;
private boolean varArgs;
@ -86,12 +86,13 @@ public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements ICPPAS
}
public IASTTypeId[] getExceptionSpecification() {
if (typeIds == null)
return IASTTypeId.EMPTY_TYPEID_ARRAY;
return typeIds= ArrayUtil.trimAt(IASTTypeId.class, typeIds, typeIdsPos);
}
public void setEmptyExceptionSpecification() {
typeIds= IASTTypeId.EMPTY_TYPEID_ARRAY;
}
public void addExceptionSpecificationTypeId(IASTTypeId typeId) {
if (typeId != null) {
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 {
private static final int DEFAULT_PARM_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_PARAMETER_LIST_SIZE= 4;
private static final ASTVisitor EMPTY_VISITOR = new ASTVisitor() {};
private static enum DtorStrategy {PREFER_FUNCTION, PREFER_NESTED}
@ -3434,10 +3432,9 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
IToken last = consume(IToken.tLPAREN);
int startOffset= last.getOffset();
boolean seenParameter= false;
boolean encounteredVarArgs= false;
List<IASTParameterDeclaration> parameters= null;
int endOffset= last.getEndOffset();
final ICPPASTFunctionDeclarator fc= createFunctionDeclarator();
paramLoop: while(true) {
switch (LT(1)) {
case IToken.tRPAREN:
@ -3446,7 +3443,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
break paramLoop;
case IToken.tELLIPSIS:
endOffset= consume().getEndOffset();
encounteredVarArgs = true;
fc.setVarArgs(true);
break;
case IToken.tCOMMA:
endOffset= consume().getEndOffset();
@ -3457,10 +3454,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
throwBacktrack(startOffset, endOffset - startOffset);
IASTParameterDeclaration pd = parameterDeclaration();
fc.addParameterDeclaration(pd);
endOffset = calculateEndOffset(pd);
if (parameters == null)
parameters = new ArrayList<IASTParameterDeclaration>(DEFAULT_PARAMETER_LIST_SIZE);
parameters.add(pd);
seenParameter = true;
break;
}
@ -3469,20 +3464,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
// Consume any number of __attribute__ tokens after the parameters
__attribute_decl_seq(supportAttributeSpecifiers, false);
boolean isConst= false;
boolean isVolatile= false;
boolean isPureVirtual= false;
ArrayList<IASTTypeId> exceptionSpecIds= null;
// cv-qualifiers
cvloop: while(true) {
switch(LT(1)) {
case IToken.t_const:
isConst= true;
fc.setConst(true);
endOffset= consume().getEndOffset();
break;
case IToken.t_volatile:
isVolatile= true;
fc.setVolatile(true);
endOffset= consume().getEndOffset();
break;
default:
@ -3492,7 +3482,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
// throws clause
if (LT(1) == IToken.t_throw) {
exceptionSpecIds = new ArrayList<IASTTypeId>(DEFAULT_SIZE_EXCEPTIONS_LIST);
fc.setEmptyExceptionSpecification();
consume(); // throw
consume(IToken.tLPAREN);
@ -3509,7 +3499,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
int thoffset= LA(1).getOffset();
IASTTypeId typeId= typeId(DeclarationOptions.TYPEID);
if (typeId != null) {
exceptionSpecIds.add(typeId);
fc.addExceptionSpecificationTypeId(typeId);
} else {
int thendoffset= LA(1).getOffset();
if (thoffset == thendoffset) {
@ -3519,7 +3509,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
IASTProblemTypeId typeIdProblem = createTypeIDProblem();
typeIdProblem.setProblem(p);
((ASTNode) typeIdProblem).setOffsetAndLength(((ASTNode) p));
exceptionSpecIds.add(typeIdProblem);
fc.addExceptionSpecificationTypeId(typeIdProblem);
}
break;
}
@ -3535,24 +3525,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
if (image.length == 1 && image[0] == '0') {
consume(); // tASSIGN
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);
return fc;
}

View file

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

View file

@ -65,6 +65,13 @@ public class ModifiedASTDeclaratorWriter extends DeclaratorWriter {
@Override
protected void writeExceptionSpecification(ICPPASTFunctionDeclarator funcDec, IASTTypeId[] exceptions ) {
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);
}