mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-31 21:05:37 +02:00
Bug 437630 - NPE in Organize Includes with a lambda expression
This commit is contained in:
parent
2163d2af4c
commit
852659fa1d
2 changed files with 20 additions and 7 deletions
|
@ -579,6 +579,14 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
|
||||||
assertDeclared();
|
assertDeclared();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// struct A {};
|
||||||
|
|
||||||
|
// auto lambda = [](A* a) { return *a; };
|
||||||
|
public void testLambdaExpression() throws Exception {
|
||||||
|
assertDefined("A");
|
||||||
|
assertDeclared();
|
||||||
|
}
|
||||||
|
|
||||||
// struct A {};
|
// struct A {};
|
||||||
// struct B {};
|
// struct B {};
|
||||||
// struct C {};
|
// struct C {};
|
||||||
|
|
|
@ -87,6 +87,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBas
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNameSpecifier;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNameSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
|
||||||
|
@ -116,6 +117,7 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
|
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.CPPFunction;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction;
|
||||||
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;
|
||||||
|
@ -216,7 +218,7 @@ public class BindingClassifier {
|
||||||
if (declarator instanceof IASTFunctionDeclarator) {
|
if (declarator instanceof IASTFunctionDeclarator) {
|
||||||
/*
|
/*
|
||||||
* The type specifier of a function definition doesn't need to be defined if it is
|
* The type specifier of a function definition doesn't need to be defined if it is
|
||||||
* a pointer or reference type.
|
* a pointer or a reference type.
|
||||||
*
|
*
|
||||||
* Example 1:
|
* Example 1:
|
||||||
* X *foo() { } // definition of X is not required here
|
* X *foo() { } // definition of X is not required here
|
||||||
|
@ -224,12 +226,16 @@ public class BindingClassifier {
|
||||||
* Example 2:
|
* Example 2:
|
||||||
* X& foo() { } // definition of X is not required here
|
* X& foo() { } // definition of X is not required here
|
||||||
*/
|
*/
|
||||||
IBinding binding = declarator.getName().resolveBinding();
|
IASTName name = declarator.getPropertyInParent() == ICPPASTLambdaExpression.DECLARATOR ?
|
||||||
|
((ICPPASTLambdaExpression) declarator.getParent()).getFunctionCallOperatorName() :
|
||||||
|
declarator.getName();
|
||||||
|
IBinding binding = name.resolveBinding();
|
||||||
if (binding instanceof IFunction) {
|
if (binding instanceof IFunction) {
|
||||||
IFunction function = (IFunction) binding;
|
IFunction function = (IFunction) binding;
|
||||||
|
|
||||||
IFunctionType functionType = function.getType();
|
IFunctionType functionType = function.getType();
|
||||||
if (declarator.getPropertyInParent() == IASTFunctionDefinition.DECLARATOR) {
|
if (declarator.getPropertyInParent() == IASTFunctionDefinition.DECLARATOR ||
|
||||||
|
declarator.getPropertyInParent() == ICPPASTLambdaExpression.DECLARATOR) {
|
||||||
// Define the return type if necessary.
|
// Define the return type if necessary.
|
||||||
IType returnType = functionType.getReturnType();
|
IType returnType = functionType.getReturnType();
|
||||||
if (!(returnType instanceof IPointerType || returnType instanceof ICPPReferenceType)) {
|
if (!(returnType instanceof IPointerType || returnType instanceof ICPPReferenceType)) {
|
||||||
|
@ -248,8 +254,8 @@ public class BindingClassifier {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// As a matter of policy, a function declaration is responsible for
|
// As a matter of policy, a function declaration is responsible for
|
||||||
// providing definitions of parameter types that have implicit converting
|
// providing definitions of parameter types that have implicit
|
||||||
// constructors.
|
// converting constructors.
|
||||||
IType[] parameterTypes = functionType.getParameterTypes();
|
IType[] parameterTypes = functionType.getParameterTypes();
|
||||||
for (IType type : parameterTypes) {
|
for (IType type : parameterTypes) {
|
||||||
if (!(type instanceof IPointerType)) {
|
if (!(type instanceof IPointerType)) {
|
||||||
|
@ -260,7 +266,6 @@ public class BindingClassifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return PROCESS_CONTINUE;
|
return PROCESS_CONTINUE;
|
||||||
}
|
}
|
||||||
|
@ -1209,7 +1214,7 @@ public class BindingClassifier {
|
||||||
private void defineBinding(IBinding binding) {
|
private void defineBinding(IBinding binding) {
|
||||||
if (!markAsDefined(binding))
|
if (!markAsDefined(binding))
|
||||||
return;
|
return;
|
||||||
if (fAst.getDefinitionsInAST(binding).length != 0)
|
if (binding instanceof CPPClosureType || fAst.getDefinitionsInAST(binding).length != 0)
|
||||||
return; // Defined locally.
|
return; // Defined locally.
|
||||||
|
|
||||||
Collection<IBinding> requiredBindings = getRequiredBindings(binding);
|
Collection<IBinding> requiredBindings = getRequiredBindings(binding);
|
||||||
|
|
Loading…
Add table
Reference in a new issue