1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 14:12:10 +02:00

Bug 424068 - [C++11] Inheriting constructors.

Inheriting of template constructors is not supported yet.
This commit is contained in:
Sergey Prigogin 2014-04-24 16:57:43 -07:00
parent 8f2ea4c665
commit b96e29ae62
15 changed files with 566 additions and 102 deletions

View file

@ -1340,6 +1340,59 @@ public class AST2CPPTests extends AST2TestBase {
assertTrue(ctor instanceof ICPPConstructor); assertTrue(ctor instanceof ICPPConstructor);
} }
// struct A {
// A(int);
// };
//
// struct B : public A {
// using A::A;
// };
//
// void foo(B);
//
// int test() {
// foo(1);
// }
public void testInheritingConstructor() throws Exception {
parseAndCheckBindings();
}
// template <class T>
// struct A {
// A(T);
// };
//
// struct B : public A<int> {
// using A::A;
// };
//
// void foo(B);
//
// int test() {
// foo(1);
// }
public void testInheritingConstructorWithTemplate_1() throws Exception {
parseAndCheckBindings();
}
// struct A {
// A(int);
// };
//
// template <class T>
// struct B : public T {
// using T::T;
// };
//
// void foo(B<A>);
//
// int test() {
// foo(1);
// }
public void testInheritingConstructorWithTemplate_2() throws Exception {
parseAndCheckBindings();
}
// class A { ~A(); }; // class A { ~A(); };
// class B { ~B(void); }; // class B { ~B(void); };
public void testExplicitDestructor_183160() throws Exception { public void testExplicitDestructor_183160() throws Exception {
@ -2239,7 +2292,7 @@ public class AST2CPPTests extends AST2TestBase {
// }; // };
// void set(); // void set();
// class B{}; // class B{};
public void testFriend_1() throws Exception { public void testFriend() throws Exception {
IASTTranslationUnit tu = parse(getAboveComment(), CPP); IASTTranslationUnit tu = parse(getAboveComment(), CPP);
NameCollector col = new NameCollector(); NameCollector col = new NameCollector();
tu.accept(col); tu.accept(col);

View file

@ -204,7 +204,7 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti
// B b; // B b;
// b.p(E1); // b.p(E1);
// } // }
public void testUsingTypeDirective_201177() { public void testUsingTypeDeclaration_201177() {
IBinding b0= getBindingFromASTName("B::m", 4); IBinding b0= getBindingFromASTName("B::m", 4);
IBinding b1= getBindingFromASTName("B::n", 4); IBinding b1= getBindingFromASTName("B::n", 4);
IBinding b2= getBindingFromASTName("B::o", 4); IBinding b2= getBindingFromASTName("B::o", 4);
@ -254,7 +254,7 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti
// int g(int x) {return 4;} // int g(int x) {return 4;}
// int g(char x) {return 2;} // int g(char x) {return 2;}
// int nn= g(f(2)); // int nn= g(f(2));
public void testUsingTypeDirective_177917_1() { public void testUsingTypeDeclaration_177917_1() {
IBinding b1= getBindingFromASTName("A a", 1); IBinding b1= getBindingFromASTName("A a", 1);
IBinding b2= getBindingFromASTName("B b", 1); IBinding b2= getBindingFromASTName("B b", 1);
IBinding b3= getBindingFromASTName("C c", 1); IBinding b3= getBindingFromASTName("C c", 1);
@ -271,7 +271,7 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti
// #include "header.h" // #include "header.h"
// b::A aa; // b::A aa;
// b::B bb; // b::B bb;
public void testUsingTypeDirective_177917_2() { public void testUsingTypeDeclaration_177917_2() {
IBinding b0= getBindingFromASTName("A aa", 1); IBinding b0= getBindingFromASTName("A aa", 1);
IBinding b1= getBindingFromASTName("B bb", 1); IBinding b1= getBindingFromASTName("B bb", 1);
} }
@ -319,7 +319,7 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti
// fs(1); // fs(1);
// cls c2; // cls c2;
// } // }
public void testUsingOverloadedFunctionDirective() { public void testUsingOverloadedFunctionDeclaration() {
IBinding b; IBinding b;
b= getBindingFromASTName("fh()", 2); b= getBindingFromASTName("fh()", 2);
b= getBindingFromASTName("fh(1)", 2); b= getBindingFromASTName("fh(1)", 2);
@ -1760,4 +1760,56 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti
public void testAnonymousNamespaces_418130() throws Exception { public void testAnonymousNamespaces_418130() throws Exception {
checkBindings(); checkBindings();
} }
// struct A {
// A(int);
// };
// struct B : public A {
// using A::A;
// };
//
// void foo(B);
//
// int test() {
// foo(1);
// }
public void testInheritingConstructor() throws Exception {
checkBindings();
}
// template <class T>
// struct A {
// A(T);
// };
// struct B : public A<int> {
// using A::A;
// };
//
// void foo(B);
//
// int test() {
// foo(1);
// }
public void testInheritingConstructorWithTemplate_1() throws Exception {
checkBindings();
}
// struct A {
// A(int);
// };
//
// template <class T>
// struct B : public T {
// using T::T;
// };
// void foo(B<A>);
//
// int test() {
// foo(1);
// }
public void testInheritingConstructorWithTemplate_2() throws Exception {
checkBindings();
}
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2004, 2010 IBM Corporation and others. * Copyright (c) 2004, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -8,6 +8,7 @@
* Contributors: * Contributors:
* IBM - Initial API and implementation * IBM - Initial API and implementation
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.core.dom.ast.cpp; package org.eclipse.cdt.core.dom.ast.cpp;
@ -65,6 +66,13 @@ public interface ICPPBase extends Cloneable {
*/ */
public boolean isVirtual(); public boolean isVirtual();
/**
* The base class is a source of inherited constructors if the class definition that declares
* this base contains a using declaration naming the constructors of the base class.
* @since 5.7
*/
public boolean isInheritedConstructorsSource();
/** /**
* @since 5.1 * @since 5.1
*/ */

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2005, 2013 IBM Corporation and others. * Copyright (c) 2005, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -14,6 +14,8 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp; package org.eclipse.cdt.internal.core.dom.parser.cpp;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassScope.createInheritedConsructors;
import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IName; import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.DOMException;
@ -31,6 +33,7 @@ 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.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
@ -47,7 +50,9 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
*/ */
public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializationScope { public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializationScope {
private final ICPPClassSpecialization specialClass; private final ICPPClassSpecialization specialClass;
private volatile ICPPBase[] fBases; // Used by the pdom bindings, needs to be volatile. // The following fields are used by the PDOM bindings and need to be volatile.
private volatile ICPPBase[] fBases;
private volatile ICPPMethod[] ownInheritedConstructors;
public AbstractCPPClassSpecializationScope(ICPPClassSpecialization specialization) { public AbstractCPPClassSpecializationScope(ICPPClassSpecialization specialization) {
this.specialClass= specialization; this.specialClass= specialization;
@ -85,11 +90,11 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
if (bindings == null) if (bindings == null)
return null; return null;
IBinding[] specs = new IBinding[0]; IBinding[] specs = IBinding.EMPTY_BINDING_ARRAY;
for (IBinding binding : bindings) { for (IBinding binding : bindings) {
specs = ArrayUtil.append(IBinding.class, specs, specialClass.specializeMember(binding, name)); specs = ArrayUtil.append(specs, specialClass.specializeMember(binding, name));
} }
specs = ArrayUtil.trim(IBinding.class, specs); specs = ArrayUtil.trim(specs);
return CPPSemantics.resolveAmbiguities(name, specs); return CPPSemantics.resolveAmbiguities(name, specs);
} }
@ -108,7 +113,7 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
return IBinding.EMPTY_BINDING_ARRAY; return IBinding.EMPTY_BINDING_ARRAY;
IBinding[] bindings= classScope.getBindings(lookup); IBinding[] bindings= classScope.getBindings(lookup);
IBinding[] result= null; IBinding[] result= IBinding.EMPTY_BINDING_ARRAY;
for (IBinding binding : bindings) { for (IBinding binding : bindings) {
if (binding == specialized || if (binding == specialized ||
(binding instanceof ICPPClassType && specialized.isSameType((IType) binding))) { (binding instanceof ICPPClassType && specialized.isSameType((IType) binding))) {
@ -116,9 +121,9 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
} else { } else {
binding= specialClass.specializeMember(binding, lookup.getLookupPoint()); binding= specialClass.specializeMember(binding, lookup.getLookupPoint());
} }
result = ArrayUtil.append(IBinding.class, result, binding); result = ArrayUtil.append(result, binding);
} }
return ArrayUtil.trim(IBinding.class, result); return ArrayUtil.trim(result);
} }
@Override @Override
@ -129,7 +134,7 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
@Override @Override
public ICPPBase[] getBases(IASTNode point) { public ICPPBase[] getBases(IASTNode point) {
if (fBases == null) { if (fBases == null) {
ICPPBase[] result = null; ICPPBase[] result = ICPPBase.EMPTY_BASE_ARRAY;
ICPPBase[] bases = ClassTypeHelper.getBases(specialClass.getSpecializedBinding(), point); ICPPBase[] bases = ClassTypeHelper.getBases(specialClass.getSpecializedBinding(), point);
if (bases.length == 0) { if (bases.length == 0) {
fBases= bases; fBases= bases;
@ -141,14 +146,14 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
IType[] specClasses= CPPTemplates.instantiateTypes(new IType[] { new CPPParameterPackType((IType) origClass) }, IType[] specClasses= CPPTemplates.instantiateTypes(new IType[] { new CPPParameterPackType((IType) origClass) },
tpmap, -1, specialClass, point); tpmap, -1, specialClass, point);
if (specClasses.length == 1 && specClasses[0] instanceof ICPPParameterPackType) { if (specClasses.length == 1 && specClasses[0] instanceof ICPPParameterPackType) {
result= ArrayUtil.append(ICPPBase.class, result, base); result= ArrayUtil.append(result, base);
} else { } else {
for (IType specClass : specClasses) { for (IType specClass : specClasses) {
ICPPBase specBase = base.clone(); ICPPBase specBase = base.clone();
specClass = SemanticUtil.getUltimateType(specClass, false); specClass = SemanticUtil.getUltimateType(specClass, false);
if (specClass instanceof IBinding && !(specClass instanceof IProblemBinding)) { if (specClass instanceof IBinding && !(specClass instanceof IProblemBinding)) {
specBase.setBaseClass((IBinding) specClass); specBase.setBaseClass((IBinding) specClass);
result = ArrayUtil.append(ICPPBase.class, result, specBase); result = ArrayUtil.append(result, specBase);
} }
} }
} }
@ -165,10 +170,10 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
if (specClass instanceof IBinding && !(specClass instanceof IProblemBinding)) { if (specClass instanceof IBinding && !(specClass instanceof IProblemBinding)) {
specBase.setBaseClass((IBinding) specClass); specBase.setBaseClass((IBinding) specClass);
} }
result = ArrayUtil.append(ICPPBase.class, result, specBase); result = ArrayUtil.append(result, specBase);
} }
} }
result= ArrayUtil.trim(ICPPBase.class, result); result= ArrayUtil.trim(result);
fBases= result; fBases= result;
return result; return result;
} }
@ -205,7 +210,10 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
public ICPPMethod[] getImplicitMethods(IASTNode point) { public ICPPMethod[] getImplicitMethods(IASTNode point) {
ICPPClassType origClass = specialClass.getSpecializedBinding(); ICPPClassType origClass = specialClass.getSpecializedBinding();
ICPPMethod[] methods= ClassTypeHelper.getImplicitMethods(origClass, point); ICPPMethod[] methods= ClassTypeHelper.getImplicitMethods(origClass, point);
return specializeMembers(methods, point); ICPPMethod[] specializedMembers = specializeMembers(methods, point);
// Add inherited constructors.
ICPPMethod[] inheritedConstructors = getOwnInheritedConstructors(point);
return ArrayUtil.addAll(specializedMembers, inheritedConstructors);
} }
@Override @Override
@ -224,7 +232,52 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
@Override @Override
public ICPPConstructor[] getConstructors(IASTNode point) { public ICPPConstructor[] getConstructors(IASTNode point) {
ICPPConstructor[] ctors= ClassTypeHelper.getConstructors(specialClass.getSpecializedBinding(), point); ICPPConstructor[] ctors= ClassTypeHelper.getConstructors(specialClass.getSpecializedBinding(), point);
return specializeMembers(ctors, point); ICPPConstructor[] specializedCtors = specializeMembers(ctors, point);
// Add inherited constructors.
ICPPMethod[] inheritedConstructors = getOwnInheritedConstructors(specializedCtors, point);
return ArrayUtil.addAll(specializedCtors, inheritedConstructors);
}
/**
* Returns the inherited constructors that are not specializations of the inherited constructors
* of the specialized class.
*/
private ICPPMethod[] getOwnInheritedConstructors(ICPPConstructor[] existingConstructors,
IASTNode point) {
if (ownInheritedConstructors == null) {
if (!hasInheritedConstructorsSources(point))
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
IType[][] existingConstructorParamTypes = new IType[existingConstructors.length][];
for (int i = 0; i < existingConstructors.length; i++) {
ICPPParameter[] params = existingConstructors[i].getParameters();
IType[] types = new IType[params.length];
for (int j = 0; j < params.length; j++) {
types[j] = params[j].getType();
}
existingConstructorParamTypes[i] = types;
}
ICPPMethod[] constructors = createInheritedConsructors(this, specialClass.getNameCharArray(),
getBases(point), existingConstructorParamTypes, point);
ownInheritedConstructors = constructors;
}
return ownInheritedConstructors;
}
private ICPPMethod[] getOwnInheritedConstructors(IASTNode point) {
if (ownInheritedConstructors != null)
return ownInheritedConstructors;
ICPPConstructor[] ctors= ClassTypeHelper.getConstructors(specialClass.getSpecializedBinding(), point);
ICPPConstructor[] specializedCtors = specializeMembers(ctors, point);
return getOwnInheritedConstructors(specializedCtors, point);
}
private boolean hasInheritedConstructorsSources(IASTNode point) {
for (ICPPBase base : getBases(point)) {
if (base.isInheritedConstructorsSource())
return true;
}
return false;
} }
@Override @Override
@ -263,14 +316,14 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
} }
@Override @Override
public String toString() { public EScopeKind getKind() {
IName name = getScopeName(); return EScopeKind.eClassType;
return name != null ? name.toString() : String.valueOf(specialClass);
} }
@Override @Override
public EScopeKind getKind() { public String toString() {
return EScopeKind.eClassType; IName name = getScopeName();
return name != null ? name.toString() : String.valueOf(specialClass);
} }
// Note: equals() and hashCode() are overridden because multiple instances // Note: equals() and hashCode() are overridden because multiple instances

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2004, 2013 IBM Corporation and others. * Copyright (c) 2004, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -10,6 +10,7 @@
* Bryan Wilkinson (QNX) * Bryan Wilkinson (QNX)
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
* Nathan Ridge * Nathan Ridge
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp; package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -30,6 +31,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
public class CPPBaseClause implements ICPPBase, ICPPInternalBase { public class CPPBaseClause implements ICPPBase, ICPPInternalBase {
private final ICPPASTBaseSpecifier base; private final ICPPASTBaseSpecifier base;
private IType baseClass; private IType baseClass;
private boolean inheritedConstructorsSource;
public CPPBaseClause(ICPPASTBaseSpecifier base) { public CPPBaseClause(ICPPASTBaseSpecifier base) {
this.base = base; this.base = base;
@ -80,14 +82,8 @@ public class CPPBaseClause implements ICPPBase, ICPPInternalBase {
} }
@Override @Override
public void setBaseClass(IBinding cls) { public boolean isInheritedConstructorsSource() {
if (cls instanceof IType) return inheritedConstructorsSource;
baseClass = (IType) cls;
}
@Override
public void setBaseClass(IType cls) {
baseClass = cls;
} }
@Override @Override
@ -110,8 +106,23 @@ public class CPPBaseClause implements ICPPBase, ICPPInternalBase {
try { try {
t = (ICPPBase) super.clone(); t = (ICPPBase) super.clone();
} catch (CloneNotSupportedException e) { } catch (CloneNotSupportedException e) {
//not going to happen // Not going to happen.
} }
return t; return t;
} }
@Override
public void setBaseClass(IBinding cls) {
if (cls instanceof IType)
baseClass = (IType) cls;
}
@Override
public void setBaseClass(IType cls) {
baseClass = cls;
}
public void setInheritedConstructorsSource(boolean value) {
inheritedConstructorsSource = value;
}
} }

View file

@ -16,17 +16,28 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp; package org.eclipse.cdt.internal.core.dom.parser.cpp;
import static org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter.EMPTY_CPPPARAMETER_ARRAY; import static org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter.EMPTY_CPPPARAMETER_ARRAY;
import static org.eclipse.cdt.core.parser.util.ArrayUtil.addAll;
import static org.eclipse.cdt.core.parser.util.ArrayUtil.append;
import static org.eclipse.cdt.core.parser.util.ArrayUtil.appendAt;
import static org.eclipse.cdt.core.parser.util.ArrayUtil.trim;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType.UNSPECIFIED_TYPE; import static org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType.UNSPECIFIED_TYPE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
import java.util.Arrays;
import org.eclipse.cdt.core.dom.IName; import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.EScopeKind; import org.eclipse.cdt.core.dom.ast.EScopeKind;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFieldReference; import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.ISemanticProblem; import org.eclipse.cdt.core.dom.ast.ISemanticProblem;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
@ -35,6 +46,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNameSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
@ -42,8 +55,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; 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.ICPPParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
import org.eclipse.cdt.core.index.IIndexFileSet; import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectSet; import org.eclipse.cdt.core.parser.util.ObjectSet;
@ -127,6 +140,116 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
implicits[i++] = m; implicits[i++] = m;
addBinding(m); addBinding(m);
} }
ICPPBase[] inheritedConstructorsSources = findInheritedConstructorsSourceBases(compTypeSpec);
ICPPMethod[] inheritedConstructors = createInheritedConsructors(this, className,
inheritedConstructorsSources, ia.getParametersOfNontrivialUserDeclaredConstructors(),
compTypeSpec);
implicits = addAll(implicits, inheritedConstructors);
for (ICPPMethod ctor : inheritedConstructors)
addBinding(ctor);
}
private ICPPBase[] findInheritedConstructorsSourceBases(
ICPPASTCompositeTypeSpecifier compositeTypeSpec) {
ICPPBase[] bases = ClassTypeHelper.getBases(getClassType(), compositeTypeSpec);
if (bases.length == 0)
return bases;
ICPPBase[] results = ICPPBase.EMPTY_BASE_ARRAY;
IASTDeclaration[] members = compositeTypeSpec.getMembers();
int n = 0;
for (IASTDeclaration member : members) {
if (member instanceof ICPPASTUsingDeclaration) {
IASTName name = ((ICPPASTUsingDeclaration) member).getName();
if (!(name instanceof ICPPASTQualifiedName))
continue;
ICPPASTQualifiedName qName = (ICPPASTQualifiedName) name;
ICPPASTNameSpecifier[] qualifier = qName.getQualifier();
IBinding parent = qualifier[qualifier.length - 1].resolveBinding();
if (!(parent instanceof IType) || parent instanceof IProblemBinding)
continue;
IType type = SemanticUtil.getNestedType((IType) parent, TDEF);
if (type instanceof IBinding &&
Arrays.equals(((IBinding) type).getNameCharArray(), qName.getLastName().getSimpleID())) {
for (ICPPBase base : bases) {
IType baseClass = base.getBaseClassType();
if (type.isSameType(baseClass)) {
((CPPBaseClause) base).setInheritedConstructorsSource(true);
results = appendAt(results, n++, base);
}
}
}
}
}
return trim(results, n);
}
static ICPPMethod[] createInheritedConsructors(ICPPClassScope scope, char[] className,
ICPPBase[] bases, IType[][] existingConstructorParamTypes, IASTNode point) {
ICPPMethod[] inheritedConstructors = ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
int n = 0;
for (ICPPBase base : bases) {
if (!base.isInheritedConstructorsSource())
continue;
IBinding baseClass = base.getBaseClass();
if (!(baseClass instanceof ICPPClassType))
continue;
ICPPConstructor[] ctors = ClassTypeHelper.getConstructors((ICPPClassType) baseClass, point);
for (ICPPConstructor ctor : ctors) {
ICPPParameter[] prototypeParams = ctor.getParameters();
// 19.9-1 For each non-template constructor of X that has at least one parameter
// with a default argument, the set of constructors that results from omitting
// any ellipsis parameter specification and successively omitting parameters
// with a default argument from the end of the parameter-type-list.
for (int k = Math.max(ctor.getRequiredArgumentCount(), 1); k <= prototypeParams.length; k++) {
if (k == 1 && isReferenceToClass(prototypeParams[0].getType(), (ICPPClassType) baseClass)) {
continue; // Skip the copy constructor.
}
if (findMatchingSignature(prototypeParams, k, existingConstructorParamTypes) < 0) {
ICPPParameter[] params = deriveParameters(prototypeParams, k);
CPPInheritedConstructor inheritedConstructor =
new CPPInheritedConstructor(scope, className, ctor, params);
inheritedConstructors = appendAt(inheritedConstructors, n++, inheritedConstructor);
}
}
}
}
return trim(inheritedConstructors, n);
}
private static ICPPParameter[] deriveParameters(ICPPParameter[] prototypes, int count) {
ICPPParameter[] params = new ICPPParameter[count];
for (int i = 0; i < count; i++) {
params[i] = new CPPParameter(prototypes[i].getType(), i);
}
return params;
}
private static boolean isReferenceToClass(IType type, IType classType) {
type= SemanticUtil.getNestedType(type, TDEF);
if (type instanceof ICPPReferenceType && !((ICPPReferenceType) type).isRValueReference()) {
type= SemanticUtil.getNestedType(type, TDEF|REF|CVTYPE);
return classType.isSameType(type);
}
return false;
}
private static int findMatchingSignature(ICPPParameter[] params, int numParams, IType[][] paramTypes) {
for (int i = 0; i < paramTypes.length; i++) {
if (doParameterTypesMatch(params, numParams, paramTypes[i]))
return i;
}
return -1;
}
private static boolean doParameterTypesMatch(ICPPParameter[] params, int numParams, IType[] types) {
if (numParams != types.length)
return false;
for (int i = 0; i < numParams; i++) {
if (!params[i].getType().isSameType(types[i]))
return false;
}
return true;
} }
@Override @Override
@ -239,13 +362,13 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|| (prefixLookup && ContentAssistMatcherFactory.getInstance().match(c, compName.getLookupKey()))) { || (prefixLookup && ContentAssistMatcherFactory.getInstance().match(c, compName.getLookupKey()))) {
final IASTName lookupName = lookup.getLookupName(); final IASTName lookupName = lookup.getLookupName();
if (shallReturnConstructors(lookupName, prefixLookup)) { if (shallReturnConstructors(lookupName, prefixLookup)) {
result = ArrayUtil.addAll(IBinding.class, result, getConstructors(lookupName, lookup.isResolve())); result = addAll(IBinding.class, result, getConstructors(lookupName, lookup.isResolve()));
} }
// 9.2 ... The class-name is also inserted into the scope of the class itself. // 9.2 ... The class-name is also inserted into the scope of the class itself.
result = ArrayUtil.append(IBinding.class, result, compName.resolveBinding()); result = append(IBinding.class, result, compName.resolveBinding());
} }
result = ArrayUtil.addAll(IBinding.class, result, super.getBindings(lookup)); result = addAll(IBinding.class, result, super.getBindings(lookup));
return ArrayUtil.trim(IBinding.class, result); return trim(IBinding.class, result);
} }
static protected boolean shouldResolve(boolean force, IASTName candidate, IASTName forName) { static protected boolean shouldResolve(boolean force, IASTName candidate, IASTName forName) {
@ -282,16 +405,16 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
IASTName n = (IASTName) obj; IASTName n = (IASTName) obj;
binding = shouldResolve(forceResolve, n, forName) ? n.resolveBinding() : n.getBinding(); binding = shouldResolve(forceResolve, n, forName) ? n.resolveBinding() : n.getBinding();
if (binding instanceof ICPPConstructor) { if (binding instanceof ICPPConstructor) {
bs = ArrayUtil.append(bs, (ICPPConstructor) binding); bs = append(bs, (ICPPConstructor) binding);
} }
} else if (obj instanceof ICPPConstructor) { } else if (obj instanceof ICPPConstructor) {
bs = ArrayUtil.append(bs, (ICPPConstructor) obj); bs = append(bs, (ICPPConstructor) obj);
} }
} }
return ArrayUtil.trim(ICPPConstructor.class, bs); return trim(ICPPConstructor.class, bs);
} else if (o instanceof IASTName) { } else if (o instanceof IASTName) {
if (shouldResolve(forceResolve, (IASTName) o, forName) || ((IASTName) o).getBinding() != null) { if (shouldResolve(forceResolve, (IASTName) o, forName) || ((IASTName) o).getBinding() != null) {
// Always store the name, rather than the binding, such that we can properly flush the scope. // Always store the name, rather than the binding, so that we can properly flush the scope.
nameMap.put(CONSTRUCTOR_KEY, o); nameMap.put(CONSTRUCTOR_KEY, o);
binding = ((IASTName)o).resolveBinding(); binding = ((IASTName)o).resolveBinding();
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2005, 2013 IBM Corporation and others. * Copyright (c) 2005, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -146,10 +146,11 @@ public class CPPClassSpecialization extends CPPSpecialization
private ICPPClassSpecializationScope specScope; private ICPPClassSpecializationScope specScope;
private ObjectMap specializationMap= ObjectMap.EMPTY_MAP; private ObjectMap specializationMap= ObjectMap.EMPTY_MAP;
private ICPPBase[] bases;
private final ThreadLocal<Set<IBinding>> fInProgress= new ThreadLocal<Set<IBinding>>() { private final ThreadLocal<Set<IBinding>> fInProgress= new ThreadLocal<Set<IBinding>>() {
@Override @Override
protected Set<IBinding> initialValue() { protected Set<IBinding> initialValue() {
return new HashSet<IBinding>(); return new HashSet<>();
} }
}; };
@ -174,7 +175,6 @@ public class CPPClassSpecialization extends CPPSpecialization
IBinding result= (IBinding) specializationMap.get(original); IBinding result= (IBinding) specializationMap.get(original);
if (result != null) if (result != null)
return result; return result;
} }
IBinding result; IBinding result;
@ -226,8 +226,12 @@ public class CPPClassSpecialization extends CPPSpecialization
@Override @Override
public ICPPBase[] getBases(IASTNode point) { public ICPPBase[] getBases(IASTNode point) {
ICPPClassSpecializationScope scope= getSpecializationScope(); ICPPClassSpecializationScope scope= getSpecializationScope();
if (scope == null) if (scope == null) {
return ClassTypeHelper.getBases(this); if (bases == null) {
bases = ClassTypeHelper.getBases(this);
}
return bases;
}
return scope.getBases(point); return scope.getBases(point);
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2005, 2012 IBM Corporation and others. * Copyright (c) 2005, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -11,6 +11,7 @@
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
* Thomas Corbat (IFS) * Thomas Corbat (IFS)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp; package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -49,6 +50,7 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements ICPPClass
private ICPPClassTemplatePartialSpecialization[] partialSpecializations; private ICPPClassTemplatePartialSpecialization[] partialSpecializations;
private ICPPDeferredClassInstance fDeferredInstance; private ICPPDeferredClassInstance fDeferredInstance;
private boolean addedPartialSpecializationsOfIndex; private boolean addedPartialSpecializationsOfIndex;
private ICPPBase[] bases;
public CPPClassTemplate(IASTName name) { public CPPClassTemplate(IASTName name) {
super(name); super(name);
@ -154,7 +156,10 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements ICPPClass
@Override @Override
public ICPPBase[] getBases() { public ICPPBase[] getBases() {
return ClassTypeHelper.getBases(this); if (bases == null) {
bases = ClassTypeHelper.getBases(this);
}
return bases;
} }
@Override @Override

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2004, 2010 IBM Corporation and others. * Copyright (c) 2004, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -119,6 +119,7 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp
private IASTName[] declarations; private IASTName[] declarations;
private boolean checked; private boolean checked;
private ICPPClassType typeInIndex; private ICPPClassType typeInIndex;
private ICPPBase[] bases;
public CPPClassType(IASTName name, IBinding indexBinding) { public CPPClassType(IASTName name, IBinding indexBinding) {
name = stripQualifier(name); name = stripQualifier(name);
@ -311,7 +312,10 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp
@Override @Override
public ICPPBase[] getBases() { public ICPPBase[] getBases() {
return ClassTypeHelper.getBases(this); if (bases == null) {
bases = ClassTypeHelper.getBases(this);
}
return bases;
} }
@Override @Override

View file

@ -0,0 +1,74 @@
/*******************************************************************************
* Copyright (c) 2014 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType.UNSPECIFIED_TYPE;
import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
/**
* Binding for implicit constructors (default and copy constructor).
* 12.9
*/
public class CPPInheritedConstructor extends CPPImplicitMethod implements ICPPConstructor {
private final ICPPConstructor prototype;
public CPPInheritedConstructor(ICPPClassScope scope, char[] name, ICPPConstructor prototype,
ICPPParameter[] params) {
super(scope, name, createFunctionType(params), params);
this.prototype = prototype;
}
private static ICPPFunctionType createFunctionType(IParameter[] params) {
return CPPVisitor.createImplicitFunctionType(UNSPECIFIED_TYPE, params, false, false);
}
@Override
public boolean isDestructor() {
return false;
}
@Override
public boolean isImplicit() {
return true;
}
@Override
public int getVisibility() {
return prototype.getVisibility();
}
@Override
public boolean isExplicit() {
return prototype.isExplicit();
}
@Override
public boolean isDeleted() {
return prototype.isDeleted();
}
@Override
public boolean isConstexpr() {
return prototype.isConstexpr();
}
@Override
public IType[] getExceptionSpecification() {
return prototype.getExceptionSpecification();
}
}

View file

@ -12,6 +12,8 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp; package org.eclipse.cdt.internal.core.dom.parser.cpp;
import static org.eclipse.cdt.core.parser.util.ArrayUtil.appendAt;
import static org.eclipse.cdt.core.parser.util.ArrayUtil.trim;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
@ -20,11 +22,13 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
@ -35,17 +39,20 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
/** /**
* Helps analysis of the class declaration for user declared members relevant * Helps analysis of the class declaration for user declared members relevant for deciding
* to deciding which implicit bindings to declare. * which implicit bindings to declare.
* *
* @see chapter 12 of the ISO specification * @see chapter 12 of the ISO specification
*/ */
class ImplicitsAnalysis { final class ImplicitsAnalysis {
private boolean hasUserDeclaredConstructor; private static final IASTParameterDeclaration[][] EMPTY_ARRAY_OF_PARAMETER_ARRAYS = {};
private boolean hasUserDeclaredCopyConstructor;
private boolean hasUserDeclaredCopyAssignmentOperator;
private boolean hasUserDeclaredDestructor;
private final ICPPClassType classType; private final ICPPClassType classType;
private boolean hasConstructor;
private boolean hasCopyConstructor;
private boolean hasCopyAssignmentOperator;
private boolean hasDestructor;
private IASTParameterDeclaration[][] parametersOfNontrivialConstructors = EMPTY_ARRAY_OF_PARAMETER_ARRAYS;
ImplicitsAnalysis(ICPPASTCompositeTypeSpecifier compositeTypeSpecifier, ICPPClassType classType) { ImplicitsAnalysis(ICPPASTCompositeTypeSpecifier compositeTypeSpecifier, ICPPClassType classType) {
this.classType= classType; this.classType= classType;
@ -53,29 +60,54 @@ class ImplicitsAnalysis {
} }
public boolean hasUserDeclaredConstructor() { public boolean hasUserDeclaredConstructor() {
return hasUserDeclaredConstructor; return hasConstructor;
} }
public boolean hasUserDeclaredCopyConstructor() { public boolean hasUserDeclaredCopyConstructor() {
return hasUserDeclaredCopyConstructor; return hasCopyConstructor;
} }
public boolean hasUserDeclaredCopyAssignmentOperator() { public boolean hasUserDeclaredCopyAssignmentOperator() {
return hasUserDeclaredCopyAssignmentOperator; return hasCopyAssignmentOperator;
} }
public boolean hasUserDeclaredDestructor() { public boolean hasUserDeclaredDestructor() {
return hasUserDeclaredDestructor; return hasDestructor;
} }
/**
* Returns the types of parameters of user-declared constructors excluding the default and copy
* constructors. Available only when the class has at least one base class.
*/
public IType[][] getParametersOfNontrivialUserDeclaredConstructors() {
IASTParameterDeclaration[][] paramDeclarations = parametersOfNontrivialConstructors;
IType[][] paramTypes = new IType[paramDeclarations.length][];
for (int i = 0; i < paramDeclarations.length; i++) {
IASTParameterDeclaration[] declarations = paramDeclarations[i];
int numParams = declarations.length;
IType[] types = paramTypes[i] = new IType[numParams];
for (int j = 0; j < numParams; j++) {
types[j] = CPPVisitor.createType((ICPPASTParameterDeclaration) declarations[j], true);
}
}
return paramTypes;
}
/**
* Returns the number of implicit methods to declare not counting the inherited constructors.
*/
public int getImplicitsToDeclareCount() { public int getImplicitsToDeclareCount() {
return (!hasUserDeclaredDestructor ? 1 : 0) return (!hasDestructor ? 1 : 0)
+ (!hasUserDeclaredConstructor ? 1 : 0) + (!hasConstructor ? 1 : 0)
+ (!hasUserDeclaredCopyConstructor ? 1 : 0) + (!hasCopyConstructor ? 1 : 0)
+ (!hasUserDeclaredCopyAssignmentOperator ? 1 : 0); + (!hasCopyAssignmentOperator ? 1 : 0);
} }
private void analyzeMembers(ICPPASTCompositeTypeSpecifier compositeTypeSpecifier) { private void analyzeMembers(ICPPASTCompositeTypeSpecifier compositeTypeSpecifier) {
int numNontrivialConstructors = 0;
ICPPASTBaseSpecifier[] baseSpecifiers = compositeTypeSpecifier.getBaseSpecifiers();
IASTDeclaration[] members = compositeTypeSpecifier.getMembers(); IASTDeclaration[] members = compositeTypeSpecifier.getMembers();
char[] name = compositeTypeSpecifier.getName().getLookupKey(); char[] name = compositeTypeSpecifier.getName().getLookupKey();
for (IASTDeclaration member : members) { for (IASTDeclaration member : members) {
@ -83,7 +115,7 @@ class ImplicitsAnalysis {
IASTDeclSpecifier spec = null; IASTDeclSpecifier spec = null;
if (member instanceof IASTSimpleDeclaration) { if (member instanceof IASTSimpleDeclaration) {
IASTDeclarator[] dtors = ((IASTSimpleDeclaration) member).getDeclarators(); IASTDeclarator[] dtors = ((IASTSimpleDeclaration) member).getDeclarators();
if (dtors.length == 0 || dtors.length > 1) if (dtors.length != 1)
continue; continue;
dcltor = dtors[0]; dcltor = dtors[0];
spec = ((IASTSimpleDeclaration) member).getDeclSpecifier(); spec = ((IASTSimpleDeclaration) member).getDeclSpecifier();
@ -95,46 +127,57 @@ class ImplicitsAnalysis {
if (!(dcltor instanceof ICPPASTFunctionDeclarator)) if (!(dcltor instanceof ICPPASTFunctionDeclarator))
continue; continue;
char[] declName= ASTQueries.findInnermostDeclarator(dcltor).getName().getLookupKey(); IASTName memberName = ASTQueries.findInnermostDeclarator(dcltor).getName();
char[] declName = memberName.getLookupKey();
if (spec instanceof IASTSimpleDeclSpecifier && if (spec instanceof IASTSimpleDeclSpecifier &&
((IASTSimpleDeclSpecifier) spec).getType() == IASTSimpleDeclSpecifier.t_unspecified) { ((IASTSimpleDeclSpecifier) spec).getType() == IASTSimpleDeclSpecifier.t_unspecified) {
if (CharArrayUtils.equals(declName, name)) { if (CharArrayUtils.equals(declName, name)) {
hasUserDeclaredConstructor = true; hasConstructor = true;
IASTParameterDeclaration[] ps = ((ICPPASTFunctionDeclarator) dcltor).getParameters(); IASTParameterDeclaration[] params = ((ICPPASTFunctionDeclarator) dcltor).getParameters();
if (ps.length >= 1) { if (params.length != 0) {
if (hasTypeReferenceToClassType(ps[0]) && parametersHaveInitializers(ps, 1)) { if (hasTypeReferenceToClassType(params[0])) {
hasUserDeclaredCopyConstructor= true; if (parametersHaveInitializers(params, 1)) {
hasCopyConstructor = true;
}
if (params.length > 1) {
parametersOfNontrivialConstructors =
appendAt(parametersOfNontrivialConstructors, numNontrivialConstructors++, params);
}
} else {
parametersOfNontrivialConstructors =
appendAt(parametersOfNontrivialConstructors, numNontrivialConstructors++, params);
} }
} }
} if (declName.length > 0 && declName[0] == '~' && } if (declName.length != 0 && declName[0] == '~' &&
CharArrayUtils.equals(declName, 1, name.length, name)) { CharArrayUtils.equals(declName, 1, name.length, name)) {
hasUserDeclaredDestructor = true; hasDestructor = true;
} }
} if (CharArrayUtils.equals(declName, OverloadableOperator.ASSIGN.toCharArray())) { } if (CharArrayUtils.equals(declName, OverloadableOperator.ASSIGN.toCharArray())) {
IASTParameterDeclaration[] ps = ((ICPPASTFunctionDeclarator) dcltor).getParameters(); IASTParameterDeclaration[] params = ((ICPPASTFunctionDeclarator) dcltor).getParameters();
if (ps.length == 1 && hasTypeReferenceToClassType(ps[0])) if (params.length == 1 && hasTypeReferenceToClassType(params[0]))
hasUserDeclaredCopyAssignmentOperator = true; hasCopyAssignmentOperator = true;
} }
if (hasUserDeclaredCopyConstructor && hasUserDeclaredDestructor && hasUserDeclaredCopyAssignmentOperator) if (hasCopyConstructor && hasDestructor && hasCopyAssignmentOperator && baseSpecifiers.length == 0) {
break; break; // Nothing else to look for.
} }
} }
private boolean hasTypeReferenceToClassType(IASTParameterDeclaration dec) { parametersOfNontrivialConstructors = trim(parametersOfNontrivialConstructors, numNontrivialConstructors);
if (dec instanceof ICPPASTParameterDeclaration) { }
IType t= CPPVisitor.createType((ICPPASTParameterDeclaration) dec, false);
private boolean hasTypeReferenceToClassType(IASTParameterDeclaration decl) {
if (decl instanceof ICPPASTParameterDeclaration) {
IType t = CPPVisitor.createType((ICPPASTParameterDeclaration) decl, false);
if (t != null) { if (t != null) {
t= SemanticUtil.getNestedType(t, TDEF); t= SemanticUtil.getNestedType(t, TDEF);
if (t instanceof ICPPReferenceType) { if (t instanceof ICPPReferenceType && !((ICPPReferenceType) t).isRValueReference()) {
if (!((ICPPReferenceType) t).isRValueReference()) {
t= SemanticUtil.getNestedType(t, TDEF|REF|CVTYPE); t= SemanticUtil.getNestedType(t, TDEF|REF|CVTYPE);
return classType.isSameType(t); return classType.isSameType(t);
} }
} }
} }
}
return false; return false;
} }

View file

@ -2031,10 +2031,10 @@ public class CPPSemantics {
fns = new ObjectSet<>(2); fns = new ObjectSet<>(2);
fns.put((ICPPFunction) temp); fns.put((ICPPFunction) temp);
} else if (temp instanceof IType) { } else if (temp instanceof IType) {
// Specializations are selected during instantiation // Specializations are selected during instantiation.
if (temp instanceof ICPPClassTemplatePartialSpecialization) if (temp instanceof ICPPClassTemplatePartialSpecialization)
continue; continue;
if (temp instanceof ICPPTemplateInstance) { if (temp instanceof ICPPTemplateInstance && lookupName instanceof ICPPASTTemplateId) {
temp= ((ICPPTemplateInstance) temp).getSpecializedBinding(); temp= ((ICPPTemplateInstance) temp).getSpecializedBinding();
if (!(temp instanceof IType)) if (!(temp instanceof IType))
continue; continue;

View file

@ -747,4 +747,12 @@ public class SemanticUtil {
} }
return minValue; return minValue;
} }
public static int findSameType(IType type, IType[] types) {
for (int i = 0; i < types.length; i++) {
if (type.isSameType(types[i]))
return i;
}
return -1;
}
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2007, 2012 Symbian Software Systems and others. * Copyright (c) 2007, 2014 Symbian Software Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -17,6 +17,7 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType;
import java.util.Arrays; import java.util.Arrays;
import org.eclipse.cdt.core.dom.IName; import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField; import org.eclipse.cdt.core.dom.ast.IField;
@ -103,6 +104,11 @@ class CompositeCPPClassType extends CompositeCPPBinding implements ICPPClassType
return base.isVirtual(); return base.isVirtual();
} }
@Override
public boolean isInheritedConstructorsSource() {
return base.isInheritedConstructorsSource();
}
@Override @Override
public void setBaseClass(IBinding binding) { public void setBaseClass(IBinding binding) {
if (writable && binding instanceof IType) { if (writable && binding instanceof IType) {

View file

@ -38,6 +38,10 @@ class PDOMCPPBase implements ICPPBase, ICPPInternalBase {
protected static final int RECORD_SIZE = FLAGS + 1; protected static final int RECORD_SIZE = FLAGS + 1;
private static final int FLAGS_VISIBILITY_MASK = 0x03;
private static final int FLAGS_VIRTUAL = 0x04;
private static final int FLAGS_INHERITED_CONSTRUCTORS_SOURCE = 0x08;
private final PDOMLinkage linkage; private final PDOMLinkage linkage;
private final long record; private final long record;
@ -55,7 +59,8 @@ class PDOMCPPBase implements ICPPBase, ICPPInternalBase {
db.putRecPtr(record + CLASS_DEFINITION, classDefName.getRecord()); db.putRecPtr(record + CLASS_DEFINITION, classDefName.getRecord());
linkage.storeType(record + BASECLASS_TYPE, base.getBaseClassType()); linkage.storeType(record + BASECLASS_TYPE, base.getBaseClassType());
byte flags = (byte) (base.getVisibility() | (base.isVirtual() ? 4 : 0)); byte flags = (byte) (base.getVisibility() | (base.isVirtual() ? FLAGS_VIRTUAL : 0)
| (base.isInheritedConstructorsSource() ? FLAGS_INHERITED_CONSTRUCTORS_SOURCE : 0));
db.putByte(record + FLAGS, flags); db.putByte(record + FLAGS, flags);
} }
@ -123,7 +128,7 @@ class PDOMCPPBase implements ICPPBase, ICPPInternalBase {
@Override @Override
public int getVisibility() { public int getVisibility() {
try { try {
return getFlags() & 0x3; return getFlags() & FLAGS_VISIBILITY_MASK;
} catch (CoreException e) { } catch (CoreException e) {
CCorePlugin.log(e); CCorePlugin.log(e);
return 0; return 0;
@ -133,7 +138,17 @@ class PDOMCPPBase implements ICPPBase, ICPPInternalBase {
@Override @Override
public boolean isVirtual() { public boolean isVirtual() {
try { try {
return (getFlags() & 0x4) != 0; return (getFlags() & FLAGS_VIRTUAL) != 0;
} catch (CoreException e) {
CCorePlugin.log(e);
return false;
}
}
@Override
public boolean isInheritedConstructorsSource() {
try {
return (getFlags() & FLAGS_INHERITED_CONSTRUCTORS_SOURCE) != 0;
} catch (CoreException e) { } catch (CoreException e) {
CCorePlugin.log(e); CCorePlugin.log(e);
return false; return false;
@ -160,7 +175,7 @@ class PDOMCPPBase implements ICPPBase, ICPPInternalBase {
private static class PDOMCPPBaseClone implements ICPPBase, ICPPInternalBase { private static class PDOMCPPBaseClone implements ICPPBase, ICPPInternalBase {
private final ICPPBase base; private final ICPPBase base;
private IType baseClass = null; private IType baseClass;
public PDOMCPPBaseClone(ICPPBase base) { public PDOMCPPBaseClone(ICPPBase base) {
this.base = base; this.base = base;
@ -203,6 +218,11 @@ class PDOMCPPBase implements ICPPBase, ICPPInternalBase {
return base.isVirtual(); return base.isVirtual();
} }
@Override
public boolean isInheritedConstructorsSource() {
return base.isInheritedConstructorsSource();
}
@Override @Override
public void setBaseClass(IBinding binding) { public void setBaseClass(IBinding binding) {
if (binding instanceof IType) if (binding instanceof IType)