From 02001dbe71c6d848ab7ac0752c319c40454bc493 Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Wed, 27 Nov 2013 14:27:00 -0800 Subject: [PATCH] Bug 422695. More test cases and fixes. --- .../includes/BindingClassifierTest.java | 48 ++++++++++++++- .../includes/BindingClassifier.java | 58 ++++++++++++++----- 2 files changed, 89 insertions(+), 17 deletions(-) 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 7cb72e241bf..2396e128d2a 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 @@ -501,6 +501,29 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase { assertDeclared(); } + // namespace std { + // template + // struct unique_ptr { + // T* operator->(); + // }; + // } + // struct A { + // void m(); + // }; + // class B : public A { + // }; + // struct C { + // std::unique_ptr x; + // }; + + // void test(C* c) { + // c->x->m(); + // } + public void testTemplatesAllowingIncompleteParameterType_3() throws Exception { + assertDefined("B", "C"); + assertDeclared(); + } + // namespace std { // template // struct shared_ptr { @@ -517,11 +540,34 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase { // void test() { // f()->m(); // } - public void testTemplatesAllowingIncompleteParameterType_3() throws Exception { + public void testTemplatesAllowingIncompleteParameterType_4() throws Exception { assertDefined("B", "f"); assertDeclared(); } + // namespace std { + // template + // struct unique_ptr { + // T* operator->(); + // }; + // } + // struct A { + // void m(); + // }; + // class B : public A { + // }; + // struct C { + // std::unique_ptr f(); + // }; + + // void test(C* c) { + // c->f()->m(); + // } + public void testTemplatesAllowingIncompleteParameterType_5() throws Exception { + assertDefined("B", "C"); + assertDeclared(); + } + // struct A {}; // struct B {}; // struct C {}; 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 9fef7370c4a..a9793736570 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 @@ -229,7 +229,7 @@ public class BindingClassifier { * @return {@code true} if the types have to be defined */ private boolean isTypeDefinitionRequiredForConversion(IType sourceType, IType targetType) { - if (!(targetType instanceof IPointerType) && !(targetType instanceof ICPPReferenceType)) + if (!(targetType instanceof IPointerType || targetType instanceof ICPPReferenceType)) return true; if (targetType instanceof IPointerType && Conversions.isNullPointerConstant(sourceType)) return false; @@ -556,14 +556,14 @@ public class BindingClassifier { // Handle return or expression type of the function or constructor call. IType returnType = function.getType().getReturnType(); - defineTypeOfBinding(function, returnType); + defineTypeForBinding(function, returnType); // Handle parameters. processFunctionParameters(function, arguments); } - private void defineTypeOfBinding(IBinding binding, IType type) { - if (fBindingsToDefine.contains(binding) && !mayBeForwardDeclared(type)) { + private void defineTypeForBinding(IBinding binding, IType type) { + if (isDefined(binding) && !mayBeForwardDeclared(type)) { if (type instanceof ICPPTemplateInstance) { ICPPTemplateInstance instance = (ICPPTemplateInstance) type; IBinding template = instance.getSpecializedBinding(); @@ -575,11 +575,20 @@ public class BindingClassifier { } } } - } else if (!(type instanceof IPointerType) && !(type instanceof ICPPReferenceType)) { + } else if (!(type instanceof IPointerType || type instanceof ICPPReferenceType)) { defineTypeExceptTypedefOrNonFixedEnum(type); } } + private boolean isDefined(IBinding binding) { + if (fBindingsToDefine.contains(binding)) + return true; + IBinding owner = binding.getOwner(); + if (owner instanceof IType && fBindingsToDefine.contains(owner)) + return true; + return false; + } + private class BindingCollector extends ASTVisitor { BindingCollector() { super(true); @@ -665,7 +674,7 @@ public class BindingClassifier { if (declarator.getPropertyInParent() == IASTFunctionDefinition.DECLARATOR) { // Define the return type if necessary. IType returnType = functionType.getReturnType(); - if (!(returnType instanceof IPointerType) && !(returnType instanceof ICPPReferenceType)) { + if (!(returnType instanceof IPointerType || returnType instanceof ICPPReferenceType)) { defineTypeExceptTypedefOrNonFixedEnum(returnType); } @@ -795,7 +804,7 @@ public class BindingClassifier { if (memberBinding instanceof IVariable) { // Variable construction. IType memberType = ((IVariable) memberBinding).getType(); - if (!(memberType instanceof IPointerType) && !(memberType instanceof ICPPReferenceType)) { + if (!(memberType instanceof IPointerType || memberType instanceof ICPPReferenceType)) { // We're constructing a non-pointer type. We need to define the member type // either way since we must be able to call its constructor. defineTypeExceptTypedefOrNonFixedEnum(memberType); @@ -938,7 +947,7 @@ public class BindingClassifier { if (binding instanceof IVariable) { // Get the declared type. IType variableType = ((IVariable) binding).getType(); - defineTypeOfBinding(binding, variableType); + defineTypeForBinding(binding, variableType); } } else if (expression instanceof IASTUnaryExpression) { /* @@ -1103,8 +1112,8 @@ public class BindingClassifier { IASTFunctionCallExpression functionCallExpression = (IASTFunctionCallExpression) expression; IASTExpression functionNameExpression = functionCallExpression.getFunctionNameExpression(); - if (functionNameExpression instanceof IASTIdExpression) { - IBinding binding = ((IASTIdExpression) functionNameExpression).getName().resolveBinding(); + IBinding binding = getBindingOfExpression(functionNameExpression); + if (binding != null) { if (binding instanceof IFunction) { declareFunction((IFunction) binding, functionCallExpression.getArguments()); } else { @@ -1121,7 +1130,7 @@ public class BindingClassifier { } } } - } + } } else if (expression instanceof IASTFieldReference) { /* * The type of the expression part of a field reference always requires a definition. @@ -1135,12 +1144,17 @@ public class BindingClassifier { IASTExpression fieldOwner = ((IASTFieldReference) expression).getFieldOwner(); IType expressionType = fieldOwner.getExpressionType(); - if (!(fieldOwner instanceof IASTIdExpression || fieldOwner instanceof IASTFunctionCallExpression) || - expressionType instanceof IPointerType || expressionType instanceof ICPPReferenceType) { - // Id expressions and function call expressions returning non pointer and - // non reference types are processed separately. + if (expressionType instanceof IPointerType || expressionType instanceof ICPPReferenceType) { defineTypeExceptTypedefOrNonFixedEnum(expressionType); + } else if (!(fieldOwner instanceof IASTIdExpression || fieldOwner instanceof IASTFunctionCallExpression)) { + IBinding binding = getBindingOfExpression(fieldOwner); + if (binding != null) { + defineTypeForBinding(binding, expressionType); + } else { + defineTypeExceptTypedefOrNonFixedEnum(expressionType); + } } + // Id expressions and function call expressions are handled elsewhere. } else if (expression instanceof ICPPASTNewExpression) { /* * The type specifier of a "new" expression always requires a definition. @@ -1180,7 +1194,7 @@ public class BindingClassifier { // We need to define both types, even if they're pointers. defineTypeExceptTypedefOrNonFixedEnum(targetType); defineTypeExceptTypedefOrNonFixedEnum(sourceType); - } else if (!(targetType instanceof IPointerType) && !(targetType instanceof ICPPReferenceType)) { + } else if (!(targetType instanceof IPointerType || targetType instanceof ICPPReferenceType)) { // Define the target type if it's not a pointer or reference type. defineTypeExceptTypedefOrNonFixedEnum(targetType); } @@ -1234,6 +1248,18 @@ public class BindingClassifier { } } + /** + * @return the binding corresponding to the ID or the field reference expression. + */ + private IBinding getBindingOfExpression(IASTExpression expression) { + if (expression instanceof IASTIdExpression) { + return ((IASTIdExpression) expression).getName().resolveBinding(); + } else if (expression instanceof IASTFieldReference) { + return ((IASTFieldReference) expression).getFieldName().resolveBinding(); + } + return null; + } + /** * Resolves the given type to a binding which we actually have to either declare or define. * As an example if the given type is a pointer type, this function returns the binding for