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:
parent
da8e356c89
commit
6fb068d42e
2 changed files with 123 additions and 42 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue