mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
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
This commit is contained in:
parent
310a13309b
commit
9ae111eb8c
9 changed files with 178 additions and 252 deletions
|
@ -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<int> a) {
|
||||
// foo(a);
|
||||
// }
|
||||
public void _testInheritedTemplateConstructor() throws Exception {
|
||||
public void testInheritedTemplateConstructor() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <typename T>
|
||||
// struct A {};
|
||||
//
|
||||
// struct B {
|
||||
// template <typename T>
|
||||
// B(const A<T>&, int i = 3);
|
||||
// };
|
||||
//
|
||||
// struct C : public B {
|
||||
// using B::B;
|
||||
// };
|
||||
|
||||
// void foo(C);
|
||||
//
|
||||
// void test(A<int> a) {
|
||||
// foo(a);
|
||||
// }
|
||||
public void testInheritedTemplateConstructor() {
|
||||
checkBindings();
|
||||
}
|
||||
|
||||
// constexpr int foo(int a = 42) {
|
||||
// return a;
|
||||
// }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue