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 a5b80a63f97..b5aeac6af1f 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 @@ -9118,4 +9118,40 @@ public class AST2CPPTests extends AST2BaseTest { assertSame(fc, ref); bh.assertNonProblem("g(0 ? p : \"\")", 1); // } + + // struct C { + // C(); + // C(int a, int b); + // }; + // + // C c1; // C() + // C c2(1,2); // C(int, int) + // C c3 ({1,2}); // C(C(int, int)) // copy ctor is elided + // C c4 ={1,2}; // C(C(int, int)) // copy ctor is elided + // C c5 {1,2}; // C(int, int) + public void testCtorForAutomaticVariables_156668() throws Exception { + String code= getAboveComment(); + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + IFunction ctor1= bh.assertNonProblem("C();", 1); + IFunction ctor2= bh.assertNonProblem("C(int a, int b);", 1); + + IASTName name; + IASTImplicitNameOwner dtor; + name= bh.findName("c1", 2); + dtor= (IASTImplicitNameOwner) name.getParent(); + assertSame(ctor1, dtor.getImplicitNames()[0].resolveBinding()); + name= bh.findName("c2", 2); + dtor= (IASTImplicitNameOwner) name.getParent(); + assertSame(ctor2, dtor.getImplicitNames()[0].resolveBinding()); + name= bh.findName("c3", 2); + dtor= (IASTImplicitNameOwner) name.getParent(); + assertSame(ctor2, dtor.getImplicitNames()[0].resolveBinding()); + name= bh.findName("c4", 2); + dtor= (IASTImplicitNameOwner) name.getParent(); + assertSame(ctor2, dtor.getImplicitNames()[0].resolveBinding()); + name= bh.findName("c5", 2); + dtor= (IASTImplicitNameOwner) name.getParent(); + assertSame(ctor2, dtor.getImplicitNames()[0].resolveBinding()); + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 685acf9098d..f3d1b638cda 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -196,6 +196,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalNamespaceScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownClassType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType; import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.Context; @@ -2399,7 +2400,14 @@ public class CPPSemantics { ((FunctionSetType) iType).applySelectedFunction(bestFnCost.getCost(i).getSelectedFunction()); } } - return bestFnCost.getFunction(); + IFunction result= bestFnCost.getFunction(); + if (bestFnCost.isDirectInitWithCopyCtor()) { + Cost c0= bestFnCost.getCost(0); + IFunction firstConversion= c0.getUserDefinedConversion(); + if (firstConversion instanceof ICPPConstructor) + return firstConversion; + } + return result; } private static void setTargetedFunctionsToUnknown(IType[] argTypes) { @@ -2450,8 +2458,8 @@ public class CPPSemantics { if (iast != i) { fns[i]= fns[iast]; fns[iast]= fn; - iast++; } + iast++; } } } @@ -2545,9 +2553,10 @@ public class CPPSemantics { Context ctx= Context.ORDINARY; if (j==0 && sourceLen == 1 && fn instanceof ICPPConstructor) { - if (paramType instanceof ICPPReferenceType && !((ICPPReferenceType) paramType).isRValueReference()) { + if (paramType instanceof ICPPReferenceType) { if (((ICPPConstructor) fn).getClassOwner().isSameType(getNestedType(paramType, TDEF|REF|CVTYPE))) { ctx= Context.FIRST_PARAM_OF_DIRECT_COPY_CTOR; + result.setIsDirectInitWithCopyCtor(true); } } } @@ -2940,7 +2949,8 @@ public class CPPSemantics { IASTDeclarator dtor= ASTQueries.findOutermostDeclarator(declarator); IASTNode parent = dtor.getParent(); if (parent instanceof IASTSimpleDeclaration) { - if (dtor.getInitializer() == null) { + final IASTInitializer initializer = dtor.getInitializer(); + if (initializer == null) { IASTDeclSpecifier declSpec = ((IASTSimpleDeclaration) parent).getDeclSpecifier(); parent = parent.getParent(); if (parent instanceof IASTCompositeTypeSpecifier || @@ -2950,7 +2960,7 @@ public class CPPSemantics { return null; } } - return findImplicitlyCalledConstructor(declarator.getName(), dtor.getInitializer()); + return findImplicitlyCalledConstructor(declarator.getName(), initializer); } return null; } @@ -2976,10 +2986,12 @@ public class CPPSemantics { type = SemanticUtil.getNestedType(((ICPPVariable) binding).getType(), TDEF | CVTYPE); if (!(type instanceof ICPPClassType)) return null; + if (type instanceof ICPPClassTemplate || type instanceof ICPPUnknownClassType || type instanceof IProblemBinding) + return null; + final ICPPClassType classType = (ICPPClassType) type; - - // Copy initialization if (initializer instanceof IASTEqualsInitializer) { + // Copy initialization IASTEqualsInitializer eqInit= (IASTEqualsInitializer) initializer; IASTInitializerClause initClause = eqInit.getInitializerClause(); IType sourceType= null; @@ -2994,35 +3006,47 @@ public class CPPSemantics { if (sourceType != null) { Cost c= Conversions.checkImplicitConversionSequence(type, sourceType, isLValue, UDCMode.ALLOWED, Context.ORDINARY); if (c.converts()) { - IFunction f= c.getUserDefinedConversion(); - if (f instanceof ICPPConstructor) - return (ICPPConstructor) f; + ICPPFunction f = c.getUserDefinedConversion(); + if (f instanceof ICPPConstructor) + return (ICPPConstructor) f; + // If a conversion is used, the constructor is elided. } - return null; } - } - - // Direct Initialization - CPPASTName astName = new CPPASTName(); - astName.setName(classType.getNameCharArray()); - astName.setOffsetAndLength((ASTNode) name); - CPPASTIdExpression idExp = new CPPASTIdExpression(astName); - idExp.setParent(name.getParent()); - idExp.setPropertyInParent(IASTFunctionCallExpression.FUNCTION_NAME); + } else if (initializer instanceof ICPPASTInitializerList) { + // List initialization + final InitializerListType listType = new InitializerListType((ICPPASTInitializerList) initializer); + Cost c= Conversions.listInitializationSequence(listType, type, UDCMode.ALLOWED, true); + if (c.converts()) { + ICPPFunction f = c.getUserDefinedConversion(); + if (f instanceof ICPPConstructor) + return (ICPPConstructor) f; + } + } else if (initializer instanceof ICPPASTConstructorInitializer) { + // Direct Initialization + final IASTInitializerClause[] arguments = ((ICPPASTConstructorInitializer) initializer).getArguments(); + CPPASTName astName = new CPPASTName(); + astName.setName(classType.getNameCharArray()); + astName.setOffsetAndLength((ASTNode) name); + CPPASTIdExpression idExp = new CPPASTIdExpression(astName); + idExp.setParent(name.getParent()); + idExp.setPropertyInParent(IASTFunctionCallExpression.FUNCTION_NAME); - LookupData data = new LookupData(astName); - if (initializer == null) { - data.setFunctionArguments(false); - } else if (initializer instanceof ICPPASTConstructorInitializer) { - data.setFunctionArguments(false, ((ICPPASTConstructorInitializer) initializer).getArguments()); - } else { + LookupData data = new LookupData(astName); + data.setFunctionArguments(false, arguments); + data.forceQualified = true; + data.foundItems = classType.getConstructors(); + binding = resolveAmbiguities(data, astName); + if (binding instanceof ICPPConstructor) + return (ICPPConstructor) binding; + } else if (initializer == null) { + // Default initialization + ICPPConstructor[] ctors = classType.getConstructors(); + for (ICPPConstructor ctor : ctors) { + if (ctor.getRequiredArgumentCount() == 0) + return ctor; + } return null; - } - data.forceQualified = true; - data.foundItems = classType.getConstructors(); - binding = resolveAmbiguities(data, astName); - if (binding instanceof ICPPConstructor) - return (ICPPConstructor) binding; + } } catch (DOMException e) { } return null; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java index 81040d55f15..224afe1c343 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java @@ -85,32 +85,42 @@ public class Conversions { public static Cost checkImplicitConversionSequence(IType target, IType exprType, ValueCategory valueCat, UDCMode udc, Context ctx) throws DOMException { final boolean isImpliedObject= ctx == Context.IMPLICIT_OBJECT; - if (isImpliedObject) { + if (isImpliedObject) udc= UDCMode.FORBIDDEN; - } target= getNestedType(target, TDEF); exprType= getNestedType(exprType, TDEF | REF); + final IType cv1T1= getNestedType(target, TDEF | REF); + final IType T1= getNestedType(cv1T1, TDEF | REF | ALLCVQ); + ReferenceBinding refBindingType= ReferenceBinding.OTHER; if (target instanceof ICPPReferenceType) { // [8.5.3-5] initialization of a reference final boolean isLValueRef= !((ICPPReferenceType) target).isRValueReference(); - final IType cv1T1= getNestedType(target, TDEF | REF); - final IType T1= getNestedType(cv1T1, TDEF | REF | ALLCVQ); final IType cv2T2= exprType; final IType T2= getNestedType(cv2T2, TDEF | REF | ALLCVQ); // mstodo: will change when implementing rvalue references on this pointer final boolean isImplicitWithoutRefQualifier = isImpliedObject; - ReferenceBinding refBindingType= ReferenceBinding.OTHER; if (!isImplicitWithoutRefQualifier) { if (isLValueRef) { refBindingType= ReferenceBinding.LVALUE_REF; - } else if (valueCat == LVALUE) { + } else { refBindingType= ReferenceBinding.RVALUE_REF_BINDS_RVALUE; } } + if (exprType instanceof InitializerListType) { + if (isLValueRef && getCVQualifier(cv1T1) != CVQualifier.c) + return Cost.NO_CONVERSION; + + Cost cost= listInitializationSequence(((InitializerListType) exprType), T1, udc, false); + if (cost.converts()) { + cost.setReferenceBinding(refBindingType); + } + return cost; + } + // If the reference is an lvalue reference and ... if (isLValueRef) { // ... the initializer expression is an lvalue (but is not a bit field) @@ -237,23 +247,11 @@ public class Conversions { } // Non-reference binding - IType uqsource= getNestedType(exprType, TDEF | REF | ALLCVQ); - IType uqtarget= getNestedType(target, TDEF | REF | ALLCVQ); - - // [13.3.3.1-6] Derived to base conversion - if (uqsource instanceof ICPPClassType && uqtarget instanceof ICPPClassType) { - int depth= SemanticUtil.calculateInheritanceDepth(uqsource, uqtarget); - if (depth > -1) { - if (depth == 0) { - return new Cost(uqsource, uqtarget, Rank.IDENTITY); - } - Cost cost= new Cost(uqsource, uqtarget, Rank.CONVERSION); - cost.setInheritanceDistance(depth); - return cost; - } + Cost cost= nonReferenceConversion(valueCat, exprType, T1, udc, isImpliedObject); + if (cost.converts()) { + cost.setReferenceBinding(refBindingType); } - - return nonReferenceConversion(valueCat, exprType, uqtarget, udc, isImpliedObject); + return cost; } /** @@ -314,7 +312,7 @@ public class Conversions { if (uqTarget instanceof ICPPClassType) { if (uqSource instanceof ICPPClassType) { // 13.3.3.1-6 Conceptual derived to base conversion - int depth= calculateInheritanceDepth(uqTarget, uqSource); + int depth= calculateInheritanceDepth(uqSource, uqTarget); if (depth >= 0) { if (depth == 0) { return new Cost(source, target, Rank.IDENTITY); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java index e1c735a4bf8..84c8c2ebc51 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java @@ -74,6 +74,10 @@ public class Cost { public void setCouldNarrow() { assert false; } + @Override + public void setSelectedFunction(ICPPFunction function) { + assert false; + } }; IType source; @@ -110,6 +114,11 @@ public class Cost { fRank= rank; } + + public ReferenceBinding getReferenceBinding() { + return fReferenceBinding; + } + public void setReferenceBinding(ReferenceBinding binding) { fReferenceBinding= binding; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java index 028a017deae..b4fe8e74b8a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java @@ -30,6 +30,7 @@ class FunctionCost { private final IFunction fFunction; private final Cost[] fCosts; private final ValueCategory[] fValueCategories; + private boolean fIsDirectCopyCtor; public FunctionCost(IFunction fn, int paramCount) { fFunction= fn; @@ -109,6 +110,7 @@ class FunctionCost { if (!udcCost.converts()) { return false; } + udcCost.setReferenceBinding(cost.getReferenceBinding()); } return true; } @@ -212,4 +214,12 @@ class FunctionCost { } return null; } + + public void setIsDirectInitWithCopyCtor(boolean val) { + fIsDirectCopyCtor= val; + } + + public boolean isDirectInitWithCopyCtor() { + return fIsDirectCopyCtor; + } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/BasicCppCallHierarchyTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/BasicCppCallHierarchyTest.java index b3bb78ea078..aaf92a35ce8 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/BasicCppCallHierarchyTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/BasicCppCallHierarchyTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2010 Wind River Systems, 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 @@ -293,7 +293,7 @@ public class BasicCppCallHierarchyTest extends CallHierarchyBaseTest { // void automatic() { // MyClass m; // } - public void _testAutomaticConstructor_156668() throws Exception { + public void testAutomaticConstructor_156668() throws Exception { String content = readTaggedComment("testAutomaticConstructor"); IFile file= createFile(getProject(), "testConstructor.cpp", content); waitForIndexer(fIndex, file, CallHierarchyBaseTest.INDEXER_WAIT_TIME); @@ -304,6 +304,15 @@ public class BasicCppCallHierarchyTest extends CallHierarchyBaseTest { Tree tree = getCHTreeViewer().getTree(); checkTreeNode(tree, 0, "MyClass::MyClass()"); checkTreeNode(tree, 0, 0, "automatic()"); + } + + public void _testAutomaticDestructor_156668() throws Exception { + String content = readTaggedComment("testAutomaticConstructor"); + IFile file= createFile(getProject(), "testConstructor.cpp", content); + waitForIndexer(fIndex, file, CallHierarchyBaseTest.INDEXER_WAIT_TIME); + CEditor editor = openEditor(file); + openCallHierarchy(editor); + Tree tree = getCHTreeViewer().getTree(); editor.selectAndReveal(content.indexOf("~MyClass"), 2); openCallHierarchy(editor); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java index e57f1af21bc..db6081306b5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java @@ -58,6 +58,7 @@ import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.PreferenceConstants; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator; /** @@ -1991,6 +1992,8 @@ public class SemanticHighlightings { && ((ICPPMethod) binding).isImplicit()) { return false; } + if (binding instanceof ICPPUnknownBinding) + return false; char[] chars = name.toCharArray(); if (chars[0] == '~' || OverloadableOperator.isNew(chars) || OverloadableOperator.isDelete(chars)) {