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:
parent
2f38016b98
commit
02001dbe71
2 changed files with 89 additions and 17 deletions
|
@ -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 {};
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue