1
0
Fork 0
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:
Sergey Prigogin 2016-02-25 19:54:01 -08:00
parent 34eac4ab17
commit 7c321bae13
2 changed files with 87 additions and 49 deletions

View file

@ -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

View file

@ -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);
} }