mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-01 06:05:24 +02:00
Bug 488506 - Organize Includes adds include for function hidden behind a
macro Change-Id: Ic737e34f71953f1e53a2c1cf2a21e340b7593c33
This commit is contained in:
parent
34eac4ab17
commit
7c321bae13
2 changed files with 87 additions and 49 deletions
|
@ -744,6 +744,20 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
|
||||||
assertDeclared();
|
assertDeclared();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// template <typename T>
|
||||||
|
// void m();
|
||||||
|
//
|
||||||
|
// #define MACRO(a) m<a>()
|
||||||
|
|
||||||
|
// typedef int INT;
|
||||||
|
// void test() {
|
||||||
|
// MACRO(INT);
|
||||||
|
// }
|
||||||
|
public void testMacro_5() throws Exception {
|
||||||
|
assertDefined("MACRO");
|
||||||
|
assertDeclared();
|
||||||
|
}
|
||||||
|
|
||||||
// #define bool bool
|
// #define bool bool
|
||||||
// #define false false
|
// #define false false
|
||||||
|
|
||||||
|
|
|
@ -365,9 +365,9 @@ public class BindingClassifier {
|
||||||
}
|
}
|
||||||
memberNode = memberNode.getParent();
|
memberNode = memberNode.getParent();
|
||||||
}
|
}
|
||||||
if (memberName != null) {
|
|
||||||
|
if (memberName != null)
|
||||||
memberBinding = memberName.resolveBinding();
|
memberBinding = memberName.resolveBinding();
|
||||||
}
|
|
||||||
|
|
||||||
// Get the arguments of the initializer.
|
// Get the arguments of the initializer.
|
||||||
IASTInitializerClause[] arguments = IASTExpression.EMPTY_EXPRESSION_ARRAY;
|
IASTInitializerClause[] arguments = IASTExpression.EMPTY_EXPRESSION_ARRAY;
|
||||||
|
@ -411,7 +411,7 @@ public class BindingClassifier {
|
||||||
defineBinding(constructor.getOwner());
|
defineBinding(constructor.getOwner());
|
||||||
|
|
||||||
// Process the parameters.
|
// Process the parameters.
|
||||||
processFunctionParameters(constructor, arguments);
|
processFunctionParameters(constructor, true, arguments);
|
||||||
}
|
}
|
||||||
return PROCESS_CONTINUE;
|
return PROCESS_CONTINUE;
|
||||||
}
|
}
|
||||||
|
@ -561,7 +561,7 @@ public class BindingClassifier {
|
||||||
if (unaryExpression instanceof ICPPASTUnaryExpression) {
|
if (unaryExpression instanceof ICPPASTUnaryExpression) {
|
||||||
ICPPFunction overload = ((ICPPASTUnaryExpression) unaryExpression).getOverload();
|
ICPPFunction overload = ((ICPPASTUnaryExpression) unaryExpression).getOverload();
|
||||||
if (overload != null) {
|
if (overload != null) {
|
||||||
defineForFunctionCall(overload, new IASTInitializerClause[] { operand });
|
defineForFunctionCall(overload, true, new IASTInitializerClause[] { operand });
|
||||||
return PROCESS_CONTINUE;
|
return PROCESS_CONTINUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -618,7 +618,9 @@ public class BindingClassifier {
|
||||||
if (binaryExpression instanceof ICPPASTBinaryExpression) {
|
if (binaryExpression instanceof ICPPASTBinaryExpression) {
|
||||||
ICPPFunction overload = ((ICPPASTBinaryExpression) binaryExpression).getOverload();
|
ICPPFunction overload = ((ICPPASTBinaryExpression) binaryExpression).getOverload();
|
||||||
if (overload != null) {
|
if (overload != null) {
|
||||||
defineForFunctionCall(overload, new IASTInitializerClause[] { binaryExpression.getOperand1(), binaryExpression.getOperand2() });
|
IASTInitializerClause[] arguments = new IASTInitializerClause[]
|
||||||
|
{ binaryExpression.getOperand1(), binaryExpression.getOperand2() };
|
||||||
|
defineForFunctionCall(overload, true, arguments);
|
||||||
return PROCESS_CONTINUE;
|
return PROCESS_CONTINUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -703,22 +705,31 @@ public class BindingClassifier {
|
||||||
IASTInitializerClause[] arguments = functionCallExpression.getArguments();
|
IASTInitializerClause[] arguments = functionCallExpression.getArguments();
|
||||||
IASTName functionName = getNameOfIdOrFieldReferenceExpression(functionNameExpression);
|
IASTName functionName = getNameOfIdOrFieldReferenceExpression(functionNameExpression);
|
||||||
if (functionName != null) {
|
if (functionName != null) {
|
||||||
IBinding binding = functionName.resolveBinding();
|
IBinding function = functionName.resolveBinding();
|
||||||
if (binding instanceof IProblemBinding) {
|
if (function instanceof IProblemBinding) {
|
||||||
IBinding[] candidates = ((IProblemBinding) binding).getCandidateBindings();
|
IBinding[] candidates = ((IProblemBinding) function).getCandidateBindings();
|
||||||
if (candidates.length != 0) {
|
if (candidates.length != 0) {
|
||||||
for (IBinding candidate : candidates) {
|
for (IBinding candidate : candidates) {
|
||||||
defineBindingForFunctionCall(candidate, arguments);
|
defineBindingForFunctionCall(candidate, true, arguments);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
defineBinding(binding);
|
defineBinding(function);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LookupData data = new LookupData(functionName);
|
IASTName name = functionName;
|
||||||
IType impliedObjectType = data.getImpliedObjectType();
|
if (functionName instanceof ICPPASTTemplateId) {
|
||||||
if (impliedObjectType != null)
|
name = ((ICPPASTTemplateId) functionName).getTemplateName();
|
||||||
defineTypeExceptTypedefOrNonFixedEnum(impliedObjectType);
|
}
|
||||||
defineBindingForFunctionCall(binding, arguments);
|
boolean defineFunction = !isPartOfExternalMacroDefinition(name);
|
||||||
|
|
||||||
|
if (defineFunction) {
|
||||||
|
LookupData data = new LookupData(functionName);
|
||||||
|
IType impliedObjectType = data.getImpliedObjectType();
|
||||||
|
if (impliedObjectType != null)
|
||||||
|
defineTypeExceptTypedefOrNonFixedEnum(impliedObjectType);
|
||||||
|
}
|
||||||
|
|
||||||
|
defineBindingForFunctionCall(function, defineFunction, arguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,7 +738,7 @@ public class BindingClassifier {
|
||||||
for (IASTName name : implicitNames) {
|
for (IASTName name : implicitNames) {
|
||||||
IBinding binding = name.resolveBinding();
|
IBinding binding = name.resolveBinding();
|
||||||
if (binding instanceof IFunction) {
|
if (binding instanceof IFunction) {
|
||||||
defineForFunctionCall((IFunction) binding, arguments);
|
defineForFunctionCall((IFunction) binding, true, arguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -797,22 +808,28 @@ public class BindingClassifier {
|
||||||
return PROCESS_CONTINUE;
|
return PROCESS_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void defineBindingForFunctionCall(IBinding binding, IASTInitializerClause[] arguments) {
|
protected void defineBindingForFunctionCall(IBinding binding, boolean defineFunction,
|
||||||
|
IASTInitializerClause[] arguments) {
|
||||||
if (binding instanceof IFunction) {
|
if (binding instanceof IFunction) {
|
||||||
defineForFunctionCall((IFunction) binding, arguments);
|
defineForFunctionCall((IFunction) binding, defineFunction, arguments);
|
||||||
} else if (binding instanceof ICPPMember) {
|
} else if (defineFunction) {
|
||||||
try {
|
if (binding instanceof ICPPMember) {
|
||||||
IType memberType = ((ICPPMember) binding).getType();
|
try {
|
||||||
defineIndirectTypes(memberType);
|
IType memberType = ((ICPPMember) binding).getType();
|
||||||
} catch (DOMException e) {
|
defineIndirectTypes(memberType);
|
||||||
|
} catch (DOMException e) {
|
||||||
|
}
|
||||||
|
} else if (binding instanceof ITypedef) {
|
||||||
|
defineBinding(binding);
|
||||||
}
|
}
|
||||||
} else if (binding instanceof ITypedef) {
|
|
||||||
defineBinding(binding);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int leave(IASTName name) {
|
public int leave(IASTName name) {
|
||||||
|
if (name instanceof ICPPASTQualifiedName || name instanceof ICPPASTTemplateId) {
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
if (isPartOfExternalMacroDefinition(name))
|
if (isPartOfExternalMacroDefinition(name))
|
||||||
return PROCESS_CONTINUE;
|
return PROCESS_CONTINUE;
|
||||||
|
|
||||||
|
@ -947,7 +964,8 @@ public class BindingClassifier {
|
||||||
* Defines the required types of the parameters of a function or constructor call expression by
|
* Defines the required types of the parameters of a function or constructor call expression by
|
||||||
* comparing the declared parameters with the actual arguments.
|
* comparing the declared parameters with the actual arguments.
|
||||||
*/
|
*/
|
||||||
private void processFunctionParameters(IFunction function, IASTInitializerClause[] arguments) {
|
private void processFunctionParameters(IFunction function, boolean defineFunction,
|
||||||
|
IASTInitializerClause[] arguments) {
|
||||||
boolean functionIsDeclared = fProcessedDefinedBindings.contains(function);
|
boolean functionIsDeclared = fProcessedDefinedBindings.contains(function);
|
||||||
IParameter[] parameters = function.getParameters();
|
IParameter[] parameters = function.getParameters();
|
||||||
for (int i = 0; i < parameters.length && i < arguments.length; i++) {
|
for (int i = 0; i < parameters.length && i < arguments.length; i++) {
|
||||||
|
@ -959,7 +977,7 @@ public class BindingClassifier {
|
||||||
// A declaration is sufficient if the argument type matches the parameter type.
|
// A declaration is sufficient if the argument type matches the parameter type.
|
||||||
// We don't need to provide a declaration of the parameter type since it is
|
// We don't need to provide a declaration of the parameter type since it is
|
||||||
// a responsibility of the header declaring the function.
|
// a responsibility of the header declaring the function.
|
||||||
if (!functionIsDeclared) {
|
if (!functionIsDeclared && defineFunction) {
|
||||||
declareType(parameterType);
|
declareType(parameterType);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -968,15 +986,17 @@ public class BindingClassifier {
|
||||||
// The type of the argument requires a full definition.
|
// The type of the argument requires a full definition.
|
||||||
defineTypeExceptTypedefOrNonFixedEnum(argumentType);
|
defineTypeExceptTypedefOrNonFixedEnum(argumentType);
|
||||||
}
|
}
|
||||||
// As a matter of policy, a header declaring the function is responsible for
|
if (defineFunction) {
|
||||||
// defining parameter types that allow implicit conversion.
|
// As a matter of policy, a header declaring the function is responsible for
|
||||||
parameterType = getNestedType(parameterType, REF | ALLCVQ);
|
// defining parameter types that allow implicit conversion.
|
||||||
if (!(parameterType instanceof ICPPClassType) ||
|
parameterType = getNestedType(parameterType, REF | ALLCVQ);
|
||||||
fAst.getDeclarationsInAST(function).length != 0 ||
|
if (!(parameterType instanceof ICPPClassType) ||
|
||||||
!hasConvertingConstructor((ICPPClassType) parameterType, argument)) {
|
fAst.getDeclarationsInAST(function).length != 0 ||
|
||||||
defineTypeExceptTypedefOrNonFixedEnum(parameterType);
|
!hasConvertingConstructor((ICPPClassType) parameterType, argument)) {
|
||||||
} else if (!functionIsDeclared) {
|
defineTypeExceptTypedefOrNonFixedEnum(parameterType);
|
||||||
declareType(parameterType);
|
} else if (!functionIsDeclared) {
|
||||||
|
declareType(parameterType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1337,23 +1357,27 @@ public class BindingClassifier {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void defineForFunctionCall(IFunction function, IASTInitializerClause[] arguments) {
|
private void defineForFunctionCall(IFunction function, boolean defineFunction,
|
||||||
if (!fProcessedDefinedBindings.contains(function)) {
|
IASTInitializerClause[] arguments) {
|
||||||
if (!(function instanceof ICPPMethod) && (!canForwardDeclare(function) || isDefinedInHeaderFile(function))) {
|
if (defineFunction) {
|
||||||
// Since the function is defined in a header file, its definition has to be
|
if (!fProcessedDefinedBindings.contains(function)) {
|
||||||
// reachable through includes to make a function call.
|
if (!(function instanceof ICPPMethod)
|
||||||
defineBinding(function);
|
&& (!canForwardDeclare(function) || isDefinedInHeaderFile(function))) {
|
||||||
} else {
|
// Since the function is defined in a header file, its definition has to be
|
||||||
declareBinding(function);
|
// reachable through includes to make a function call.
|
||||||
|
defineBinding(function);
|
||||||
|
} else {
|
||||||
|
declareBinding(function);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle return or expression type of the function or constructor call.
|
||||||
|
IType returnType = function.getType().getReturnType();
|
||||||
|
defineTypeForBinding(function, returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle return or expression type of the function or constructor call.
|
|
||||||
IType returnType = function.getType().getReturnType();
|
|
||||||
defineTypeForBinding(function, returnType);
|
|
||||||
|
|
||||||
// Handle parameters.
|
// Handle parameters.
|
||||||
processFunctionParameters(function, arguments);
|
processFunctionParameters(function, defineFunction, arguments);
|
||||||
|
|
||||||
fProcessedDefinedBindings.add(function);
|
fProcessedDefinedBindings.add(function);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue