diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/includes/BindingClassifierTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/includes/BindingClassifierTest.java index 8ec8696f633..6c61420b4e0 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/includes/BindingClassifierTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/includes/BindingClassifierTest.java @@ -208,13 +208,31 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase { // void test() { // f(""); // } - public void testFunctionCallWithTypeConversion() throws Exception { + public void testFunctionCallWithTypeConversion_1() throws Exception { IPreferenceStore preferenceStore = getPreferenceStore(); preferenceStore.setValue(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS, true); + // A header declaring the function is responsible for defining the parameter type that + // provides constructor that can be used for implicit conversion. assertDefined(); assertDeclared("f"); } + // struct A {}; + // struct B { operator A(); }; + // void f(A p); + + // void test(B b) { + // f(b); + // } + public void testFunctionCallWithTypeConversion_2() throws Exception { + IPreferenceStore preferenceStore = getPreferenceStore(); + preferenceStore.setValue(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS, true); + // A header declaring the function is not responsible for defining the parameter type since + // the implicit conversion from B to A is provided externally to parameter type. + assertDefined("A", "B"); + assertDeclared("f"); + } + // struct A {}; // struct B {}; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/BindingClassifier.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/BindingClassifier.java index b4de744bad9..11c1f1f75fc 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/BindingClassifier.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/BindingClassifier.java @@ -162,18 +162,22 @@ public class BindingClassifier { IParameter[] parameters = function.getParameters(); for (int i = 0; i < parameters.length; i++) { IType parameterType = parameters[i].getType(); - IType argumentType = null; + parameterType = getNestedType(parameterType, REF | ALLCVQ); + IASTInitializerClause argument = null; boolean canBeDeclared = false; - if (parameterType instanceof IPointerType || parameterType instanceof ICPPReferenceType) { - // The declared parameter type is a pointer or reference type. A declaration is - // sufficient if it matches the actual parameter type. - parameterType = getNestedType(parameterType, REF | ALLCVQ); - if (i < arguments.length) { - // This argument is present within the function call expression. - // It's therefore not a default parameter. - IASTInitializerClause argument = arguments[i]; + if (i >= arguments.length) { + // This is a default value parameter. The function call itself doesn't need + // a definition of this parameter type. + canBeDeclared = true; + } else { + // This argument is present within the function call expression. + // It's therefore not a default parameter. + argument = arguments[i]; + if (parameterType instanceof IPointerType || parameterType instanceof ICPPReferenceType) { + // The declared parameter type is a pointer or reference type. A declaration is + // sufficient if it matches the actual parameter type. if (argument instanceof IASTExpression) { - argumentType = ((IASTExpression) argument).getExpressionType(); + IType argumentType = ((IASTExpression) argument).getExpressionType(); argumentType = getNestedType(argumentType, REF | ALLCVQ); if (parameterType instanceof IPointerType && argumentType instanceof IPointerType) { @@ -184,10 +188,6 @@ public class BindingClassifier { canBeDeclared = true; } } - } else { - // This is a default value parameter. The function call itself doesn't need - // a definition of this parameter type. - canBeDeclared = true; } } @@ -196,23 +196,17 @@ public class BindingClassifier { // because this type doesn't appear within the AST. declareType(parameterType); } else { - parameterType = getNestedType(parameterType, REF | ALLCVQ); - if (i < arguments.length) { - // This argument is present within the function call expression. - // It's therefore not a default parameter. - IASTInitializerClause argument = arguments[i]; - if (argument instanceof IASTExpression) { - argumentType = ((IASTExpression) argument).getExpressionType(); - // The type of the argument requires a full definition. - defineTypeExceptTypedefOrNonFixedEnum(argumentType); - } + assert argument != null; + if (argument instanceof IASTExpression) { + IType argumentType = ((IASTExpression) argument).getExpressionType(); + // The type of the argument requires a full definition. + defineTypeExceptTypedefOrNonFixedEnum(argumentType); } // As a matter of policy, a header declaring the function is responsible for // defining parameter types that allow implicit conversion. - if (i >= arguments.length || - !(parameterType instanceof ICPPClassType) || + if (!(parameterType instanceof ICPPClassType) || fAst.getDeclarationsInAST(function).length != 0 || - !hasConvertingConstructor((ICPPClassType) parameterType, arguments[i])) { + !hasConvertingConstructor((ICPPClassType) parameterType, argument)) { defineTypeExceptTypedefOrNonFixedEnum(parameterType); } } @@ -236,7 +230,7 @@ public class BindingClassifier { lookupData.qualified = true; try { IBinding constructor = CPPSemantics.resolveFunction(lookupData, ClassTypeHelper.getConstructors(classType, argument), false); - if (constructor instanceof ICPPConstructor) + if (constructor instanceof ICPPConstructor && !((ICPPConstructor) constructor).isExplicit()) return true; } catch (DOMException e) { }