diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexUpdateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexUpdateTests.java index cd0b65a4318..d3d5747fd05 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexUpdateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexUpdateTests.java @@ -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;}; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/MethodTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/MethodTests.java index 0d7f83ea18d..5e3b2c83ffb 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/MethodTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/MethodTests.java @@ -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)); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTestBase.java index eaf2b534567..95380db412c 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTestBase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTestBase.java @@ -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("::"); diff --git a/core/org.eclipse.cdt.core.tests/resources/pdomtests/methodTests/inheritance.cpp b/core/org.eclipse.cdt.core.tests/resources/pdomtests/methodTests/inheritance.cpp index 782139217c3..9c218bf5bce 100644 --- a/core/org.eclipse.cdt.core.tests/resources/pdomtests/methodTests/inheritance.cpp +++ b/core/org.eclipse.cdt.core.tests/resources/pdomtests/methodTests/inheritance.cpp @@ -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(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPFunction.java index b29a06c2502..051b122e908 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPFunction.java @@ -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 null if there + * is no exception specification. + * @since 5.1 + */ + public IType[] getExceptionSpecification() throws DOMException; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunctionInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunctionInstance.java index 601ead3f614..3ca58de0d5a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunctionInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunctionInstance.java @@ -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(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java index e2c86302f51..d73826b89f2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java @@ -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 inheritedTypeids = new ArrayList(); + 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; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index 8121308d8af..e5042106c2d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -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(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFunction.java index ecbfa9de705..10d658fa418 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFunction.java @@ -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; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFunctionSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFunctionSpecialization.java index de690495369..2274e8a172d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFunctionSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFunctionSpecialization.java @@ -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); - } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index 98b255c218b..d7760e0e7b2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -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); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunction.java index cb656ef4839..7be137b5af2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunction.java @@ -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; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunctionInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunctionInstance.java index f41ed40f2ce..92bce6424e4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunctionInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunctionInstance.java @@ -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()); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunctionSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunctionSpecialization.java index 4570406e917..1193e6810b8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunctionSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunctionSpecialization.java @@ -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; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethod.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethod.java index c8dd55afb83..12ac9daa0ef 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethod.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethod.java @@ -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(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethodSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethodSpecialization.java index 8062aef4852..0bbe3d8a0d1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethodSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethodSpecialization.java @@ -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(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTypeList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTypeList.java new file mode 100644 index 00000000000..b69802b747f --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTypeList.java @@ -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= 0 && len <= (Database.MAX_MALLOC_SIZE-2)/NODE_SIZE); + rec+=2; + IType[] result= new IType[len]; + for (int i=0; i= 0 && len <= (Database.MAX_MALLOC_SIZE-2)/NODE_SIZE); + int p= record+2; + for (int i=0; i