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);
}
// 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 B { ~B(void); };
public void testExplicitDestructor_183160() throws Exception {
@ -2239,7 +2292,7 @@ public class AST2CPPTests extends AST2TestBase {
// };
// void set();
// class B{};
public void testFriend_1() throws Exception {
public void testFriend() throws Exception {
IASTTranslationUnit tu = parse(getAboveComment(), CPP);
NameCollector col = new NameCollector();
tu.accept(col);

View file

@ -204,7 +204,7 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti
// B b;
// b.p(E1);
// }
public void testUsingTypeDirective_201177() {
public void testUsingTypeDeclaration_201177() {
IBinding b0= getBindingFromASTName("B::m", 4);
IBinding b1= getBindingFromASTName("B::n", 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(char x) {return 2;}
// int nn= g(f(2));
public void testUsingTypeDirective_177917_1() {
public void testUsingTypeDeclaration_177917_1() {
IBinding b1= getBindingFromASTName("A a", 1);
IBinding b2= getBindingFromASTName("B b", 1);
IBinding b3= getBindingFromASTName("C c", 1);
@ -271,7 +271,7 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti
// #include "header.h"
// b::A aa;
// b::B bb;
public void testUsingTypeDirective_177917_2() {
public void testUsingTypeDeclaration_177917_2() {
IBinding b0= getBindingFromASTName("A aa", 1);
IBinding b1= getBindingFromASTName("B bb", 1);
}
@ -319,7 +319,7 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti
// fs(1);
// cls c2;
// }
public void testUsingOverloadedFunctionDirective() {
public void testUsingOverloadedFunctionDeclaration() {
IBinding b;
b= getBindingFromASTName("fh()", 2);
b= getBindingFromASTName("fh(1)", 2);
@ -1760,4 +1760,56 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti
public void testAnonymousNamespaces_418130() throws Exception {
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
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -8,6 +8,7 @@
* Contributors:
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast.cpp;
@ -65,6 +66,13 @@ public interface ICPPBase extends Cloneable {
*/
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
*/

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
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -14,6 +14,8 @@
*******************************************************************************/
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.dom.IName;
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.ICPPMethod;
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.ICPPTemplateParameter;
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 {
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) {
this.specialClass= specialization;
@ -85,11 +90,11 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
if (bindings == null)
return null;
IBinding[] specs = new IBinding[0];
IBinding[] specs = IBinding.EMPTY_BINDING_ARRAY;
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);
}
@ -108,7 +113,7 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
return IBinding.EMPTY_BINDING_ARRAY;
IBinding[] bindings= classScope.getBindings(lookup);
IBinding[] result= null;
IBinding[] result= IBinding.EMPTY_BINDING_ARRAY;
for (IBinding binding : bindings) {
if (binding == specialized ||
(binding instanceof ICPPClassType && specialized.isSameType((IType) binding))) {
@ -116,9 +121,9 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
} else {
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
@ -129,7 +134,7 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
@Override
public ICPPBase[] getBases(IASTNode point) {
if (fBases == null) {
ICPPBase[] result = null;
ICPPBase[] result = ICPPBase.EMPTY_BASE_ARRAY;
ICPPBase[] bases = ClassTypeHelper.getBases(specialClass.getSpecializedBinding(), point);
if (bases.length == 0) {
fBases= bases;
@ -141,14 +146,14 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
IType[] specClasses= CPPTemplates.instantiateTypes(new IType[] { new CPPParameterPackType((IType) origClass) },
tpmap, -1, specialClass, point);
if (specClasses.length == 1 && specClasses[0] instanceof ICPPParameterPackType) {
result= ArrayUtil.append(ICPPBase.class, result, base);
result= ArrayUtil.append(result, base);
} else {
for (IType specClass : specClasses) {
ICPPBase specBase = base.clone();
specClass = SemanticUtil.getUltimateType(specClass, false);
if (specClass instanceof IBinding && !(specClass instanceof IProblemBinding)) {
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)) {
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;
return result;
}
@ -205,7 +210,10 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
public ICPPMethod[] getImplicitMethods(IASTNode point) {
ICPPClassType origClass = specialClass.getSpecializedBinding();
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
@ -224,7 +232,52 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
@Override
public ICPPConstructor[] getConstructors(IASTNode 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
@ -263,14 +316,14 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
}
@Override
public String toString() {
IName name = getScopeName();
return name != null ? name.toString() : String.valueOf(specialClass);
public EScopeKind getKind() {
return EScopeKind.eClassType;
}
@Override
public EScopeKind getKind() {
return EScopeKind.eClassType;
public String toString() {
IName name = getScopeName();
return name != null ? name.toString() : String.valueOf(specialClass);
}
// 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
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -10,6 +10,7 @@
* Bryan Wilkinson (QNX)
* Markus Schorn (Wind River Systems)
* Nathan Ridge
* Sergey Prigogin (Google)
*******************************************************************************/
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 {
private final ICPPASTBaseSpecifier base;
private IType baseClass;
private boolean inheritedConstructorsSource;
public CPPBaseClause(ICPPASTBaseSpecifier base) {
this.base = base;
@ -80,14 +82,8 @@ public class CPPBaseClause implements ICPPBase, ICPPInternalBase {
}
@Override
public void setBaseClass(IBinding cls) {
if (cls instanceof IType)
baseClass = (IType) cls;
}
@Override
public void setBaseClass(IType cls) {
baseClass = cls;
public boolean isInheritedConstructorsSource() {
return inheritedConstructorsSource;
}
@Override
@ -110,8 +106,23 @@ public class CPPBaseClause implements ICPPBase, ICPPInternalBase {
try {
t = (ICPPBase) super.clone();
} catch (CloneNotSupportedException e) {
//not going to happen
// Not going to happen.
}
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;
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.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.ast.EScopeKind;
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.IASTFieldReference;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
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.ISemanticProblem;
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.ICPPASTQualifiedName;
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.ICPPClassTemplate;
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.ICPPMethod;
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.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectSet;
@ -127,6 +140,116 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
implicits[i++] = 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
@ -239,13 +362,13 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|| (prefixLookup && ContentAssistMatcherFactory.getInstance().match(c, compName.getLookupKey()))) {
final IASTName lookupName = lookup.getLookupName();
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.
result = ArrayUtil.append(IBinding.class, result, compName.resolveBinding());
result = append(IBinding.class, result, compName.resolveBinding());
}
result = ArrayUtil.addAll(IBinding.class, result, super.getBindings(lookup));
return ArrayUtil.trim(IBinding.class, result);
result = addAll(IBinding.class, result, super.getBindings(lookup));
return trim(IBinding.class, result);
}
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;
binding = shouldResolve(forceResolve, n, forName) ? n.resolveBinding() : n.getBinding();
if (binding instanceof ICPPConstructor) {
bs = ArrayUtil.append(bs, (ICPPConstructor) binding);
bs = append(bs, (ICPPConstructor) binding);
}
} 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) {
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);
binding = ((IASTName)o).resolveBinding();
}
@ -372,7 +495,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
public IName getScopeName() {
IASTNode node = getPhysicalNode();
if (node instanceof ICPPASTCompositeTypeSpecifier) {
return ((ICPPASTCompositeTypeSpecifier)node).getName();
return ((ICPPASTCompositeTypeSpecifier) node).getName();
}
return null;
}

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
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -146,10 +146,11 @@ public class CPPClassSpecialization extends CPPSpecialization
private ICPPClassSpecializationScope specScope;
private ObjectMap specializationMap= ObjectMap.EMPTY_MAP;
private ICPPBase[] bases;
private final ThreadLocal<Set<IBinding>> fInProgress= new ThreadLocal<Set<IBinding>>() {
@Override
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);
if (result != null)
return result;
}
IBinding result;
@ -226,8 +226,12 @@ public class CPPClassSpecialization extends CPPSpecialization
@Override
public ICPPBase[] getBases(IASTNode point) {
ICPPClassSpecializationScope scope= getSpecializationScope();
if (scope == null)
return ClassTypeHelper.getBases(this);
if (scope == null) {
if (bases == null) {
bases = ClassTypeHelper.getBases(this);
}
return bases;
}
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
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -11,6 +11,7 @@
* Markus Schorn (Wind River Systems)
* Andrew Ferguson (Symbian)
* Thomas Corbat (IFS)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -49,6 +50,7 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements ICPPClass
private ICPPClassTemplatePartialSpecialization[] partialSpecializations;
private ICPPDeferredClassInstance fDeferredInstance;
private boolean addedPartialSpecializationsOfIndex;
private ICPPBase[] bases;
public CPPClassTemplate(IASTName name) {
super(name);
@ -154,7 +156,10 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements ICPPClass
@Override
public ICPPBase[] getBases() {
return ClassTypeHelper.getBases(this);
if (bases == null) {
bases = ClassTypeHelper.getBases(this);
}
return bases;
}
@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
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -119,6 +119,7 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp
private IASTName[] declarations;
private boolean checked;
private ICPPClassType typeInIndex;
private ICPPBase[] bases;
public CPPClassType(IASTName name, IBinding indexBinding) {
name = stripQualifier(name);
@ -168,7 +169,7 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp
while (node instanceof IASTName)
node = node.getParent();
if (node instanceof ICPPASTCompositeTypeSpecifier)
return (ICPPASTCompositeTypeSpecifier)node;
return (ICPPASTCompositeTypeSpecifier) node;
}
return null;
}
@ -311,7 +312,10 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp
@Override
public ICPPBase[] getBases() {
return ClassTypeHelper.getBases(this);
if (bases == null) {
bases = ClassTypeHelper.getBases(this);
}
return bases;
}
@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;
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.REF;
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.IASTDeclarator;
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.IASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
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.ICPPASTBaseSpecifier;
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.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;
/**
* Helps analysis of the class declaration for user declared members relevant
* to deciding which implicit bindings to declare.
* Helps analysis of the class declaration for user declared members relevant for deciding
* which implicit bindings to declare.
*
* @see chapter 12 of the ISO specification
*/
class ImplicitsAnalysis {
private boolean hasUserDeclaredConstructor;
private boolean hasUserDeclaredCopyConstructor;
private boolean hasUserDeclaredCopyAssignmentOperator;
private boolean hasUserDeclaredDestructor;
final class ImplicitsAnalysis {
private static final IASTParameterDeclaration[][] EMPTY_ARRAY_OF_PARAMETER_ARRAYS = {};
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) {
this.classType= classType;
@ -53,29 +60,54 @@ class ImplicitsAnalysis {
}
public boolean hasUserDeclaredConstructor() {
return hasUserDeclaredConstructor;
return hasConstructor;
}
public boolean hasUserDeclaredCopyConstructor() {
return hasUserDeclaredCopyConstructor;
return hasCopyConstructor;
}
public boolean hasUserDeclaredCopyAssignmentOperator() {
return hasUserDeclaredCopyAssignmentOperator;
return hasCopyAssignmentOperator;
}
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() {
return (!hasUserDeclaredDestructor ? 1 : 0)
+ (!hasUserDeclaredConstructor ? 1 : 0)
+ (!hasUserDeclaredCopyConstructor ? 1 : 0)
+ (!hasUserDeclaredCopyAssignmentOperator ? 1 : 0);
return (!hasDestructor ? 1 : 0)
+ (!hasConstructor ? 1 : 0)
+ (!hasCopyConstructor ? 1 : 0)
+ (!hasCopyAssignmentOperator ? 1 : 0);
}
private void analyzeMembers(ICPPASTCompositeTypeSpecifier compositeTypeSpecifier) {
int numNontrivialConstructors = 0;
ICPPASTBaseSpecifier[] baseSpecifiers = compositeTypeSpecifier.getBaseSpecifiers();
IASTDeclaration[] members = compositeTypeSpecifier.getMembers();
char[] name = compositeTypeSpecifier.getName().getLookupKey();
for (IASTDeclaration member : members) {
@ -83,7 +115,7 @@ class ImplicitsAnalysis {
IASTDeclSpecifier spec = null;
if (member instanceof IASTSimpleDeclaration) {
IASTDeclarator[] dtors = ((IASTSimpleDeclaration) member).getDeclarators();
if (dtors.length == 0 || dtors.length > 1)
if (dtors.length != 1)
continue;
dcltor = dtors[0];
spec = ((IASTSimpleDeclaration) member).getDeclSpecifier();
@ -95,43 +127,54 @@ class ImplicitsAnalysis {
if (!(dcltor instanceof ICPPASTFunctionDeclarator))
continue;
char[] declName= ASTQueries.findInnermostDeclarator(dcltor).getName().getLookupKey();
IASTName memberName = ASTQueries.findInnermostDeclarator(dcltor).getName();
char[] declName = memberName.getLookupKey();
if (spec instanceof IASTSimpleDeclSpecifier &&
((IASTSimpleDeclSpecifier) spec).getType() == IASTSimpleDeclSpecifier.t_unspecified) {
if (CharArrayUtils.equals(declName, name)) {
hasUserDeclaredConstructor = true;
IASTParameterDeclaration[] ps = ((ICPPASTFunctionDeclarator) dcltor).getParameters();
if (ps.length >= 1) {
if (hasTypeReferenceToClassType(ps[0]) && parametersHaveInitializers(ps, 1)) {
hasUserDeclaredCopyConstructor= true;
hasConstructor = true;
IASTParameterDeclaration[] params = ((ICPPASTFunctionDeclarator) dcltor).getParameters();
if (params.length != 0) {
if (hasTypeReferenceToClassType(params[0])) {
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)) {
hasUserDeclaredDestructor = true;
hasDestructor = true;
}
} if (CharArrayUtils.equals(declName, OverloadableOperator.ASSIGN.toCharArray())) {
IASTParameterDeclaration[] ps = ((ICPPASTFunctionDeclarator) dcltor).getParameters();
if (ps.length == 1 && hasTypeReferenceToClassType(ps[0]))
hasUserDeclaredCopyAssignmentOperator = true;
IASTParameterDeclaration[] params = ((ICPPASTFunctionDeclarator) dcltor).getParameters();
if (params.length == 1 && hasTypeReferenceToClassType(params[0]))
hasCopyAssignmentOperator = true;
}
if (hasUserDeclaredCopyConstructor && hasUserDeclaredDestructor && hasUserDeclaredCopyAssignmentOperator)
break;
if (hasCopyConstructor && hasDestructor && hasCopyAssignmentOperator && baseSpecifiers.length == 0) {
break; // Nothing else to look for.
}
}
parametersOfNontrivialConstructors = trim(parametersOfNontrivialConstructors, numNontrivialConstructors);
}
private boolean hasTypeReferenceToClassType(IASTParameterDeclaration dec) {
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) {
t= SemanticUtil.getNestedType(t, TDEF);
if (t instanceof ICPPReferenceType) {
if (!((ICPPReferenceType) t).isRValueReference()) {
t= SemanticUtil.getNestedType(t, TDEF|REF|CVTYPE);
return classType.isSameType(t);
}
if (t instanceof ICPPReferenceType && !((ICPPReferenceType) t).isRValueReference()) {
t= SemanticUtil.getNestedType(t, TDEF|REF|CVTYPE);
return classType.isSameType(t);
}
}
}

View file

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

View file

@ -747,4 +747,12 @@ public class SemanticUtil {
}
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
* are made available under the terms of the Eclipse Public License v1.0
* 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 java.util.Arrays;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField;
@ -103,6 +104,11 @@ class CompositeCPPClassType extends CompositeCPPBinding implements ICPPClassType
return base.isVirtual();
}
@Override
public boolean isInheritedConstructorsSource() {
return base.isInheritedConstructorsSource();
}
@Override
public void setBaseClass(IBinding binding) {
if (writable && binding instanceof IType) {

View file

@ -38,6 +38,10 @@ class PDOMCPPBase implements ICPPBase, ICPPInternalBase {
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 long record;
@ -55,7 +59,8 @@ class PDOMCPPBase implements ICPPBase, ICPPInternalBase {
db.putRecPtr(record + CLASS_DEFINITION, classDefName.getRecord());
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);
}
@ -123,7 +128,7 @@ class PDOMCPPBase implements ICPPBase, ICPPInternalBase {
@Override
public int getVisibility() {
try {
return getFlags() & 0x3;
return getFlags() & FLAGS_VISIBILITY_MASK;
} catch (CoreException e) {
CCorePlugin.log(e);
return 0;
@ -133,7 +138,17 @@ class PDOMCPPBase implements ICPPBase, ICPPInternalBase {
@Override
public boolean isVirtual() {
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) {
CCorePlugin.log(e);
return false;
@ -160,7 +175,7 @@ class PDOMCPPBase implements ICPPBase, ICPPInternalBase {
private static class PDOMCPPBaseClone implements ICPPBase, ICPPInternalBase {
private final ICPPBase base;
private IType baseClass = null;
private IType baseClass;
public PDOMCPPBaseClone(ICPPBase base) {
this.base = base;
@ -203,6 +218,11 @@ class PDOMCPPBase implements ICPPBase, ICPPInternalBase {
return base.isVirtual();
}
@Override
public boolean isInheritedConstructorsSource() {
return base.isInheritedConstructorsSource();
}
@Override
public void setBaseClass(IBinding binding) {
if (binding instanceof IType)