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:
parent
fe9a0ddd82
commit
1aae35abf1
9 changed files with 71 additions and 49 deletions
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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('(');
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue