1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Support for exception specifications by Sebastian Moss, bug 252697

This commit is contained in:
Markus Schorn 2008-11-10 15:46:54 +00:00
parent e9f3d2a3a2
commit c656d4d2ee
23 changed files with 655 additions and 65 deletions

View file

@ -873,6 +873,82 @@ public class IndexUpdateTests extends IndexTestBase {
checkValue("C::mem", null);
checkValue("e0", 0L);
}
// class A {
// public: void foo();
// };
// class A {
// public: void foo() throw();
// };
// class A {
// public: void foo() throw(int, double);
// };
// class A {
// public: void foo() throw();
// };
// class A {
// public: void foo();
// };
public void testExceptionSpecification() throws Exception {
ICPPMethod method;
IType[] exceptionSpec;
setupFile(5, true);
fIndex.acquireReadLock();
try {
method = (ICPPMethod) findBinding("A::foo");
exceptionSpec = method.getExceptionSpecification();
assertNull(exceptionSpec);
} finally {
fIndex.releaseReadLock();
}
updateFile();
fIndex.acquireReadLock();
try {
method = (ICPPMethod) findBinding("A::foo");
exceptionSpec = method.getExceptionSpecification();
assertEquals(0, exceptionSpec.length);
} finally {
fIndex.releaseReadLock();
}
updateFile();
fIndex.acquireReadLock();
try {
method = (ICPPMethod) findBinding("A::foo");
exceptionSpec = method.getExceptionSpecification();
assertNotNull(exceptionSpec);
assertEquals(2, exceptionSpec.length);
assertEquals("int", ASTTypeUtil.getType(exceptionSpec[0]));
assertEquals("double", ASTTypeUtil.getType(exceptionSpec[1]));
} finally {
fIndex.releaseReadLock();
}
updateFile();
fIndex.acquireReadLock();
try {
method = (ICPPMethod) findBinding("A::foo");
exceptionSpec = method.getExceptionSpecification();
assertEquals(0, exceptionSpec.length);
} finally {
fIndex.releaseReadLock();
}
updateFile();
fIndex.acquireReadLock();
try {
method = (ICPPMethod) findBinding("A::foo");
exceptionSpec = method.getExceptionSpecification();
assertNull(exceptionSpec);
} finally {
fIndex.releaseReadLock();
}
}
// int global;
// struct C {int mem;};

View file

@ -15,6 +15,7 @@ import junit.framework.Test;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
@ -246,5 +247,59 @@ public class MethodTests extends PDOMTestBase {
assertFalse(type.isConst());
assertFalse(type.isVolatile());
}
public void testNoExceptionSpecification() throws Exception {
IBinding[] bindings = findQualifiedName(pdom, "Class1::noExceptionSpecMethod");
assertEquals(1, bindings.length);
ICPPMethod method = (ICPPMethod) bindings[0];
IType[] exceptionSpec = method.getExceptionSpecification();
assertNull(exceptionSpec);
}
public void testEmptyExceptionSpecification() throws Exception {
IBinding[] bindings = findQualifiedName(pdom, "Class1::emptyExceptionSpecMethod");
assertEquals(1, bindings.length);
ICPPMethod method = (ICPPMethod) bindings[0];
IType[] exceptionSpec = method.getExceptionSpecification();
assertEquals(0, exceptionSpec.length);
}
public void testNonEmptyExceptionSpecification() throws Exception {
IBinding[] bindings = findQualifiedName(pdom, "Class1::nonEmptyExceptionSpecMethod");
assertEquals(1, bindings.length);
ICPPMethod method = (ICPPMethod) bindings[0];
IType[] exceptionSpec = method.getExceptionSpecification();
assertEquals(1, exceptionSpec.length);
assertEquals(IBasicType.t_int, ((ICPPBasicType) exceptionSpec[0]).getType());
}
public void testImplicitCtorExceptionSpec() throws Exception {
IBinding[] bindings = findQualifiedPossiblyImplicit(pdom, "D::D");
// get both default ctor + copy ctor
assertEquals(2, bindings.length);
ICPPMethod method = (ICPPMethod) bindings[0];
IType[] exceptionSpec = method.getExceptionSpecification();
assertNull(exceptionSpec);
}
public void testImplicitCopyCtorExceptionSpec() throws Exception {
IBinding[] bindings = findQualifiedPossiblyImplicit(pdom, "D::D");
// get both default ctor + copy ctor
assertEquals(2, bindings.length);
ICPPMethod method = (ICPPMethod) bindings[1];
IType[] exceptionSpec = method.getExceptionSpecification();
assertEquals(0, exceptionSpec.length);
}
public void testImplicitDtorExceptionSpec() throws Exception {
IBinding[] bindings = findQualifiedPossiblyImplicit(pdom, "D::~D");
assertEquals(1, bindings.length);
ICPPMethod method = (ICPPMethod) bindings[0];
IType[] exceptionSpec = method.getExceptionSpecification();
assertEquals(2, exceptionSpec.length);
int t1= ((ICPPBasicType) exceptionSpec[0]).getType();
int t2= ((ICPPBasicType) exceptionSpec[1]).getType();
assertEquals(IBasicType.t_int, Math.min(t1, t2));
assertEquals(IBasicType.t_double, Math.max(t1, t2));
}
}

View file

@ -120,6 +120,15 @@ public class PDOMTestBase extends BaseTestCase {
}
return pdom.findBindings(pattern, true, IndexFilter.ALL_DECLARED, PROGRESS);
}
protected IBinding[] findQualifiedPossiblyImplicit(PDOM pdom, String name) throws CoreException {
String[] segments = name.split("::");
Pattern[] pattern = new Pattern[segments.length];
for (int i = 0; i < segments.length; i++) {
pattern[i] = Pattern.compile(segments[i]);
}
return pdom.findBindings(pattern, true, IndexFilter.ALL, PROGRESS);
}
protected IBinding[] findUnqualifiedName(PDOM pdom, String name) throws CoreException {
String[] segments = name.split("::");

View file

@ -4,30 +4,48 @@ public:
virtual void inheritedMethod();
virtual void pureVirtualMethod() = 0;
virtual void overriddenMethod();
void noExceptionSpecMethod();
void emptyExceptionSpecMethod() throw();
void nonEmptyExceptionSpecMethod() throw(int);
inline int inlineMethod();
static int staticMethod();
int varArgsMethod(...);
int constMethod() const;
int volatileMethod() volatile;
int constVolatileMethod() const volatile;
// Here, const/volatile applies to the return value, not the method
const int *notConstMethod();
volatile int *notVolatileMethod();
const volatile int *notConstVolatileMethod();
Class1();
virtual ~Class1() = 0;
};
struct A {
A();
A(const A&) throw();
~A() throw(int);
};
struct B {
B() throw();
B(const B&) throw();
~B() throw(double);
};
struct D : public A, public B {};
class Class2 : public Class1 {
public:
void pureVirtualMethod();
void overriddenMethod();
void overloadedMethod();
void overloadedMethod(int p1);
Class2();
~Class2();
};
@ -66,7 +84,7 @@ Class2::~Class2() {
}
class Class3 {
int defaultMethod();
int defaultMethod();
private:
void privateMethod();
protected:
@ -85,23 +103,23 @@ int main() {
pc1->pureVirtualMethod();
pc1->pureVirtualMethod();
pc1->overriddenMethod();
pc1->overriddenMethod();
pc1->overriddenMethod();
c2.inheritedMethod();
pc2->inheritedMethod();
c2.pureVirtualMethod();
c2.pureVirtualMethod();
pc2->pureVirtualMethod();
c2.overriddenMethod();
c2.overriddenMethod();
c2.overriddenMethod();
pc2->overriddenMethod();
c2.overloadedMethod();
pc2->overloadedMethod();

View file

@ -6,24 +6,23 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Andrew Niefer (IBM Corporation) - initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
/*
* Created on Mar 15, 2005
*/
package org.eclipse.cdt.core.dom.ast.cpp;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IType;
/**
* @author aniefer
* Binding for c++ functions.
*
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface ICPPFunction extends IFunction, ICPPBinding {
/**
/**
* does this function have the mutable storage class specifier
* @throws DOMException
*/
@ -39,4 +38,11 @@ public interface ICPPFunction extends IFunction, ICPPBinding {
* @since 5.0
*/
public boolean isExternC() throws DOMException;
/**
* Returns the exception specification for this function or <code>null</code> if there
* is no exception specification.
* @since 5.1
*/
public IType[] getExceptionSpecification() throws DOMException;
}

View file

@ -143,4 +143,8 @@ public class CPPDeferredFunctionInstance extends CPPUnknownBinding implements IC
public IBinding resolveParameter(IASTParameterDeclaration param) {
return null;
}
public IType[] getExceptionSpecification() throws DOMException {
return ((ICPPFunction)getTemplateDefinition()).getExceptionSpecification();
}
}

View file

@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Andrew Niefer (IBM Corporation) - initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -24,11 +24,13 @@ import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
@ -44,10 +46,10 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.core.runtime.PlatformObject;
/**
* @author aniefer
* Binding for c++ function
*/
public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInternalFunction {
public static class CPPFunctionProblem extends ProblemBinding implements ICPPFunction {
public CPPFunctionProblem(IASTNode node, int id, char[] arg) {
super(node, id, arg);
@ -97,6 +99,9 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
public boolean takesVarArgs() throws DOMException {
throw new DOMException(this);
}
public IType[] getExceptionSpecification() throws DOMException {
throw new DOMException(this);
}
}
protected ICPPASTFunctionDeclarator[] declarations;
@ -213,7 +218,7 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
public IParameter[] getParameters() {
IASTStandardFunctionDeclarator dtor = (definition != null) ? definition : declarations[0];
IASTStandardFunctionDeclarator dtor = getPreferredDtor();
IASTParameterDeclaration[] params = dtor.getParameters();
int size = params.length;
IParameter[] result = new IParameter[ size ];
@ -516,15 +521,8 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
}
public boolean takesVarArgs() {
ICPPASTFunctionDeclarator dtor = (ICPPASTFunctionDeclarator) getDefinition();
if (dtor != null) {
return dtor.takesVarArgs();
}
ICPPASTFunctionDeclarator[] ds = (ICPPASTFunctionDeclarator[]) getDeclarations();
if (ds != null && ds.length > 0) {
return ds[0].takesVarArgs();
}
return false;
ICPPASTFunctionDeclarator dtor= getPreferredDtor();
return dtor != null ? dtor.takesVarArgs() : false;
}
public ILinkage getLinkage() {
@ -543,4 +541,38 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
public IBinding getOwner() throws DOMException {
return CPPVisitor.findNameOwner(getASTName(), false);
}
public IType[] getExceptionSpecification() throws DOMException {
ICPPASTFunctionDeclarator declarator = getPreferredDtor();
if (declarator != null) {
IASTTypeId[] astTypeIds= declarator.getExceptionSpecification();
if (astTypeIds.equals(ICPPASTFunctionDeclarator.NO_EXCEPTION_SPECIFICATION))
return null;
if (astTypeIds.equals(IASTTypeId.EMPTY_TYPEID_ARRAY))
return IType.EMPTY_TYPE_ARRAY;
IType[] typeIds = new IType[astTypeIds.length];
for (int i=0; i<astTypeIds.length; ++i) {
typeIds[i] = CPPVisitor.createType(astTypeIds[i]);
}
return typeIds;
}
return null;
}
protected ICPPASTFunctionDeclarator getPreferredDtor() {
ICPPASTFunctionDeclarator dtor = (ICPPASTFunctionDeclarator) getDefinition();
if (dtor != null)
return dtor;
ICPPASTFunctionDeclarator[] dtors = (ICPPASTFunctionDeclarator[]) getDeclarations();
if (dtors != null) {
for (ICPPASTFunctionDeclarator declarator : dtors) {
if (declarator != null)
return declarator;
}
}
return null;
}
}

View file

@ -24,6 +24,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
@ -38,6 +39,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
public class CPPFunctionSpecialization extends CPPSpecialization implements ICPPFunction, ICPPInternalFunction {
private IFunctionType type = null;
private IParameter[] specializedParams = null;
private IType[] specializedExceptionSpec = null;
public CPPFunctionSpecialization(IBinding orig, IBinding owner, ICPPTemplateParameterMap argMap) {
super(orig, owner, argMap);
@ -249,4 +251,17 @@ public class CPPFunctionSpecialization extends CPPSpecialization implements ICPP
}
return result.toString();
}
public IType[] getExceptionSpecification() throws DOMException {
if (specializedExceptionSpec == null) {
ICPPFunction function = (ICPPFunction) getSpecializedBinding();
IType[] types = function.getExceptionSpecification();
if (types != null) {
IType[] specializedTypeList = new IType[types.length];
for (int i=0; i<types.length; ++i)
specializedTypeList[i] = specializeType(types[i]);
}
}
return specializedExceptionSpec;
}
}

View file

@ -21,6 +21,7 @@ import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IParameter;
@ -94,6 +95,9 @@ public class CPPFunctionTemplate extends CPPTemplateDefinition
public boolean takesVarArgs() throws DOMException {
throw new DOMException(this);
}
public IType[] getExceptionSpecification() throws DOMException {
throw new DOMException( this );
}
}
protected IFunctionType type = null;
@ -355,4 +359,24 @@ public class CPPFunctionTemplate extends CPPTemplateDefinition
result.append(t != null ? ASTTypeUtil.getParameterTypeString(t) : "()"); //$NON-NLS-1$
return result.toString();
}
public IType[] getExceptionSpecification() throws DOMException {
ICPPASTFunctionDeclarator declarator = getDeclaratorByName(getDefinition());
if (declarator != null) {
IASTTypeId[] astTypeIds = declarator.getExceptionSpecification();
if (astTypeIds.equals(ICPPASTFunctionDeclarator.NO_EXCEPTION_SPECIFICATION)) {
return null;
}
if (astTypeIds.equals(IASTTypeId.EMPTY_TYPEID_ARRAY)) {
return IType.EMPTY_TYPE_ARRAY;
}
IType[] typeIds = new IType[astTypeIds.length];
for (int i=0; i<astTypeIds.length; ++i) {
typeIds[i] = CPPVisitor.createType(astTypeIds[i]);
}
return typeIds;
}
return null;
}
}

View file

@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Andrew Niefer (IBM Corporation) - initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -20,15 +20,11 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
/**
* @author aniefer
* Binding for implicit constructors (default and copy constructor).
*/
public class CPPImplicitConstructor extends CPPImplicitMethod implements ICPPConstructor {
/**
* @param name
* @param params
*/
public CPPImplicitConstructor( ICPPClassScope scope, char [] name, IParameter[] params ) {
public CPPImplicitConstructor(ICPPClassScope scope, char[] name, IParameter[] params) {
super( scope, name, createFunctionType(scope, params), params );
}
@ -37,9 +33,6 @@ public class CPPImplicitConstructor extends CPPImplicitMethod implements ICPPCon
return CPPVisitor.createImplicitFunctionType(returnType, params, null);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor#isExplicit()
*/
public boolean isExplicit() {
return false;
}

View file

@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Andrew Niefer (IBM Corporation) - initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -35,7 +35,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
/**
* @author aniefer
* Binding for implicit methods, base class for implicit constructors.
*/
public class CPPImplicitMethod extends CPPImplicitFunction implements ICPPMethod {
@ -180,4 +180,8 @@ public class CPPImplicitMethod extends CPPImplicitFunction implements ICPPMethod
return getClassOwner();
}
@Override
public IType[] getExceptionSpecification() throws DOMException {
return ClassTypeHelper.getInheritedExceptionSpecification(this);
}
}

View file

@ -17,6 +17,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
@ -75,7 +76,7 @@ public class CPPMethodSpecialization extends CPPFunctionSpecialization
}
public boolean isImplicit() {
return false;
return ((ICPPMethod) getSpecializedBinding()).isImplicit();
}
public boolean isPureVirtual() throws DOMException {
@ -86,4 +87,11 @@ public class CPPMethodSpecialization extends CPPFunctionSpecialization
return false;
}
@Override
public IType[] getExceptionSpecification() throws DOMException {
if (isImplicit()) {
return ClassTypeHelper.getInheritedExceptionSpecification(this);
}
return super.getExceptionSpecification();
}
}

View file

@ -29,10 +29,15 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IQualifierType;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
@ -45,6 +50,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.index.IIndex;
@ -207,8 +213,10 @@ public class ClassTypeHelper {
ICPPClassType[] bases= getAllBases(ct);
for (ICPPClassType base : bases) {
set.addAll(base.getDeclaredMethods());
scope= (ICPPClassScope) base.getCompositeScope();
set.addAll(scope.getImplicitMethods());
final IScope compositeScope = base.getCompositeScope();
if (compositeScope instanceof ICPPClassScope) {
set.addAll(((ICPPClassScope) compositeScope).getImplicitMethods());
}
}
return set.keyArray(ICPPMethod.class);
}
@ -547,4 +555,119 @@ public class ClassTypeHelper {
}
}
}
private static final int KIND_DEFAULT_CTOR= 0;
private static final int KIND_COPY_CTOR= 1;
private static final int KIND_ASSIGNMENT_OP= 2;
private static final int KIND_DTOR= 3;
private static final int KIND_OTHER= 4;
/**
* For implicit methods the exception specification is inherited, search it
* @throws DOMException
*/
public static IType[] getInheritedExceptionSpecification(ICPPMethod implicitMethod) throws DOMException {
// See 15.4.13
ICPPClassType owner= implicitMethod.getClassOwner();
if (owner == null || owner.getBases().length == 0)
return null;
// we use a list as types aren't comparable, and can have duplicates (15.4.6)
int kind= getImplicitMethodKind(owner, implicitMethod);
if (kind == KIND_OTHER)
return null;
List<IType> inheritedTypeids = new ArrayList<IType>();
ICPPClassType[] bases= getAllBases(owner);
for (ICPPClassType base : bases) {
if (!(base instanceof ICPPDeferredClassInstance)) {
ICPPMethod baseMethod= getMethodInClass(base, kind);
if (baseMethod != null) {
IType[] baseExceptionSpec= baseMethod.getExceptionSpecification();
if (baseExceptionSpec == null)
return null;
for (IType baseTypeId : baseMethod.getExceptionSpecification()) {
inheritedTypeids.add(baseTypeId);
}
}
}
}
return inheritedTypeids.toArray(new IType[inheritedTypeids.size()]);
}
private static int getImplicitMethodKind(ICPPClassType ct, ICPPMethod method) throws DOMException {
if (method instanceof ICPPConstructor) {
final IFunctionType type= method.getType();
final IType[] params= type.getParameterTypes();
if (params.length == 0)
return KIND_DEFAULT_CTOR;
if (params.length == 1) {
IType t= params[0];
if (t instanceof IBasicType && ((IBasicType) t).getType() == IBasicType.t_void)
return KIND_DEFAULT_CTOR;
if (isRefToConstClass(ct, t))
return KIND_COPY_CTOR;
}
return KIND_OTHER;
}
if (method.isDestructor())
return KIND_DTOR;
if (CharArrayUtils.equals(method.getNameCharArray(), OverloadableOperator.ASSIGN.toCharArray())) {
final IFunctionType type= method.getType();
final IType[] params= type.getParameterTypes();
if (params.length == 1) {
IType t= params[0];
if (isRefToConstClass(ct, t))
return KIND_ASSIGNMENT_OP;
}
return KIND_OTHER;
}
return KIND_OTHER;
}
private static boolean isRefToConstClass(ICPPClassType ct, IType t) throws DOMException {
while (t instanceof ITypedef)
t= ((ITypedef) t).getType();
if (t instanceof ICPPReferenceType) {
t= ((ICPPReferenceType) t).getType();
while (t instanceof ITypedef)
t= ((ITypedef) t).getType();
if (t instanceof IQualifierType) {
t= ((IQualifierType) t).getType();
return ct.isSameType(t);
}
}
return false;
}
private static ICPPMethod getMethodInClass(ICPPClassType ct, int kind) throws DOMException {
switch(kind) {
case KIND_DEFAULT_CTOR:
case KIND_COPY_CTOR:
for (ICPPConstructor ctor : ct.getConstructors()) {
if (!ctor.isImplicit() && getImplicitMethodKind(ct, ctor) == kind)
return ctor;
}
return null;
case KIND_ASSIGNMENT_OP:
for (ICPPMethod method : ct.getDeclaredMethods()) {
if (method instanceof ICPPConstructor)
continue;
if (getImplicitMethodKind(ct, method) == kind)
return method;
}
return null;
case KIND_DTOR:
for (ICPPMethod method : ct.getDeclaredMethods()) {
if (method.isDestructor())
return method;
}
return null;
}
return null;
}
}

View file

@ -1617,6 +1617,9 @@ public class CPPVisitor extends ASTQueries {
}
public static IType createType(IASTDeclarator declarator) {
if (declarator == null)
return null;
IASTDeclSpecifier declSpec = null;
IASTNode node = declarator.getParent();

View file

@ -92,4 +92,16 @@ class CompositeCPPFunction extends CompositeCPPBinding implements ICPPFunction {
}
return result.toString();
}
public IType[] getExceptionSpecification() throws DOMException {
IType[] es= ((ICPPFunction)rbinding).getExceptionSpecification();
if (es == null || es.length == 0)
return es;
IType[] result= new IType[es.length];
for (int i = 0; i < result.length; i++) {
result[i]= cf.getCompositeType((IIndexType) es[i]);
}
return result;
}
}

View file

@ -14,11 +14,13 @@ package org.eclipse.cdt.internal.core.index.composite.cpp;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.parser.util.ObjectMap;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap;
import org.eclipse.cdt.internal.core.index.IIndexType;
import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory;
public class CompositeCPPFunctionSpecialization extends CompositeCPPFunction implements ICPPSpecialization {
@ -53,8 +55,21 @@ public class CompositeCPPFunctionSpecialization extends CompositeCPPFunction imp
return result.toString();
}
@Override
public IType[] getExceptionSpecification() throws DOMException {
IType[] es= ((ICPPFunction)rbinding).getExceptionSpecification();
if (es == null || es.length == 0)
return es;
IType[] result= new IType[es.length];
for (int i = 0; i < result.length; i++) {
result[i]= cf.getCompositeType((IIndexType) result[i]);
}
return result;
}
@Deprecated
public ObjectMap getArgumentMap() {
return TemplateInstanceUtil.getArgumentMap(cf, rbinding);
}
}
}

View file

@ -165,11 +165,12 @@ public class PDOM extends PlatformObject implements IPDOM {
* 73.0 - add values for variables and enumerations, bug 250788
* 74.0 - changes for proper template argument support, bug 242668
* 75.0 - support for friends, bug 250167
* 76.0 - support for exception specification, bug 252697
*/
private static int version(int major, int minor) {
return major << 16 + minor;
}
public static final int MAJOR_VERSION = 75;
public static final int MAJOR_VERSION = 76;
public static final int MINOR_VERSION = 0; // minor versions must be compatible
public static final int CURRENT_VERSION= version(MAJOR_VERSION, MINOR_VERSION);

View file

@ -6,24 +6,23 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* QNX - Initial API and implementation
* Doug Schaefer (QNX) - Initial API and implementation
* IBM Corporation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.internal.core.Util;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
import org.eclipse.cdt.internal.core.index.IndexCPPSignatureUtil;
@ -38,8 +37,7 @@ import org.eclipse.cdt.internal.core.pdom.dom.c.PDOMCAnnotation;
import org.eclipse.core.runtime.CoreException;
/**
* @author Doug Schaefer
*
* Binding for c++ functions in the index.
*/
class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverloader {
@ -65,18 +63,23 @@ class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverl
* Offset of hash of parameter information to allow fast comparison
*/
private static final int SIGNATURE_HASH = PDOMCPPBinding.RECORD_SIZE + 12;
/**
* Offset of start of exception specifications
*/
protected static final int EXCEPTION_SPEC = PDOMCPPBinding.RECORD_SIZE + 16; // int
/**
* Offset of annotation information (relative to the beginning of the
* record).
*/
protected static final int ANNOTATION = PDOMCPPBinding.RECORD_SIZE + 16; // byte
protected static final int ANNOTATION = PDOMCPPBinding.RECORD_SIZE + 20; // byte
/**
* The size in bytes of a PDOMCPPFunction record in the database.
*/
@SuppressWarnings("hiding")
protected static final int RECORD_SIZE = PDOMCPPBinding.RECORD_SIZE + 17;
protected static final int RECORD_SIZE = PDOMCPPBinding.RECORD_SIZE + 21;
public PDOMCPPFunction(PDOM pdom, PDOMNode parent, ICPPFunction function, boolean setTypes) throws CoreException {
super(pdom, parent, function.getNameCharArray());
@ -89,6 +92,7 @@ class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverl
initData((ICPPFunctionType) function.getType(), function.getParameters());
}
db.putByte(record + ANNOTATION, PDOMCPPAnnotation.encodeAnnotation(function));
storeExceptionSpec(db, function);
} catch (DOMException e) {
throw new CoreException(Util.createStatus(e));
}
@ -102,7 +106,7 @@ class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverl
@Override
public void update(final PDOMLinkage linkage, IBinding newBinding) throws CoreException {
if (newBinding instanceof ICPPFunction) {
IFunction func= (ICPPFunction) newBinding;
ICPPFunction func= (ICPPFunction) newBinding;
ICPPFunctionType newType;
IParameter[] newParams;
byte newAnnotation;
@ -123,10 +127,31 @@ class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverl
if (oldParams != null) {
oldParams.delete(linkage);
}
pdom.getDB().putByte(record + ANNOTATION, newAnnotation);
final Database db = pdom.getDB();
db.putByte(record + ANNOTATION, newAnnotation);
int oldRec = db.getInt(record+EXCEPTION_SPEC);
storeExceptionSpec(db, func);
if (oldRec != 0) {
PDOMCPPTypeList.clearTypes(this, oldRec);
}
}
}
private void storeExceptionSpec(final Database db, ICPPFunction binding) throws CoreException {
int typelist= 0;
try {
if (binding instanceof ICPPMethod && ((ICPPMethod) binding).isImplicit()) {
// don't store the exception specification, computed it on demand.
} else {
typelist = PDOMCPPTypeList.putTypes(this, binding.getExceptionSpecification());
}
} catch (DOMException e) {
// ignore problems in the exception specification.
}
db.putInt(record + EXCEPTION_SPEC, typelist);
}
private void setParameters(PDOMCPPFunctionType pft, IParameter[] params) throws CoreException {
final Database db= pdom.getDB();
db.putInt(record + NUM_PARAMS, params.length);
@ -282,4 +307,14 @@ class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverl
}
return 0;
}
public IType[] getExceptionSpecification() throws DOMException {
try {
final int rec = getPDOM().getDB().getInt(record+EXCEPTION_SPEC);
return PDOMCPPTypeList.getTypes(this, rec);
} catch (CoreException e) {
CCorePlugin.log(e);
return null;
}
}
}

View file

@ -23,6 +23,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.db.Database;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.core.runtime.CoreException;
@ -32,8 +33,12 @@ import org.eclipse.core.runtime.CoreException;
*/
class PDOMCPPFunctionInstance extends PDOMCPPFunctionSpecialization implements ICPPTemplateInstance {
private static final int ARGUMENTS = PDOMCPPFunctionSpecialization.RECORD_SIZE + 0;
@SuppressWarnings("hiding")
protected static final int RECORD_SIZE = PDOMCPPFunctionSpecialization.RECORD_SIZE + 4;
private static final int EXCEPTION_SPEC = PDOMCPPFunctionSpecialization.RECORD_SIZE + 4;
@SuppressWarnings("hiding")
protected static final int RECORD_SIZE = PDOMCPPFunctionSpecialization.RECORD_SIZE + 8;
public PDOMCPPFunctionInstance(PDOM pdom, PDOMNode parent, ICPPFunction function, PDOMBinding orig)
throws CoreException {
@ -41,7 +46,15 @@ class PDOMCPPFunctionInstance extends PDOMCPPFunctionSpecialization implements I
final ICPPTemplateInstance asInstance= (ICPPTemplateInstance) function;
final int argListRec= PDOMCPPArgumentList.putArguments(this, asInstance.getTemplateArguments());
pdom.getDB().putInt(record+ARGUMENTS, argListRec);
final Database db = pdom.getDB();
db.putInt(record+ARGUMENTS, argListRec);
try {
int exceptSpecRec = PDOMCPPTypeList.putTypes(this, function.getExceptionSpecification());
db.putInt(record+EXCEPTION_SPEC, exceptSpecRec);
} catch (DOMException e) {
// ignore problems in the exception specification
}
}
public PDOMCPPFunctionInstance(PDOM pdom, int bindingRecord) {
@ -73,6 +86,17 @@ class PDOMCPPFunctionInstance extends PDOMCPPFunctionSpecialization implements I
}
}
@Override
public IType[] getExceptionSpecification() throws DOMException {
try {
final int rec = getPDOM().getDB().getInt(record+EXCEPTION_SPEC);
return PDOMCPPTypeList.getTypes(this, rec);
} catch (CoreException e) {
CCorePlugin.log(e);
return null;
}
}
@Deprecated
public IType[] getArguments() {
return CPPTemplates.getArguments(getTemplateArguments());

View file

@ -1,12 +1,12 @@
/*******************************************************************************
* Copyright (c) 2007 QNX Software Systems and others.
* Copyright (c) 2007, 2008 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* QNX - Initial API and implementation
* Bryan Wilkinson (QNX) - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
@ -18,6 +18,7 @@ import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.internal.core.Util;
@ -31,8 +32,7 @@ import org.eclipse.cdt.internal.core.pdom.dom.c.PDOMCAnnotation;
import org.eclipse.core.runtime.CoreException;
/**
* @author Bryan Wilkinson
*
* Binding for function specialization in the index.
*/
class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization implements ICPPFunction {
/**
@ -53,17 +53,22 @@ class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization implements ICP
*/
private static final int FUNCTION_TYPE = PDOMCPPSpecialization.RECORD_SIZE + 8;
/**
* Offset of start of exception specification
*/
protected static final int EXCEPTION_SPEC = PDOMCPPSpecialization.RECORD_SIZE + 12; // int
/**
* Offset of annotation information (relative to the beginning of the
* record).
*/
protected static final int ANNOTATION = PDOMCPPSpecialization.RECORD_SIZE + 12; // byte
protected static final int ANNOTATION = PDOMCPPSpecialization.RECORD_SIZE + 16; // byte
/**
* The size in bytes of a PDOMCPPFunction record in the database.
*/
@SuppressWarnings("hiding")
protected static final int RECORD_SIZE = PDOMCPPSpecialization.RECORD_SIZE + 13;
protected static final int RECORD_SIZE = PDOMCPPSpecialization.RECORD_SIZE + 17;
public PDOMCPPFunctionSpecialization(PDOM pdom, PDOMNode parent, ICPPFunction function, PDOMBinding specialized) throws CoreException {
super(pdom, parent, (ICPPSpecialization) function, specialized);
@ -95,10 +100,22 @@ class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization implements ICP
PDOMCPPParameter sParam = new PDOMCPPParameter(pdom, this, sParams[i], type);
setFirstParameter(new PDOMCPPParameterSpecialization(pdom, this, (ICPPParameter) params[i], sParam, typeRecord));
}
db.putByte(record + ANNOTATION, PDOMCPPAnnotation.encodeAnnotation(function));
db.putByte(record + ANNOTATION, PDOMCPPAnnotation.encodeAnnotation(function));
} catch (DOMException e) {
throw new CoreException(Util.createStatus(e));
}
try {
int typelist= 0;
if (function instanceof ICPPMethod && ((ICPPMethod) function).isImplicit()) {
// don't store the exception specification, computed it on demand.
} else {
typelist = PDOMCPPTypeList.putTypes(this, function.getExceptionSpecification());
}
db.putInt(record + EXCEPTION_SPEC, typelist);
} catch (DOMException e) {
// ignore problems in the exception specification
}
}
public PDOMCPPFunctionSpecialization(PDOM pdom, int bindingRecord) {
@ -208,4 +225,14 @@ class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization implements ICP
int cmp= super.pdomCompareTo(other);
return cmp==0 ? PDOMCPPFunction.compareSignatures(this, other) : cmp;
}
public IType[] getExceptionSpecification() throws DOMException {
try {
final int rec = getPDOM().getDB().getInt(record+EXCEPTION_SPEC);
return PDOMCPPTypeList.getTypes(this, rec);
} catch (CoreException e) {
CCorePlugin.log(e);
return null;
}
}
}

View file

@ -26,6 +26,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
import org.eclipse.cdt.internal.core.Util;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.db.Database;
@ -198,4 +199,12 @@ class PDOMCPPMethod extends PDOMCPPFunction implements ICPPMethod {
}
return 0;
}
@Override
public IType[] getExceptionSpecification() throws DOMException {
if (isImplicit()) {
return ClassTypeHelper.getInheritedExceptionSpecification(this);
}
return super.getExceptionSpecification();
}
}

View file

@ -12,10 +12,12 @@
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.internal.core.Util;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.db.Database;
@ -121,4 +123,12 @@ class PDOMCPPMethodSpecialization extends PDOMCPPFunctionSpecialization
public boolean isVolatile() {
return getBit(getByte(record + ANNOTATION1), PDOMCAnnotation.VOLATILE_OFFSET + CV_OFFSET);
}
@Override
public IType[] getExceptionSpecification() throws DOMException {
if (isImplicit()) {
return ClassTypeHelper.getInheritedExceptionSpecification(this);
}
return super.getExceptionSpecification();
}
}

View file

@ -0,0 +1,87 @@
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.internal.core.pdom.db.Database;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
/**
* Stores a typelist
* TODO could refactor to have common base shared by {@link PDOMCPPArgumentList} using generics
*/
class PDOMCPPTypeList {
protected static final int NODE_SIZE = 4;
/**
* Stores the given types in the database.
* @return the record by which the types can be referenced.
*/
public static int putTypes(PDOMNode parent, IType[] types) throws CoreException {
if (types == null)
return 0;
final PDOMLinkage linkage= parent.getLinkage();
final Database db= linkage.getPDOM().getDB();
final short len = (short)Math.min(types.length, (Database.MAX_MALLOC_SIZE-2)/NODE_SIZE);
final int block = db.malloc(2+ NODE_SIZE*len);
int p = block;
db.putShort(p, len); p+=2;
for (int i=0; i<len; i++, p+=NODE_SIZE) {
final IType type = types[i];
if (type != null) {
final PDOMNode pdomType = linkage.addType(parent, type);
db.putInt(p, pdomType.getRecord());
} else {
db.putInt(p, 0);
}
}
return block;
}
public static IType[] getTypes(PDOMNode parent, int rec) throws CoreException {
if (rec == 0)
return null;
final PDOMLinkage linkage= parent.getLinkage();
final Database db= linkage.getPDOM().getDB();
final short len = db.getShort(rec);
if (len == 0)
return IType.EMPTY_TYPE_ARRAY;
Assert.isTrue(len >= 0 && len <= (Database.MAX_MALLOC_SIZE-2)/NODE_SIZE);
rec+=2;
IType[] result= new IType[len];
for (int i=0; i<len; i++, rec+=NODE_SIZE) {
final int typeRec= db.getInt(rec);
if (typeRec != 0)
result[i]= (IType)linkage.getNode(typeRec);
}
return result;
}
/**
* Restores an array of template arguments from the database.
*/
public static void clearTypes(PDOMNode parent, final int record) throws CoreException {
if (record == 0)
return;
final PDOMLinkage linkage= parent.getLinkage();
final Database db= linkage.getPDOM().getDB();
final short len= db.getShort(record);
Assert.isTrue(len >= 0 && len <= (Database.MAX_MALLOC_SIZE-2)/NODE_SIZE);
int p= record+2;
for (int i=0; i<len; i++, p+=NODE_SIZE) {
final int typeRec= db.getInt(p);
final IType t= (IType) linkage.getNode(typeRec);
linkage.deleteType(t, parent.getRecord());
}
db.free(record);
}
}