mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-25 18:05:33 +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();
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// template<typename T>
|
||||
// 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<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 B {};
|
||||
// struct C {};
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue