1
0
Fork 0
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:
Sergey Prigogin 2016-08-23 05:18:34 -07:00 committed by Gerrit Code Review @ Eclipse.org
parent 310a13309b
commit 9ae111eb8c
9 changed files with 178 additions and 252 deletions

View file

@ -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();
}

View file

@ -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;
// }

View file

@ -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;

View file

@ -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() {

View file

@ -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();
}
}

View file

@ -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) {

View file

@ -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;
}

View file

@ -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;

View file

@ -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;