From 9ae111eb8c486a694230b25341c4edb047d71508 Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Tue, 23 Aug 2016 05:18:34 -0700 Subject: [PATCH] Bug 424068 - [C++11] Inheriting constructors This change treats inherited constructors in accordance with http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0136r1.html Change-Id: Ia45edfeda0772daf57457ecdd7e16979ce7f321a --- .../core/parser/tests/ast2/AST2CPPTests.java | 6 +- .../tests/IndexCPPBindingResolutionTest.java | 25 +++- .../AbstractCPPClassSpecializationScope.java | 6 +- .../core/dom/parser/cpp/CPPClassScope.java | 93 ++------------- .../parser/cpp/CPPInheritedConstructor.java | 73 ------------ .../core/dom/parser/cpp/ClassTypeHelper.java | 106 ++++++++++++++++- .../dom/parser/cpp/ImplicitsAnalysis.java | 111 +++++------------- .../dom/cpp/PDOMCPPClassSpecialization.java | 7 +- .../core/pdom/dom/cpp/PDOMCPPClassType.java | 3 +- 9 files changed, 178 insertions(+), 252 deletions(-) delete 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 e49cd7ed0e2..c55052f03a9 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 @@ -30,6 +30,8 @@ import java.io.StringReader; import java.util.Arrays; import java.util.HashSet; +import junit.framework.TestSuite; + import org.eclipse.cdt.core.dom.IName; import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; import org.eclipse.cdt.core.dom.ast.EScopeKind; @@ -155,8 +157,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.index.IndexCPPSignatureUtil; import org.eclipse.cdt.internal.core.parser.ParserException; -import junit.framework.TestSuite; - public class AST2CPPTests extends AST2TestBase { public AST2CPPTests() { @@ -1470,7 +1470,7 @@ public class AST2CPPTests extends AST2TestBase { // void test(A a) { // foo(a); // } - public void _testInheritedTemplateConstructor() throws Exception { + public void testInheritedTemplateConstructor() throws Exception { parseAndCheckBindings(); } 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 7d2994faef9..21221577f6c 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 @@ -18,6 +18,8 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Set; +import junit.framework.TestSuite; + import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.EScopeKind; @@ -52,8 +54,6 @@ import org.eclipse.cdt.core.parser.IProblem; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.core.runtime.CoreException; -import junit.framework.TestSuite; - /** * For testing PDOM binding CPP language resolution */ @@ -1865,6 +1865,27 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti checkBindings(); } + // template + // struct A {}; + // + // struct B { + // template + // B(const A&, int i = 3); + // }; + // + // struct C : public B { + // using B::B; + // }; + + // void foo(C); + // + // void test(A a) { + // foo(a); + // } + public void testInheritedTemplateConstructor() { + checkBindings(); + } + // constexpr int foo(int a = 42) { // return a; // } 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 5abf4895555..e4c4af6320f 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 @@ -14,8 +14,6 @@ *******************************************************************************/ 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; @@ -285,8 +283,8 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat } existingConstructorParamTypes[i] = types; } - ICPPMethod[] constructors = createInheritedConsructors(this, specialClass.getNameCharArray(), - getBases(point), existingConstructorParamTypes, point); + ICPPMethod[] constructors = ClassTypeHelper.getInheritedConstructors(this, getBases(point), + existingConstructorParamTypes, point); ownInheritedConstructors = constructors; } return ownInheritedConstructors; 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 24e1451280b..35619cef5cc 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 @@ -20,8 +20,6 @@ import static org.eclipse.cdt.core.parser.util.ArrayUtil.addAll; 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; @@ -56,7 +54,6 @@ 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.CharArrayObjectMap; import org.eclipse.cdt.core.parser.util.CharArrayUtils; @@ -67,7 +64,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; import org.eclipse.cdt.internal.core.parser.util.ContentAssistMatcherFactory; /** - * Base implementation for c++ scopes. + * Base implementation for C++ scopes. */ public class CPPClassScope extends CPPScope implements ICPPClassScope { private static final ICPPFunctionType DESTRUCTOR_FUNCTION_TYPE = @@ -145,23 +142,17 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { 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); - } + markInheritedConstructorsSourceBases(compTypeSpec); } - private ICPPBase[] findInheritedConstructorsSourceBases(ICPPASTCompositeTypeSpecifier compositeTypeSpec) { + /** + * Marks bases that serve as sources of inherited constructors. + */ + private void markInheritedConstructorsSourceBases(ICPPASTCompositeTypeSpecifier compositeTypeSpec) { ICPPBase[] bases = ClassTypeHelper.getBases(getClassType(), compositeTypeSpec); if (bases.length == 0) - return bases; - ICPPBase[] results = ICPPBase.EMPTY_BASE_ARRAY; + return; IASTDeclaration[] members = compositeTypeSpec.getMembers(); - int n = 0; for (IASTDeclaration member : members) { if (member instanceof ICPPASTUsingDeclaration) { IASTName name = ((ICPPASTUsingDeclaration) member).getName(); @@ -178,13 +169,11 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { IType baseClass = base.getBaseClassType(); if (type.isSameType(baseClass)) { ((CPPBaseClause) base).setInheritedConstructorsSource(true); - results = appendAt(results, n++, base); } } } } } - return trim(results, n); } private static boolean isConstructorNameForType(char[] lastName, IType type) { @@ -197,74 +186,6 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { } return false; } - - 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(); - // 12.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 public IScope getParent() { 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 deleted file mode 100644 index 755db52fd3c..00000000000 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPInheritedConstructor.java +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * 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 a constructor inherited from a base class (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, false); - 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/ClassTypeHelper.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java index 040a880a935..8a79730b759 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java @@ -15,6 +15,12 @@ *******************************************************************************/ 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; + import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; @@ -473,7 +479,105 @@ public class ClassTypeHelper { if (scope == null) { return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY; } - return scope.getConstructors(); + ICPPConstructor[] constructors = scope.getConstructors(); + return getAllConstructors(host, constructors, null); + } + + /** + * Returns all constructors for a given class type. The returned constructors include the explicitly + * declared, the implicit, and the inherited ones. + * + * @param classType the class to get the constructors for + * @param declaredAndImplicitConstructors the declared and implicit constructors of the class + * @param point the point of template instantiation, if applicable + * @return an array of all class constructors + */ + public static ICPPConstructor[] getAllConstructors(ICPPClassType classType, + ICPPConstructor[] declaredAndImplicitConstructors, IASTNode point) { + IType[][] paramTypes = new IType[declaredAndImplicitConstructors.length][]; + for (int i = 0; i < declaredAndImplicitConstructors.length; i++) { + ICPPConstructor ctor = declaredAndImplicitConstructors[i]; + paramTypes[i] = ctor.getType().getParameterTypes(); + } + ICPPConstructor[] inheritedConstructors = getInheritedConstructors( + (ICPPClassScope) classType.getCompositeScope(), getBases(classType, point), paramTypes, point); + return ArrayUtil.addAll(declaredAndImplicitConstructors, inheritedConstructors); + } + + /** + * Returns inherited constructors for a given class scope. + * + * @param scope the composite scope of the class to get the constructors for + * @param bases the base class relationships of the class + * @param existingConstructorParamTypes parameter types of the declared and the implicit constructors + * @param point the point of template instantiation, if applicable + * @return an array of all inherited constructors + */ + public static ICPPConstructor[] getInheritedConstructors(ICPPClassScope scope, ICPPBase[] bases, + IType[][] existingConstructorParamTypes, IASTNode point) { + ICPPConstructor[] inheritedConstructors = ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY; + int n = 0; + for (ICPPBase base : bases) { + if (!base.isInheritedConstructorsSource()) + continue; + IBinding baseType = base.getBaseClass(); + if (!(baseType instanceof ICPPClassType)) + continue; + ICPPClassType baseClass = (ICPPClassType) baseType; + ICPPConstructor[] ctors = getConstructors(baseClass, point); + for (ICPPConstructor ctor : ctors) { + if (canBeInherited(ctor, baseClass, existingConstructorParamTypes)) + inheritedConstructors = appendAt(inheritedConstructors, n++, ctor); + } + } + return trim(inheritedConstructors, n); + } + + private static boolean canBeInherited(ICPPConstructor ctor, ICPPClassType baseClass, + IType[][] existingConstructorParamTypes) { + ICPPParameter[] params = ctor.getParameters(); + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0136r1.html + // 7.3.3-4 [Note] If a constructor or assignment operator brought from a base class into a derived + // class has the signature of a copy/move constructor or assignment operator for the derived class + // (12.8), the using-declaration does not by itself suppress the implicit declaration of the derived + // class member; the member from the base class is hidden or overridden by the implicitly-declared + // copy/move constructor or assignment operator of the derived class, as described below. + for (int k = Math.max(ctor.getRequiredArgumentCount(), 1); k <= params.length; k++) { + if (k == 1 && isReferenceToClass(params[0].getType(), baseClass)) { + continue; // Skip the copy constructor. + } + if (findMatchingSignature(params, k, existingConstructorParamTypes) < 0) { + return true; + } + } + return false; + } + + 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; } public static ICPPClassType[] getNestedClasses(ICPPInternalClassTypeMixinHost host) { 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 fb09e6bf341..f485adbe428 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,8 +12,6 @@ *******************************************************************************/ 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; @@ -22,15 +20,12 @@ 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.IASTNode; 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.ICPPASTFieldDeclarator; 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.ICPPBase; @@ -49,19 +44,16 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; * @see chapter 12 of the ISO specification */ final class ImplicitsAnalysis { - private static final IASTParameterDeclaration[][] EMPTY_ARRAY_OF_PARAMETER_ARRAYS = {}; - private final ICPPClassType classType; private final ICPPASTCompositeTypeSpecifier compositeTypeSpecifier; private boolean hasConstructor; private boolean hasCopyConstructor; private boolean hasCopyAssignmentOperator; private boolean hasDestructor; - private IASTParameterDeclaration[][] parametersOfNontrivialConstructors = EMPTY_ARRAY_OF_PARAMETER_ARRAYS; private boolean hasNonStaticFields; ImplicitsAnalysis(ICPPASTCompositeTypeSpecifier compositeTypeSpecifier, ICPPClassType classType) { - this.classType= classType; + this.classType = classType; this.compositeTypeSpecifier = compositeTypeSpecifier; analyzeMembers(compositeTypeSpecifier); } @@ -82,25 +74,6 @@ final class ImplicitsAnalysis { 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. */ @@ -112,9 +85,6 @@ final class ImplicitsAnalysis { } 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) { @@ -131,59 +101,42 @@ final class ImplicitsAnalysis { spec = ((IASTFunctionDefinition) member).getDeclSpecifier(); } - if (dcltor instanceof ICPPASTFunctionDeclarator) { - 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)) { - 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] == '~' && - CharArrayUtils.equals(declName, 1, name.length, name)) { - hasDestructor = true; - } - } if (CharArrayUtils.equals(declName, OverloadableOperator.ASSIGN.toCharArray())) { - IASTParameterDeclaration[] params = ((ICPPASTFunctionDeclarator) dcltor).getParameters(); - if (params.length == 1 && hasTypeReferenceToClassType(params[0])) - hasCopyAssignmentOperator = true; - } - - if (hasCopyConstructor && hasDestructor && hasCopyAssignmentOperator && baseSpecifiers.length == 0 - && hasNonStaticFields) { - break; // Nothing else to look for. - } - } else if (dcltor instanceof ICPPASTFieldDeclarator && - spec != null && spec.getStorageClass() != IASTDeclSpecifier.sc_static) { - hasNonStaticFields = true; - } - } + if (!(dcltor instanceof ICPPASTFunctionDeclarator)) + continue; - parametersOfNontrivialConstructors = trim(parametersOfNontrivialConstructors, numNontrivialConstructors); + char[] declName= ASTQueries.findInnermostDeclarator(dcltor).getName().getLookupKey(); + + if (spec instanceof IASTSimpleDeclSpecifier && + ((IASTSimpleDeclSpecifier) spec).getType() == IASTSimpleDeclSpecifier.t_unspecified) { + if (CharArrayUtils.equals(declName, name)) { + hasConstructor = true; + IASTParameterDeclaration[] params = ((ICPPASTFunctionDeclarator) dcltor).getParameters(); + if (params.length != 0 && hasTypeReferenceToClassType(params[0]) + && parametersHaveInitializers(params, 1)) { + hasCopyConstructor = true; + } + } else if (declName.length != 0 && declName[0] == '~' && + CharArrayUtils.equals(declName, 1, name.length, name)) { + hasDestructor = true; + } + } else if (CharArrayUtils.equals(declName, OverloadableOperator.ASSIGN.toCharArray())) { + IASTParameterDeclaration[] params = ((ICPPASTFunctionDeclarator) dcltor).getParameters(); + if (params.length == 1 && hasTypeReferenceToClassType(params[0])) + hasCopyAssignmentOperator = true; + } + + if (hasCopyConstructor && hasDestructor && hasCopyAssignmentOperator) + break; + } } private boolean hasTypeReferenceToClassType(IASTParameterDeclaration decl) { if (decl instanceof ICPPASTParameterDeclaration) { IType t = CPPVisitor.createType((ICPPASTParameterDeclaration) decl, false); if (t != null) { - t= SemanticUtil.getNestedType(t, TDEF); + t = SemanticUtil.getNestedType(t, TDEF); if (t instanceof ICPPReferenceType && !((ICPPReferenceType) t).isRValueReference()) { - t= SemanticUtil.getNestedType(t, TDEF|REF|CVTYPE); + t = SemanticUtil.getNestedType(t, TDEF|REF|CVTYPE); return classType.isSameType(t); } } @@ -196,9 +149,8 @@ final class ImplicitsAnalysis { */ private boolean parametersHaveInitializers(IASTParameterDeclaration[] params, int offset) { for (int i = offset; i < params.length; i++) { - if (params[i].getDeclarator().getInitializer() == null) { + if (params[i].getDeclarator().getInitializer() == null) return false; - } } return true; } @@ -219,9 +171,8 @@ final class ImplicitsAnalysis { ICPPClassType[] baseClasses = ClassTypeHelper.getAllBases(classType, compositeTypeSpecifier); for (ICPPClassType baseClass : baseClasses) { ICPPConstructor ctor = getDefaultConstructor(baseClass, compositeTypeSpecifier); - if (ctor == null || !ctor.isConstexpr()) { + if (ctor == null || !ctor.isConstexpr()) return false; - } } return true; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java index f4f14ec4061..eecd7f27bbc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java @@ -281,12 +281,15 @@ class PDOMCPPClassSpecialization extends PDOMCPPSpecialization public ICPPConstructor[] getConstructors(IASTNode point) { IScope scope= getCompositeScope(); if (scope instanceof ICPPClassSpecializationScope) { - return ((ICPPClassSpecializationScope) scope).getConstructors(point); + ICPPConstructor[] constructors = ((ICPPClassSpecializationScope) scope).getConstructors(point); + return ClassTypeHelper.getAllConstructors(this, constructors, point); } + try { PDOMClassUtil.ConstructorCollector visitor= new PDOMClassUtil.ConstructorCollector(); PDOMCPPClassScope.acceptViaCache(this, visitor, false); - return visitor.getConstructors(); + ICPPConstructor[] constructors = visitor.getConstructors(); + return ClassTypeHelper.getAllConstructors(this, constructors, point); } catch (CoreException e) { CCorePlugin.log(e); return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java index 4fea39a7d56..6eae0307abb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java @@ -330,7 +330,8 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO PDOMClassUtil.ConstructorCollector visitor= new PDOMClassUtil.ConstructorCollector(); try { PDOMCPPClassScope.acceptViaCache(this, visitor, false); - return visitor.getConstructors(); + ICPPConstructor[] constructors = visitor.getConstructors(); + return ClassTypeHelper.getAllConstructors(this, constructors, null); } catch (CoreException e) { CCorePlugin.log(e); return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY;