1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-01 13:25:45 +02:00

Bug 422695. More test cases and fixes.

This commit is contained in:
Sergey Prigogin 2013-11-27 14:27:00 -08:00
parent 2f38016b98
commit 02001dbe71
2 changed files with 89 additions and 17 deletions

View file

@ -501,6 +501,29 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
assertDeclared(); assertDeclared();
} }
// namespace std {
// template<typename T>
// struct unique_ptr {
// T* operator->();
// };
// }
// struct A {
// void m();
// };
// class B : public A {
// };
// struct C {
// std::unique_ptr<B> x;
// };
// void test(C* c) {
// c->x->m();
// }
public void testTemplatesAllowingIncompleteParameterType_3() throws Exception {
assertDefined("B", "C");
assertDeclared();
}
// namespace std { // namespace std {
// template<typename T> // template<typename T>
// struct shared_ptr { // struct shared_ptr {
@ -517,11 +540,34 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
// void test() { // void test() {
// f()->m(); // f()->m();
// } // }
public void testTemplatesAllowingIncompleteParameterType_3() throws Exception { public void testTemplatesAllowingIncompleteParameterType_4() throws Exception {
assertDefined("B", "f"); assertDefined("B", "f");
assertDeclared(); assertDeclared();
} }
// namespace std {
// template<typename T>
// struct unique_ptr {
// T* operator->();
// };
// }
// struct A {
// void m();
// };
// class B : public A {
// };
// struct C {
// std::unique_ptr<B> f();
// };
// void test(C* c) {
// c->f()->m();
// }
public void testTemplatesAllowingIncompleteParameterType_5() throws Exception {
assertDefined("B", "C");
assertDeclared();
}
// struct A {}; // struct A {};
// struct B {}; // struct B {};
// struct C {}; // struct C {};

View file

@ -229,7 +229,7 @@ public class BindingClassifier {
* @return {@code true} if the types have to be defined * @return {@code true} if the types have to be defined
*/ */
private boolean isTypeDefinitionRequiredForConversion(IType sourceType, IType targetType) { private boolean isTypeDefinitionRequiredForConversion(IType sourceType, IType targetType) {
if (!(targetType instanceof IPointerType) && !(targetType instanceof ICPPReferenceType)) if (!(targetType instanceof IPointerType || targetType instanceof ICPPReferenceType))
return true; return true;
if (targetType instanceof IPointerType && Conversions.isNullPointerConstant(sourceType)) if (targetType instanceof IPointerType && Conversions.isNullPointerConstant(sourceType))
return false; return false;
@ -556,14 +556,14 @@ public class BindingClassifier {
// Handle return or expression type of the function or constructor call. // Handle return or expression type of the function or constructor call.
IType returnType = function.getType().getReturnType(); IType returnType = function.getType().getReturnType();
defineTypeOfBinding(function, returnType); defineTypeForBinding(function, returnType);
// Handle parameters. // Handle parameters.
processFunctionParameters(function, arguments); processFunctionParameters(function, arguments);
} }
private void defineTypeOfBinding(IBinding binding, IType type) { private void defineTypeForBinding(IBinding binding, IType type) {
if (fBindingsToDefine.contains(binding) && !mayBeForwardDeclared(type)) { if (isDefined(binding) && !mayBeForwardDeclared(type)) {
if (type instanceof ICPPTemplateInstance) { if (type instanceof ICPPTemplateInstance) {
ICPPTemplateInstance instance = (ICPPTemplateInstance) type; ICPPTemplateInstance instance = (ICPPTemplateInstance) type;
IBinding template = instance.getSpecializedBinding(); 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); 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 { private class BindingCollector extends ASTVisitor {
BindingCollector() { BindingCollector() {
super(true); super(true);
@ -665,7 +674,7 @@ public class BindingClassifier {
if (declarator.getPropertyInParent() == IASTFunctionDefinition.DECLARATOR) { if (declarator.getPropertyInParent() == IASTFunctionDefinition.DECLARATOR) {
// Define the return type if necessary. // Define the return type if necessary.
IType returnType = functionType.getReturnType(); IType returnType = functionType.getReturnType();
if (!(returnType instanceof IPointerType) && !(returnType instanceof ICPPReferenceType)) { if (!(returnType instanceof IPointerType || returnType instanceof ICPPReferenceType)) {
defineTypeExceptTypedefOrNonFixedEnum(returnType); defineTypeExceptTypedefOrNonFixedEnum(returnType);
} }
@ -795,7 +804,7 @@ public class BindingClassifier {
if (memberBinding instanceof IVariable) { if (memberBinding instanceof IVariable) {
// Variable construction. // Variable construction.
IType memberType = ((IVariable) memberBinding).getType(); 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 // 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. // either way since we must be able to call its constructor.
defineTypeExceptTypedefOrNonFixedEnum(memberType); defineTypeExceptTypedefOrNonFixedEnum(memberType);
@ -938,7 +947,7 @@ public class BindingClassifier {
if (binding instanceof IVariable) { if (binding instanceof IVariable) {
// Get the declared type. // Get the declared type.
IType variableType = ((IVariable) binding).getType(); IType variableType = ((IVariable) binding).getType();
defineTypeOfBinding(binding, variableType); defineTypeForBinding(binding, variableType);
} }
} else if (expression instanceof IASTUnaryExpression) { } else if (expression instanceof IASTUnaryExpression) {
/* /*
@ -1103,8 +1112,8 @@ public class BindingClassifier {
IASTFunctionCallExpression functionCallExpression = (IASTFunctionCallExpression) expression; IASTFunctionCallExpression functionCallExpression = (IASTFunctionCallExpression) expression;
IASTExpression functionNameExpression = functionCallExpression.getFunctionNameExpression(); IASTExpression functionNameExpression = functionCallExpression.getFunctionNameExpression();
if (functionNameExpression instanceof IASTIdExpression) { IBinding binding = getBindingOfExpression(functionNameExpression);
IBinding binding = ((IASTIdExpression) functionNameExpression).getName().resolveBinding(); if (binding != null) {
if (binding instanceof IFunction) { if (binding instanceof IFunction) {
declareFunction((IFunction) binding, functionCallExpression.getArguments()); declareFunction((IFunction) binding, functionCallExpression.getArguments());
} else { } else {
@ -1135,12 +1144,17 @@ public class BindingClassifier {
IASTExpression fieldOwner = ((IASTFieldReference) expression).getFieldOwner(); IASTExpression fieldOwner = ((IASTFieldReference) expression).getFieldOwner();
IType expressionType = fieldOwner.getExpressionType(); IType expressionType = fieldOwner.getExpressionType();
if (!(fieldOwner instanceof IASTIdExpression || fieldOwner instanceof IASTFunctionCallExpression) || if (expressionType instanceof IPointerType || expressionType instanceof ICPPReferenceType) {
expressionType instanceof IPointerType || expressionType instanceof ICPPReferenceType) {
// Id expressions and function call expressions returning non pointer and
// non reference types are processed separately.
defineTypeExceptTypedefOrNonFixedEnum(expressionType); 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) { } else if (expression instanceof ICPPASTNewExpression) {
/* /*
* The type specifier of a "new" expression always requires a definition. * 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. // We need to define both types, even if they're pointers.
defineTypeExceptTypedefOrNonFixedEnum(targetType); defineTypeExceptTypedefOrNonFixedEnum(targetType);
defineTypeExceptTypedefOrNonFixedEnum(sourceType); 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. // Define the target type if it's not a pointer or reference type.
defineTypeExceptTypedefOrNonFixedEnum(targetType); 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. * 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 * As an example if the given type is a pointer type, this function returns the binding for