1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +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(); 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 ns1 {
// namespace ns2 { // namespace ns2 {
// class A {}; // class A {};
@ -758,6 +790,20 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
assertDeclared(); 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 bool bool
// #define false false // #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.IASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; 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.IASTPreprocessorFunctionStyleMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion; 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.CPPASTName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType; 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.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;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper.MethodKind; 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.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.Conversions;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.LookupData; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.LookupData;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; 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. // Get the binding of the initialized AST name first.
IASTNode memberNode = initializer; IASTNode variableNode = initializer;
IASTName memberName = null; IASTName variableName = null;
IBinding memberBinding = null; IBinding variableBinding = null;
while (memberNode != null) { while (variableNode != null) {
if (memberNode instanceof IASTDeclarator) { if (variableNode instanceof IASTDeclarator) {
memberName = ((IASTDeclarator) memberNode).getName(); variableName = ((IASTDeclarator) variableNode).getName();
break; break;
} else if (memberNode instanceof ICPPASTConstructorChainInitializer) { } else if (variableNode instanceof ICPPASTConstructorChainInitializer) {
memberName = ((ICPPASTConstructorChainInitializer) memberNode).getMemberInitializerId(); variableName = ((ICPPASTConstructorChainInitializer) variableNode).getMemberInitializerId();
break; break;
} }
memberNode = memberNode.getParent(); variableNode = variableNode.getParent();
} }
if (memberName != null) if (variableName != null)
memberBinding = memberName.resolveBinding(); variableBinding = variableName.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;
@ -379,13 +382,22 @@ public class BindingClassifier {
arguments = new IASTInitializerClause[] { equalsInitializer.getInitializerClause() }; arguments = new IASTInitializerClause[] { equalsInitializer.getInitializerClause() };
} }
if (memberBinding instanceof IVariable) { if (variableBinding instanceof IVariable) {
// Variable construction. // Variable construction.
IType memberType = ((IVariable) memberBinding).getType(); boolean defineVariableType = true;
if (!(memberType instanceof IPointerType || memberType instanceof ICPPReferenceType)) { if (initializer.getPropertyInParent() == IASTDeclarator.INITIALIZER) {
// We're constructing a non-pointer type. We need to define the member type IASTDeclarator declarator = (IASTDeclarator) initializer.getParent();
// either way since we must be able to call its constructor. IASTDeclSpecifier declSpec = getDeclarationSpecifier(declarator);
defineTypeExceptTypedefOrNonFixedEnum(memberType); 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? // TODO: Process the arguments. But how to get the corresponding IParameter[] array here?
// processParameters(declaredParameters, arguments); // processParameters(declaredParameters, arguments);
@ -394,24 +406,22 @@ public class BindingClassifier {
// to check whether the argument type matches the declared type. // to check whether the argument type matches the declared type.
for (IASTInitializerClause argument : arguments) { for (IASTInitializerClause argument : arguments) {
if (argument instanceof IASTExpression) { if (argument instanceof IASTExpression) {
IType argumentType = ((IASTExpression) argument).getExpressionType(); IASTExpression expression = (IASTExpression) argument;
if (isTypeDefinitionRequiredForConversion(argumentType, memberType)) { 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. // Types don't match. Define both types.
defineTypeExceptTypedefOrNonFixedEnum(memberType); if (defineVariableType)
defineTypeExceptTypedefOrNonFixedEnum(targetType);
defineTypeExceptTypedefOrNonFixedEnum(argumentType); 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; return PROCESS_CONTINUE;
} }
@ -568,20 +578,25 @@ public class BindingClassifier {
boolean expressionDefinitionRequired = true; boolean expressionDefinitionRequired = true;
switch (unaryExpression.getOperator()) { switch (unaryExpression.getOperator()) {
case IASTUnaryExpression.op_amper: case IASTUnaryExpression.op_amper:
case IASTUnaryExpression.op_bracketedPrimary: case IASTUnaryExpression.op_bracketedPrimary:
// The ampersand operator as well as brackets never require a definition. // The ampersand operator as well as brackets never require a definition.
expressionDefinitionRequired = false; expressionDefinitionRequired = false;
break;
case IASTUnaryExpression.op_star:
if (expression.getParent() instanceof IASTExpression)
break; break;
case IASTUnaryExpression.op_alignOf: //$FALL-THROUGH$
case IASTUnaryExpression.op_not: case IASTUnaryExpression.op_alignOf:
case IASTUnaryExpression.op_plus: case IASTUnaryExpression.op_not:
case IASTUnaryExpression.op_sizeof: case IASTUnaryExpression.op_plus:
case IASTUnaryExpression.op_typeid: case IASTUnaryExpression.op_sizeof:
// If the operand is a pointer type, then it doesn't need to be defined. case IASTUnaryExpression.op_typeid:
if (operand.getExpressionType() instanceof IPointerType) { // If the operand is a pointer type, then it doesn't need to be defined.
expressionDefinitionRequired = false; if (operand.getExpressionType() instanceof IPointerType) {
} expressionDefinitionRequired = false;
}
break;
} }
if (expressionDefinitionRequired) { if (expressionDefinitionRequired) {
@ -1568,4 +1583,24 @@ public class BindingClassifier {
node.accept(localNameFinder); node.accept(localNameFinder);
return localNameFinder.found; 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;
}
} }