1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Bug 488604 - Organize Includes adds include for type hidden behind a

macro

Change-Id: Ibfe1499580b3b34ff9c3cff0fbbd8b3b3b9506fa
This commit is contained in:
Sergey Prigogin 2016-02-26 16:32:21 -08:00
parent da8e356c89
commit 6fb068d42e
2 changed files with 123 additions and 42 deletions

View file

@ -387,6 +387,38 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
assertDeclared();
}
// class A {};
// class B {};
// class C {};
// class D {};
// void foo(A* a, B& b, C& c) {
// A& aa(*a);
// B* bb(&b);
// C cc(c);
// D d;
// }
public void testVariableDeclaration() throws Exception {
assertDefined("C", "D");
assertDeclared("A", "B");
}
// class A {};
// class B {};
// class C {};
// class D {
// A* aa;
// B& bb;
// C cc;
// D(A* a, B& b, C& c)
// : aa(a), bb(b), cc(c) {}
// };
public void testConstructorChainInitializer() throws Exception {
assertDefined("C");
assertDeclared("A", "B");
}
// namespace ns1 {
// namespace ns2 {
// class A {};
@ -758,6 +790,20 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
assertDeclared();
}
// struct A {
// A(int);
// };
//
// #define MACRO(a, b) A a(b)
// void test(int x) {
// MACRO(a, x);
// }
public void testMacro_6() throws Exception {
assertDefined("MACRO");
assertDeclared();
}
// #define bool bool
// #define false false

View file

@ -59,6 +59,7 @@ import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorFunctionStyleMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion;
@ -127,9 +128,11 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper.MethodKind;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.LookupData;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
@ -351,23 +354,23 @@ public class BindingClassifier {
*/
// Get the binding of the initialized AST name first.
IASTNode memberNode = initializer;
IASTName memberName = null;
IBinding memberBinding = null;
IASTNode variableNode = initializer;
IASTName variableName = null;
IBinding variableBinding = null;
while (memberNode != null) {
if (memberNode instanceof IASTDeclarator) {
memberName = ((IASTDeclarator) memberNode).getName();
while (variableNode != null) {
if (variableNode instanceof IASTDeclarator) {
variableName = ((IASTDeclarator) variableNode).getName();
break;
} else if (memberNode instanceof ICPPASTConstructorChainInitializer) {
memberName = ((ICPPASTConstructorChainInitializer) memberNode).getMemberInitializerId();
} else if (variableNode instanceof ICPPASTConstructorChainInitializer) {
variableName = ((ICPPASTConstructorChainInitializer) variableNode).getMemberInitializerId();
break;
}
memberNode = memberNode.getParent();
variableNode = variableNode.getParent();
}
if (memberName != null)
memberBinding = memberName.resolveBinding();
if (variableName != null)
variableBinding = variableName.resolveBinding();
// Get the arguments of the initializer.
IASTInitializerClause[] arguments = IASTExpression.EMPTY_EXPRESSION_ARRAY;
@ -379,13 +382,22 @@ public class BindingClassifier {
arguments = new IASTInitializerClause[] { equalsInitializer.getInitializerClause() };
}
if (memberBinding instanceof IVariable) {
if (variableBinding instanceof IVariable) {
// Variable construction.
IType memberType = ((IVariable) memberBinding).getType();
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);
boolean defineVariableType = true;
if (initializer.getPropertyInParent() == IASTDeclarator.INITIALIZER) {
IASTDeclarator declarator = (IASTDeclarator) initializer.getParent();
IASTDeclSpecifier declSpec = getDeclarationSpecifier(declarator);
if (declSpec != null && isPartOfExternalMacroDefinition(declSpec))
defineVariableType = false;
}
IType targetType = ((IVariable) variableBinding).getType();
if (!(targetType instanceof IPointerType || targetType instanceof ICPPReferenceType)) {
if (defineVariableType) {
// 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(targetType);
}
// TODO: Process the arguments. But how to get the corresponding IParameter[] array here?
// processParameters(declaredParameters, arguments);
@ -394,24 +406,22 @@ public class BindingClassifier {
// to check whether the argument type matches the declared type.
for (IASTInitializerClause argument : arguments) {
if (argument instanceof IASTExpression) {
IType argumentType = ((IASTExpression) argument).getExpressionType();
if (isTypeDefinitionRequiredForConversion(argumentType, memberType)) {
IASTExpression expression = (IASTExpression) argument;
IType argumentType = expression.getExpressionType();
if (targetType instanceof ICPPReferenceType
&& expression instanceof IASTUnaryExpression
&& ((IASTUnaryExpression) expression).getOperator() == IASTUnaryExpression.op_star) {
argumentType = new CPPReferenceType(argumentType, false);
}
if (isTypeDefinitionRequiredForConversion(argumentType, targetType)) {
// Types don't match. Define both types.
defineTypeExceptTypedefOrNonFixedEnum(memberType);
if (defineVariableType)
defineTypeExceptTypedefOrNonFixedEnum(targetType);
defineTypeExceptTypedefOrNonFixedEnum(argumentType);
}
}
}
}
} else if (memberBinding instanceof ICPPConstructor) {
// Class construction.
ICPPConstructor constructor = (ICPPConstructor) memberBinding;
// We need to define the owning type of the constructor.
defineBinding(constructor.getOwner());
// Process the parameters.
processFunctionParameters(constructor, true, arguments);
}
return PROCESS_CONTINUE;
}
@ -568,20 +578,25 @@ public class BindingClassifier {
boolean expressionDefinitionRequired = true;
switch (unaryExpression.getOperator()) {
case IASTUnaryExpression.op_amper:
case IASTUnaryExpression.op_bracketedPrimary:
// The ampersand operator as well as brackets never require a definition.
expressionDefinitionRequired = false;
case IASTUnaryExpression.op_amper:
case IASTUnaryExpression.op_bracketedPrimary:
// The ampersand operator as well as brackets never require a definition.
expressionDefinitionRequired = false;
break;
case IASTUnaryExpression.op_star:
if (expression.getParent() instanceof IASTExpression)
break;
case IASTUnaryExpression.op_alignOf:
case IASTUnaryExpression.op_not:
case IASTUnaryExpression.op_plus:
case IASTUnaryExpression.op_sizeof:
case IASTUnaryExpression.op_typeid:
// If the operand is a pointer type, then it doesn't need to be defined.
if (operand.getExpressionType() instanceof IPointerType) {
expressionDefinitionRequired = false;
}
//$FALL-THROUGH$
case IASTUnaryExpression.op_alignOf:
case IASTUnaryExpression.op_not:
case IASTUnaryExpression.op_plus:
case IASTUnaryExpression.op_sizeof:
case IASTUnaryExpression.op_typeid:
// If the operand is a pointer type, then it doesn't need to be defined.
if (operand.getExpressionType() instanceof IPointerType) {
expressionDefinitionRequired = false;
}
break;
}
if (expressionDefinitionRequired) {
@ -1568,4 +1583,24 @@ public class BindingClassifier {
node.accept(localNameFinder);
return localNameFinder.found;
}
/**
* Returns the declaration specifier node for the given declarator.
*/
private static IASTDeclSpecifier getDeclarationSpecifier(IASTDeclarator declarator) {
declarator= CPPVisitor.findOutermostDeclarator(declarator);
IASTNode parent = declarator.getParent();
IASTDeclSpecifier declSpec = null;
if (parent instanceof IASTSimpleDeclaration) {
declSpec = ((IASTSimpleDeclaration) parent).getDeclSpecifier();
} else if (parent instanceof IASTParameterDeclaration) {
declSpec = ((IASTParameterDeclaration) parent).getDeclSpecifier();
} else if (parent instanceof IASTFunctionDefinition) {
declSpec = ((IASTFunctionDefinition) parent).getDeclSpecifier();
} else if (parent instanceof ICPPASTTypeId) {
declSpec = ((ICPPASTTypeId) parent).getDeclSpecifier();
}
return declSpec;
}
}