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