From b96e29ae6227ad3119dfd37a426743fddf5ba41c Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Thu, 24 Apr 2014 16:57:43 -0700 Subject: [PATCH] Bug 424068 - [C++11] Inheriting constructors. Inheriting of template constructors is not supported yet. --- .../core/parser/tests/ast2/AST2CPPTests.java | 55 ++++++- .../tests/IndexCPPBindingResolutionTest.java | 60 +++++++- .../cdt/core/dom/ast/cpp/ICPPBase.java | 14 +- .../AbstractCPPClassSpecializationScope.java | 93 +++++++++--- .../core/dom/parser/cpp/CPPBaseClause.java | 31 ++-- .../core/dom/parser/cpp/CPPClassScope.java | 143 ++++++++++++++++-- .../parser/cpp/CPPClassSpecialization.java | 14 +- .../core/dom/parser/cpp/CPPClassTemplate.java | 9 +- .../core/dom/parser/cpp/CPPClassType.java | 10 +- .../parser/cpp/CPPInheritedConstructor.java | 74 +++++++++ .../dom/parser/cpp/ImplicitsAnalysis.java | 117 +++++++++----- .../parser/cpp/semantics/CPPSemantics.java | 4 +- .../parser/cpp/semantics/SemanticUtil.java | 8 + .../composite/cpp/CompositeCPPClassType.java | 8 +- .../core/pdom/dom/cpp/PDOMCPPBase.java | 28 +++- 15 files changed, 566 insertions(+), 102 deletions(-) create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPInheritedConstructor.java diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index fb297ac3e46..f5fa1afd401 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -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 + // struct A { + // A(T); + // }; + // + // struct B : public A { + // using A::A; + // }; + // + // void foo(B); + // + // int test() { + // foo(1); + // } + public void testInheritingConstructorWithTemplate_1() throws Exception { + parseAndCheckBindings(); + } + + // struct A { + // A(int); + // }; + // + // template + // struct B : public T { + // using T::T; + // }; + // + // void foo(B); + // + // 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); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java index 6177416fb6e..4c6631da5da 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java @@ -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 + // struct A { + // A(T); + // }; + + // struct B : public A { + // using A::A; + // }; + // + // void foo(B); + // + // int test() { + // foo(1); + // } + public void testInheritingConstructorWithTemplate_1() throws Exception { + checkBindings(); + } + + // struct A { + // A(int); + // }; + // + // template + // struct B : public T { + // using T::T; + // }; + + // void foo(B); + // + // int test() { + // foo(1); + // } + public void testInheritingConstructorWithTemplate_2() throws Exception { + checkBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBase.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBase.java index a76200d132c..41a306403a7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBase.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBase.java @@ -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,18 +66,25 @@ 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 */ public ICPPBase clone(); - /** + /** * Used internally to change cloned bases. * @noreference This method is not intended to be referenced by clients. */ public void setBaseClass(IBinding baseClass); - /** + /** * Used internally to change cloned bases. * @noreference This method is not intended to be referenced by clients. */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java index 09f0f95235a..c523fdf9858 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java @@ -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 diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBaseClause.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBaseClause.java index a9d0a885ffc..15eb50c2ef9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBaseClause.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBaseClause.java @@ -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; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java index c5411365d54..242f23618ea 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java @@ -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; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java index 70c14f98b0b..c7bb978411a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java @@ -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> fInProgress= new ThreadLocal>() { @Override protected Set initialValue() { - return new HashSet(); + 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); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java index dc04f2b9a31..3d288feb2ec 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java @@ -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 diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java index 1e1d77fd62b..6eb08dd0e4b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java @@ -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 diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPInheritedConstructor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPInheritedConstructor.java new file mode 100644 index 00000000000..76a188ed663 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPInheritedConstructor.java @@ -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(); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ImplicitsAnalysis.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ImplicitsAnalysis.java index 7e09ae75f6d..812f88e5c50 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ImplicitsAnalysis.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ImplicitsAnalysis.java @@ -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); } } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 507fc570139..8abc87c5ca2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java index 266f86edf73..58f470bd23c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java @@ -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; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPClassType.java index 78cfc1a576e..47e1fdc3401 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPClassType.java @@ -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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPBase.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPBase.java index b8c2f6b751c..016a0c7a557 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPBase.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPBase.java @@ -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)