mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Reverted "Bug 393717 - Have constructor definitions reference implicitly
called base constructors via implicit names" Change-Id: Icb3614727b2da9ed8d0e97ee08c7d4ba7e6eef8d
This commit is contained in:
parent
ad52facf4e
commit
f6828f8daf
4 changed files with 14 additions and 214 deletions
|
@ -24,11 +24,7 @@ import static org.eclipse.cdt.core.parser.ParserLanguage.CPP;
|
||||||
import static org.eclipse.cdt.core.parser.tests.VisibilityAsserts.assertVisibility;
|
import static org.eclipse.cdt.core.parser.tests.VisibilityAsserts.assertVisibility;
|
||||||
import static org.junit.Assert.assertNotEquals;
|
import static org.junit.Assert.assertNotEquals;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import junit.framework.TestSuite;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.IName;
|
import org.eclipse.cdt.core.dom.IName;
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
||||||
|
@ -155,7 +151,11 @@ 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.index.IndexCPPSignatureUtil;
|
||||||
import org.eclipse.cdt.internal.core.parser.ParserException;
|
import org.eclipse.cdt.internal.core.parser.ParserException;
|
||||||
|
|
||||||
import junit.framework.TestSuite;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
public class AST2CPPTests extends AST2TestBase {
|
public class AST2CPPTests extends AST2TestBase {
|
||||||
|
|
||||||
|
@ -11602,73 +11602,4 @@ public class AST2CPPTests extends AST2TestBase {
|
||||||
// this test will need to be updated.
|
// this test will need to be updated.
|
||||||
helper.assertVariableValue("generic_lambdas_supported", 0);
|
helper.assertVariableValue("generic_lambdas_supported", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct A {
|
|
||||||
// A() {}
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// struct B {
|
|
||||||
// B() {}
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// struct C : A {
|
|
||||||
// C() {}
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// struct D : virtual A, virtual B {
|
|
||||||
// D() {}
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// struct E {
|
|
||||||
// E() {}
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// struct F : D, virtual E {
|
|
||||||
// F() {}
|
|
||||||
// };
|
|
||||||
public void testImplicitlyCalledBaseConstructor_393717() throws Exception {
|
|
||||||
BindingAssertionHelper helper = getAssertionHelper();
|
|
||||||
|
|
||||||
ICPPConstructor aCtor = helper.assertNonProblem("A()", "A");
|
|
||||||
ICPPConstructor bCtor = helper.assertNonProblem("B()", "B");
|
|
||||||
ICPPConstructor dCtor = helper.assertNonProblem("D()", "D");
|
|
||||||
ICPPConstructor eCtor = helper.assertNonProblem("E()", "E");
|
|
||||||
|
|
||||||
ICPPASTFunctionDefinition ctorDef = helper.assertNode("C() {}");
|
|
||||||
IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) ctorDef).getImplicitNames();
|
|
||||||
assertEquals(1, implicitNames.length);
|
|
||||||
assertEquals(aCtor, implicitNames[0].resolveBinding());
|
|
||||||
|
|
||||||
ctorDef = helper.assertNode("D() {}");
|
|
||||||
implicitNames = ((IASTImplicitNameOwner) ctorDef).getImplicitNames();
|
|
||||||
sortNames(implicitNames);
|
|
||||||
assertEquals(2, implicitNames.length);
|
|
||||||
assertEquals(aCtor, implicitNames[0].resolveBinding());
|
|
||||||
assertEquals(bCtor, implicitNames[1].resolveBinding());
|
|
||||||
|
|
||||||
ctorDef = helper.assertNode("F() {}");
|
|
||||||
implicitNames = ((IASTImplicitNameOwner) ctorDef).getImplicitNames();
|
|
||||||
sortNames(implicitNames);
|
|
||||||
assertEquals(4, implicitNames.length);
|
|
||||||
assertEquals(aCtor, implicitNames[0].resolveBinding());
|
|
||||||
assertEquals(bCtor, implicitNames[1].resolveBinding());
|
|
||||||
assertEquals(dCtor, implicitNames[2].resolveBinding());
|
|
||||||
assertEquals(eCtor, implicitNames[3].resolveBinding());
|
|
||||||
}
|
|
||||||
|
|
||||||
// struct A {
|
|
||||||
// A(int, int);
|
|
||||||
// };
|
|
||||||
// void a(A);
|
|
||||||
// int main() {
|
|
||||||
// a(A{3, 4});
|
|
||||||
// }
|
|
||||||
public void testImplicitConstructorNameInTypeConstructorExpression_447431() throws Exception {
|
|
||||||
BindingAssertionHelper helper = getAssertionHelper();
|
|
||||||
ICPPConstructor ctor = helper.assertNonProblem("A(int, int)", "A");
|
|
||||||
ICPPASTSimpleTypeConstructorExpression typeConstructorExpr = helper.assertNode("A{3, 4}");
|
|
||||||
IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) typeConstructorExpr).getImplicitNames();
|
|
||||||
assertEquals(1, implicitNames.length);
|
|
||||||
assertEquals(ctor, implicitNames[0].resolveBinding());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,6 @@ import static org.eclipse.cdt.core.parser.ParserLanguage.CPP;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -915,15 +913,4 @@ public class AST2TestBase extends BaseTestCase {
|
||||||
assertInstance(stmt, IASTExpressionStatement.class);
|
assertInstance(stmt, IASTExpressionStatement.class);
|
||||||
return (T) ((IASTExpressionStatement) stmt).getExpression();
|
return (T) ((IASTExpressionStatement) stmt).getExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort the given array of AST names lexicographically.
|
|
||||||
*/
|
|
||||||
protected static <T extends IASTName> void sortNames(T[] names) {
|
|
||||||
Arrays.sort(names, new Comparator<IASTName>() {
|
|
||||||
@Override
|
|
||||||
public int compare(IASTName a, IASTName b) {
|
|
||||||
return a.toString().compareTo(b.toString());
|
|
||||||
}});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2004, 2015 IBM Corporation and others.
|
* Copyright (c) 2004, 2014 IBM Corporation and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -12,30 +12,18 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
|
||||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTAttributeOwner;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTAttributeOwner;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
||||||
|
|
||||||
|
@ -44,12 +32,11 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
||||||
* it may contain member initializers.
|
* it may contain member initializers.
|
||||||
*/
|
*/
|
||||||
public class CPPASTFunctionDefinition extends ASTAttributeOwner
|
public class CPPASTFunctionDefinition extends ASTAttributeOwner
|
||||||
implements ICPPASTFunctionDefinition, IASTAmbiguityParent, IASTImplicitNameOwner {
|
implements ICPPASTFunctionDefinition, IASTAmbiguityParent {
|
||||||
private IASTDeclSpecifier declSpecifier;
|
private IASTDeclSpecifier declSpecifier;
|
||||||
private IASTFunctionDeclarator declarator;
|
private IASTFunctionDeclarator declarator;
|
||||||
private IASTStatement bodyStatement;
|
private IASTStatement bodyStatement;
|
||||||
private ICPPASTConstructorChainInitializer[] memInits;
|
private ICPPASTConstructorChainInitializer[] memInits;
|
||||||
private IASTImplicitName[] implicitNames; // for constructors: base constructors called implicitly
|
|
||||||
private int memInitPos= -1;
|
private int memInitPos= -1;
|
||||||
private boolean fDeleted;
|
private boolean fDeleted;
|
||||||
private boolean fDefaulted;
|
private boolean fDefaulted;
|
||||||
|
@ -212,14 +199,6 @@ public class CPPASTFunctionDefinition extends ASTAttributeOwner
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.shouldVisitImplicitNames) {
|
|
||||||
for (IASTImplicitName implicitName : getImplicitNames()) {
|
|
||||||
if (!implicitName.accept(action)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bodyStatement != null && !bodyStatement.accept(action))
|
if (bodyStatement != null && !bodyStatement.accept(action))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -247,67 +226,4 @@ public class CPPASTFunctionDefinition extends ASTAttributeOwner
|
||||||
bodyStatement = (IASTStatement) other;
|
bodyStatement = (IASTStatement) other;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public IASTImplicitName[] getImplicitNames() {
|
|
||||||
if (implicitNames == null) {
|
|
||||||
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
|
||||||
IASTName functionName = ASTQueries.findInnermostDeclarator(declarator).getName();
|
|
||||||
IBinding function = functionName.resolveBinding();
|
|
||||||
if (function instanceof ICPPConstructor) {
|
|
||||||
ICPPClassType classOwner = ((ICPPConstructor) function).getClassOwner();
|
|
||||||
|
|
||||||
// Determine the bases of 'classOwner' that need to be initialized by this constructor.
|
|
||||||
Set<ICPPClassType> basesThatNeedInitialization = new HashSet<>();
|
|
||||||
for (ICPPBase base : ClassTypeHelper.getBases(classOwner, this)) {
|
|
||||||
IType baseType = base.getBaseClassType();
|
|
||||||
if (baseType instanceof ICPPClassType) {
|
|
||||||
basesThatNeedInitialization.add((ICPPClassType) baseType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (ICPPClassType virtualBase : ClassTypeHelper.getVirtualBases(classOwner, this)) {
|
|
||||||
basesThatNeedInitialization.add(virtualBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go through the bases determined above, and see which ones aren't initialized
|
|
||||||
// explicitly in the mem-initializer list.
|
|
||||||
for (ICPPClassType base : basesThatNeedInitialization) {
|
|
||||||
if (!isInitializedExplicitly(base)) {
|
|
||||||
// Try to find a default constructor to create an implicit name for.
|
|
||||||
for (ICPPConstructor constructor : ClassTypeHelper.getConstructors(base, this)) {
|
|
||||||
if (constructor.getRequiredArgumentCount() == 0) { // default constructor
|
|
||||||
CPPASTImplicitName ctorName = new CPPASTImplicitName(
|
|
||||||
constructor.getNameCharArray(), this);
|
|
||||||
ctorName.setBinding(constructor);
|
|
||||||
ctorName.setOffsetAndLength((ASTNode) functionName);
|
|
||||||
implicitNames = ArrayUtil.append(implicitNames, ctorName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
implicitNames = ArrayUtil.trim(implicitNames);
|
|
||||||
}
|
|
||||||
return implicitNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns whether the base type 'base' is explicitly initialized by one of the mem-initializers
|
|
||||||
// of this constructor.
|
|
||||||
private boolean isInitializedExplicitly(ICPPClassType base) {
|
|
||||||
for (ICPPASTConstructorChainInitializer memInitializer : getMemberInitializers()) {
|
|
||||||
IBinding binding = memInitializer.getMemberInitializerId().resolveBinding();
|
|
||||||
if (binding instanceof IType) {
|
|
||||||
if (((IType) binding).isSameType(base)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (binding instanceof ICPPConstructor) {
|
|
||||||
if (((ICPPConstructor) binding).getClassOwner().isSameType(base)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2004, 2015 IBM Corporation and others.
|
* Copyright (c) 2004, 2014 IBM Corporation and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -24,7 +24,6 @@ import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||||
|
@ -285,15 +284,15 @@ public class ClassTypeHelper {
|
||||||
* @return An array of base classes in arbitrary order.
|
* @return An array of base classes in arbitrary order.
|
||||||
*/
|
*/
|
||||||
public static ICPPClassType[] getAllBases(ICPPClassType classType, IASTNode point) {
|
public static ICPPClassType[] getAllBases(ICPPClassType classType, IASTNode point) {
|
||||||
Set<ICPPClassType> result= new HashSet<>();
|
HashSet<ICPPClassType> result= new HashSet<>();
|
||||||
result.add(classType);
|
result.add(classType);
|
||||||
getAllBases(classType, result, point);
|
getAllBases(classType, result, point);
|
||||||
result.remove(classType);
|
result.remove(classType);
|
||||||
return result.toArray(new ICPPClassType[result.size()]);
|
return result.toArray(new ICPPClassType[result.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void getAllBases(ICPPClassType classType, Set<ICPPClassType> result, IASTNode point) {
|
private static void getAllBases(ICPPClassType classType, HashSet<ICPPClassType> result, IASTNode point) {
|
||||||
ICPPBase[] bases= getBases(classType, point);
|
ICPPBase[] bases= ClassTypeHelper.getBases(classType, point);
|
||||||
for (ICPPBase base : bases) {
|
for (ICPPBase base : bases) {
|
||||||
IBinding b= base.getBaseClass();
|
IBinding b= base.getBaseClass();
|
||||||
if (b instanceof ICPPClassType) {
|
if (b instanceof ICPPClassType) {
|
||||||
|
@ -305,39 +304,6 @@ public class ClassTypeHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all (direct or indirect) virtual base classes of 'classType'.
|
|
||||||
* @param point the point of instantiation for name lookups
|
|
||||||
*/
|
|
||||||
public static ICPPClassType[] getVirtualBases(ICPPClassType classType, IASTNode point) {
|
|
||||||
Set<ICPPClassType> result = new HashSet<>();
|
|
||||||
result.add(classType);
|
|
||||||
getVirtualBases(classType, result, point);
|
|
||||||
result.remove(classType);
|
|
||||||
return result.toArray(new ICPPClassType[result.size()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function for getVirtualBases(classType, point).
|
|
||||||
private static void getVirtualBases(ICPPClassType classType, Set<ICPPClassType> result, IASTNode point) {
|
|
||||||
ICPPBase[] bases = getBases(classType, point);
|
|
||||||
for (ICPPBase base : bases) {
|
|
||||||
IBinding b = base.getBaseClass();
|
|
||||||
if (b instanceof ICPPClassType) {
|
|
||||||
final ICPPClassType baseClass = (ICPPClassType) b;
|
|
||||||
if (base.isVirtual()) {
|
|
||||||
if (result.add(baseClass)) {
|
|
||||||
getVirtualBases(baseClass, result, point);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// A non-virtual base could have virtual bases in its hierarchy.
|
|
||||||
if (!result.contains(baseClass)) {
|
|
||||||
getVirtualBases(baseClass, result, point);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks inheritance relationship between two classes.
|
* Checks inheritance relationship between two classes.
|
||||||
* @return {@code true} if {@code subclass} is a subclass of {@code superclass}.
|
* @return {@code true} if {@code subclass} is a subclass of {@code superclass}.
|
||||||
|
|
Loading…
Add table
Reference in a new issue