mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-20 15:35:24 +02:00
Bug 516627 - Add support for generic lambdas
Change-Id: I2e8d16cfe2dc58b77e36fa7a6957506c90b7e75a
This commit is contained in:
parent
f579acd381
commit
3147cc4732
10 changed files with 586 additions and 16 deletions
|
@ -13,6 +13,7 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.parser.tests.ast2;
|
package org.eclipse.cdt.core.parser.tests.ast2;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.parser.tests.ast2.cxx14.GenericLambdaTests;
|
||||||
import org.eclipse.cdt.core.parser.tests.ast2.cxx14.ReturnTypeDeductionTests;
|
import org.eclipse.cdt.core.parser.tests.ast2.cxx14.ReturnTypeDeductionTests;
|
||||||
import org.eclipse.cdt.core.parser.tests.ast2.cxx14.VariableTemplateTests;
|
import org.eclipse.cdt.core.parser.tests.ast2.cxx14.VariableTemplateTests;
|
||||||
import org.eclipse.cdt.core.parser.tests.prefix.CompletionTestSuite;
|
import org.eclipse.cdt.core.parser.tests.prefix.CompletionTestSuite;
|
||||||
|
@ -59,8 +60,10 @@ public class DOMParserTestSuite extends TestCase {
|
||||||
suite.addTest(AccessControlTests.suite());
|
suite.addTest(AccessControlTests.suite());
|
||||||
suite.addTest(VariableReadWriteFlagsTest.suite());
|
suite.addTest(VariableReadWriteFlagsTest.suite());
|
||||||
suite.addTest(AST2CPPAttributeTests.suite());
|
suite.addTest(AST2CPPAttributeTests.suite());
|
||||||
|
// C++14 tests
|
||||||
suite.addTest(VariableTemplateTests.suite());
|
suite.addTest(VariableTemplateTests.suite());
|
||||||
suite.addTestSuite(ReturnTypeDeductionTests.class);
|
suite.addTestSuite(ReturnTypeDeductionTests.class);
|
||||||
|
suite.addTestSuite(GenericLambdaTests.class);
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Nathan Ridge.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.core.parser.tests.ast2.cxx14;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||||
|
import org.eclipse.cdt.internal.index.tests.IndexBindingResolutionTestBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index tests for C++14 generic lambdas.
|
||||||
|
*/
|
||||||
|
public class GenericLambdaIndexTests extends IndexBindingResolutionTestBase {
|
||||||
|
public GenericLambdaIndexTests() {
|
||||||
|
setStrategy(new SinglePDOMTestStrategy(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto Identity = [](auto a){ return a; };
|
||||||
|
|
||||||
|
// auto three = Identity(3);
|
||||||
|
// auto hello = Identity("hello");
|
||||||
|
public void testBasicCall() throws Exception {
|
||||||
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
|
helper.assertVariableType("three", CommonCPPTypes.int_);
|
||||||
|
helper.assertVariableType("hello", CommonCPPTypes.pointerToConstChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Adapted from the example in [expr.prim.lambda] p7 in the standard.
|
||||||
|
// auto Identity = [](auto a){ return a; };
|
||||||
|
|
||||||
|
// void f1(int(*)(int));
|
||||||
|
// void f2(char(*)(int));
|
||||||
|
// void g(int(*)(int));
|
||||||
|
// void g(char(*)(char));
|
||||||
|
// void h(int(*)(int)); // #1
|
||||||
|
// void h(char(*)(int)); // #2
|
||||||
|
// int main() {
|
||||||
|
// f1(Identity); // ok
|
||||||
|
// f2(Identity); // error: not convertible
|
||||||
|
// g(Identity); // error: ambiguous
|
||||||
|
// h(Identity); // ok: calls #1
|
||||||
|
// }
|
||||||
|
public void testConversionToFunctionPointer() throws Exception {
|
||||||
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
|
helper.assertNonProblem("f1(Id", "f1");
|
||||||
|
helper.assertProblem("f2(Id", "f2");
|
||||||
|
helper.assertProblem("g(Id", "g");
|
||||||
|
IFunction h1 = helper.assertNonProblem("h(int", "h");
|
||||||
|
IFunction hCall = helper.assertNonProblem("h(Id", "h");
|
||||||
|
assertSame(h1, hCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
// template <typename... T>
|
||||||
|
// struct tuple {};
|
||||||
|
//
|
||||||
|
// template <typename... T>
|
||||||
|
// tuple<T...> make_tuple(T...);
|
||||||
|
//
|
||||||
|
// auto L = [](auto... args) { return make_tuple(args...); };
|
||||||
|
//
|
||||||
|
// struct Cat { void meow(); };
|
||||||
|
//
|
||||||
|
// Cat foo(tuple<int, char>);
|
||||||
|
// Cat bar(tuple<int, char, float>);
|
||||||
|
//
|
||||||
|
// void waldo(Cat);
|
||||||
|
|
||||||
|
// int main() {
|
||||||
|
// waldo(foo(L(42, 'x')));
|
||||||
|
// waldo(bar(L(42, 'x', 42.0f)));
|
||||||
|
// }
|
||||||
|
public void _testVariadicAutoParameter() throws Exception {
|
||||||
|
// TODO: To pass this test, we need to store lambda parameters in the index.
|
||||||
|
checkBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Adapted from the example in [expr.prim.lambda] p6 in the standard.
|
||||||
|
// namespace std {
|
||||||
|
// struct ostream {
|
||||||
|
// template <typename T>
|
||||||
|
// ostream& operator<<(const T&);
|
||||||
|
// };
|
||||||
|
// ostream cout;
|
||||||
|
// }
|
||||||
|
// auto vglambda = [](auto printer) {
|
||||||
|
// return [=](auto&&... ts) {
|
||||||
|
// return [=]() {
|
||||||
|
// return printer(ts...);
|
||||||
|
// };
|
||||||
|
// };
|
||||||
|
// };
|
||||||
|
// auto p = vglambda(
|
||||||
|
// [](auto v1, auto v2, auto v3) {
|
||||||
|
// return std::cout << v1 << v2 << v3;
|
||||||
|
// });
|
||||||
|
// auto q = p(1, 'a', 3.14);
|
||||||
|
// void waldo(const std::ostream&);
|
||||||
|
|
||||||
|
// int main() {
|
||||||
|
// waldo(q());
|
||||||
|
// }
|
||||||
|
public void testNestedGenericLambdas() throws Exception {
|
||||||
|
checkBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Nathan Ridge.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.core.parser.tests.ast2.cxx14;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||||
|
import org.eclipse.cdt.core.parser.tests.ast2.AST2CPPTestBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AST tests for C++14 generic lambdas.
|
||||||
|
*/
|
||||||
|
public class GenericLambdaTests extends AST2CPPTestBase {
|
||||||
|
// auto Identity = [](auto a){ return a; };
|
||||||
|
// auto three = Identity(3);
|
||||||
|
// auto hello = Identity("hello");
|
||||||
|
public void testBasicCall() throws Exception {
|
||||||
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
|
helper.assertVariableType("three", CommonCPPTypes.int_);
|
||||||
|
helper.assertVariableType("hello", CommonCPPTypes.pointerToConstChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Adapted from the example in [expr.prim.lambda] p7 in the standard.
|
||||||
|
// auto Identity = [](auto a){ return a; };
|
||||||
|
// void f1(int(*)(int));
|
||||||
|
// void f2(char(*)(int));
|
||||||
|
// void g(int(*)(int));
|
||||||
|
// void g(char(*)(char));
|
||||||
|
// void h(int(*)(int)); // #1
|
||||||
|
// void h(char(*)(int)); // #2
|
||||||
|
// void j(int&(*)(int*));
|
||||||
|
// int main() {
|
||||||
|
// f1(Identity); // ok
|
||||||
|
// f2(Identity); // error: not convertible
|
||||||
|
// g(Identity); // error: ambiguous
|
||||||
|
// h(Identity); // ok: calls #1
|
||||||
|
// j([](auto* a) -> auto& { return *a; }); // ok
|
||||||
|
// }
|
||||||
|
public void testConversionToFunctionPointer() throws Exception {
|
||||||
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
|
helper.assertNonProblem("f1(Id", "f1");
|
||||||
|
helper.assertProblem("f2(Id", "f2");
|
||||||
|
helper.assertProblem("g(Id", "g");
|
||||||
|
IFunction h1 = helper.assertNonProblem("h(int", "h");
|
||||||
|
IFunction hCall = helper.assertNonProblem("h(Id", "h");
|
||||||
|
assertSame(h1, hCall);
|
||||||
|
helper.assertNonProblem("j([]", "j");
|
||||||
|
}
|
||||||
|
|
||||||
|
// template <typename... T>
|
||||||
|
// struct tuple {};
|
||||||
|
//
|
||||||
|
// template <typename... T>
|
||||||
|
// tuple<T...> make_tuple(T...);
|
||||||
|
//
|
||||||
|
// auto L = [](auto... args) { return make_tuple(args...); };
|
||||||
|
//
|
||||||
|
// struct Cat { void meow(); };
|
||||||
|
//
|
||||||
|
// Cat foo(tuple<int, char>);
|
||||||
|
// Cat bar(tuple<int, char, float>);
|
||||||
|
//
|
||||||
|
// void waldo(Cat);
|
||||||
|
//
|
||||||
|
// int main() {
|
||||||
|
// waldo(foo(L(42, 'x')));
|
||||||
|
// waldo(bar(L(42, 'x', 42.0f)));
|
||||||
|
// }
|
||||||
|
public void testVariadicAutoParameter() throws Exception {
|
||||||
|
parseAndCheckBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Adapted from the example in [expr.prim.lambda] p6 in the standard.
|
||||||
|
// namespace std {
|
||||||
|
// struct ostream {
|
||||||
|
// template <typename T>
|
||||||
|
// ostream& operator<<(const T&);
|
||||||
|
// };
|
||||||
|
// ostream cout;
|
||||||
|
// }
|
||||||
|
// auto vglambda = [](auto printer) {
|
||||||
|
// return [=](auto&&... ts) {
|
||||||
|
// return [=]() {
|
||||||
|
// return printer(ts...);
|
||||||
|
// };
|
||||||
|
// };
|
||||||
|
// };
|
||||||
|
// auto p = vglambda(
|
||||||
|
// [](auto v1, auto v2, auto v3) {
|
||||||
|
// return std::cout << v1 << v2 << v3;
|
||||||
|
// });
|
||||||
|
// auto q = p(1, 'a', 3.14);
|
||||||
|
// void waldo(const std::ostream&);
|
||||||
|
// int main() {
|
||||||
|
// waldo(q());
|
||||||
|
// }
|
||||||
|
public void testNestedGenericLambdas() throws Exception {
|
||||||
|
parseAndCheckBindings();
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.index.tests;
|
package org.eclipse.cdt.internal.index.tests;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.parser.tests.ast2.cxx14.GenericLambdaIndexTests;
|
||||||
import org.eclipse.cdt.core.parser.tests.ast2.cxx14.ReturnTypeDeductionIndexTests;
|
import org.eclipse.cdt.core.parser.tests.ast2.cxx14.ReturnTypeDeductionIndexTests;
|
||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
|
@ -37,7 +38,9 @@ public class IndexTests extends TestSuite {
|
||||||
suite.addTest(IndexMultiVariantHeaderTest.suite());
|
suite.addTest(IndexMultiVariantHeaderTest.suite());
|
||||||
suite.addTest(IndexMultiFileTest.suite());
|
suite.addTest(IndexMultiFileTest.suite());
|
||||||
|
|
||||||
|
// C++14 index test suites
|
||||||
suite.addTestSuite(ReturnTypeDeductionIndexTests.class);
|
suite.addTestSuite(ReturnTypeDeductionIndexTests.class);
|
||||||
|
suite.addTestSuite(GenericLambdaIndexTests.class);
|
||||||
|
|
||||||
IndexCPPBindingResolutionBugs.addTests(suite);
|
IndexCPPBindingResolutionBugs.addTests(suite);
|
||||||
IndexCPPBindingResolutionTest.addTests(suite);
|
IndexCPPBindingResolutionTest.addTests(suite);
|
||||||
|
|
|
@ -40,6 +40,7 @@ public class CPPASTLambdaExpression extends ASTNode implements ICPPASTLambdaExpr
|
||||||
|
|
||||||
private IASTImplicitName fClosureTypeName;
|
private IASTImplicitName fClosureTypeName;
|
||||||
private IASTImplicitName fImplicitFunctionCallName;
|
private IASTImplicitName fImplicitFunctionCallName;
|
||||||
|
private IASTImplicitName fImplicitConversionOperatorName;
|
||||||
|
|
||||||
private ICPPEvaluation fEvaluation;
|
private ICPPEvaluation fEvaluation;
|
||||||
|
|
||||||
|
@ -106,10 +107,32 @@ public class CPPASTLambdaExpression extends ASTNode implements ICPPASTLambdaExpr
|
||||||
return fImplicitFunctionCallName;
|
return fImplicitFunctionCallName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IASTImplicitName getConversionOperatorName() {
|
||||||
|
if (fImplicitConversionOperatorName == null) {
|
||||||
|
final CPPClosureType closureType = getExpressionType();
|
||||||
|
ICPPFunction conversionOperator = closureType.getConversionOperator();
|
||||||
|
if (conversionOperator != null) {
|
||||||
|
CPPASTImplicitName name = new CPPASTImplicitName(closureType.getNameCharArray(), this);
|
||||||
|
name.setBinding(conversionOperator);
|
||||||
|
name.setIsDefinition(true);
|
||||||
|
|
||||||
|
if (fBody instanceof ASTNode) {
|
||||||
|
name.setOffsetAndLength(((ASTNode) fBody).getOffset(), 1);
|
||||||
|
}
|
||||||
|
fImplicitConversionOperatorName = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fImplicitConversionOperatorName;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IASTImplicitName[] getImplicitNames() {
|
public IASTImplicitName[] getImplicitNames() {
|
||||||
|
IASTImplicitName conversionOperatorName = getConversionOperatorName();
|
||||||
|
if (conversionOperatorName == null) {
|
||||||
return new IASTImplicitName[] { getFunctionCallOperatorName() };
|
return new IASTImplicitName[] { getFunctionCallOperatorName() };
|
||||||
}
|
}
|
||||||
|
return new IASTImplicitName[] { getFunctionCallOperatorName(), getConversionOperatorName() };
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IASTImplicitDestructorName[] getImplicitDestructorNames() {
|
public IASTImplicitDestructorName[] getImplicitDestructorNames() {
|
||||||
|
@ -138,8 +161,13 @@ public class CPPASTLambdaExpression extends ASTNode implements ICPPASTLambdaExpr
|
||||||
if (fDeclarator != null && !fDeclarator.accept(visitor))
|
if (fDeclarator != null && !fDeclarator.accept(visitor))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (visitor.shouldVisitImplicitNames && !getFunctionCallOperatorName().accept(visitor))
|
if (visitor.shouldVisitImplicitNames) {
|
||||||
|
for (IASTImplicitName name : getImplicitNames()) {
|
||||||
|
if (!name.accept(visitor)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (fBody != null && !fBody.accept(visitor))
|
if (fBody != null && !fBody.accept(visitor))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
|
@ -35,6 +36,7 @@ import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression.CaptureDefault;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression.CaptureDefault;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
|
||||||
|
@ -45,9 +47,11 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
||||||
import org.eclipse.cdt.core.index.IIndexBinding;
|
import org.eclipse.cdt.core.index.IIndexBinding;
|
||||||
import org.eclipse.cdt.core.index.IIndexFileSet;
|
import org.eclipse.cdt.core.index.IIndexFileSet;
|
||||||
|
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
import org.eclipse.cdt.core.parser.util.IContentAssistMatcher;
|
import org.eclipse.cdt.core.parser.util.IContentAssistMatcher;
|
||||||
import org.eclipse.cdt.internal.core.dom.Linkage;
|
import org.eclipse.cdt.internal.core.dom.Linkage;
|
||||||
|
@ -65,6 +69,8 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP
|
||||||
private final ICPPASTLambdaExpression fLambdaExpression;
|
private final ICPPASTLambdaExpression fLambdaExpression;
|
||||||
private ICPPMethod[] fMethods;
|
private ICPPMethod[] fMethods;
|
||||||
private ClassScope fScope;
|
private ClassScope fScope;
|
||||||
|
// Used for generic lambdas; null otherwise.
|
||||||
|
private ICPPTemplateParameter[] fInventedTemplateParameters;
|
||||||
|
|
||||||
public CPPClosureType(ICPPASTLambdaExpression lambdaExpr) {
|
public CPPClosureType(ICPPASTLambdaExpression lambdaExpr) {
|
||||||
fLambdaExpression= lambdaExpr;
|
fLambdaExpression= lambdaExpr;
|
||||||
|
@ -111,17 +117,45 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP
|
||||||
for (int i = 0; i < params.length; i++) {
|
for (int i = 0; i < params.length; i++) {
|
||||||
params[i]= new CPPParameter(parameterTypes[i], i);
|
params[i]= new CPPParameter(parameterTypes[i], i);
|
||||||
}
|
}
|
||||||
m= new CPPImplicitMethod(scope, OverloadableOperator.PAREN.toCharArray(), ft, params, false) {
|
char[] operatorParensName = OverloadableOperator.PAREN.toCharArray();
|
||||||
|
if (isGeneric()) {
|
||||||
|
m = new CPPImplicitMethodTemplate(getInventedTemplateParameterList(), scope, operatorParensName,
|
||||||
|
ft, params, false) {
|
||||||
@Override
|
@Override
|
||||||
public boolean isImplicit() { return false; }
|
public boolean isImplicit() { return false; }
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
m= new CPPImplicitMethod(scope, operatorParensName, ft, params, false) {
|
||||||
|
@Override
|
||||||
|
public boolean isImplicit() { return false; }
|
||||||
|
};
|
||||||
|
}
|
||||||
result[4]= m;
|
result[4]= m;
|
||||||
|
|
||||||
// Conversion operator
|
// Conversion operator
|
||||||
if (needConversionOperator) {
|
if (needConversionOperator) {
|
||||||
final CPPFunctionType conversionTarget = new CPPFunctionType(returnType, parameterTypes);
|
final CPPFunctionType conversionTarget = new CPPFunctionType(returnType, parameterTypes);
|
||||||
ft= new CPPFunctionType(conversionTarget, IType.EMPTY_TYPE_ARRAY, true, false, false, false, false);
|
ft= new CPPFunctionType(conversionTarget, IType.EMPTY_TYPE_ARRAY, true, false, false, false, false);
|
||||||
m= new CPPImplicitMethod(scope, CPPASTConversionName.createName(conversionTarget, null), ft, params, false);
|
char[] conversionOperatorName = CPPASTConversionName.createName(conversionTarget, null);
|
||||||
|
if (isGeneric()) {
|
||||||
|
ICPPTemplateParameter[] templateParams = getInventedTemplateParameterList();
|
||||||
|
// Clone the template parameters, since they are used by the function call operator,
|
||||||
|
// and the same parameters cannot participate in two different templates.
|
||||||
|
ICPPTemplateParameter[] templateParamClones = new ICPPTemplateParameter[templateParams.length];
|
||||||
|
for (int i = 0; i < templateParams.length; ++i) {
|
||||||
|
templateParamClones[i] = (ICPPTemplateParameter) ((IType) templateParams[i]).clone();
|
||||||
|
}
|
||||||
|
m = new CPPImplicitMethodTemplate(templateParamClones, scope,
|
||||||
|
conversionOperatorName, ft, params, false) {
|
||||||
|
@Override
|
||||||
|
public boolean isImplicit() { return false; }
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
m= new CPPImplicitMethod(scope, conversionOperatorName, ft, params, false) {
|
||||||
|
@Override
|
||||||
|
public boolean isImplicit() { return false; }
|
||||||
|
};
|
||||||
|
}
|
||||||
result[5]= m;
|
result[5]= m;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -167,6 +201,40 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP
|
||||||
return ProblemType.CANNOT_DEDUCE_AUTO_TYPE;
|
return ProblemType.CANNOT_DEDUCE_AUTO_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isGeneric() {
|
||||||
|
return getInventedTemplateParameterList().length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICPPTemplateParameter[] getInventedTemplateParameterList() {
|
||||||
|
if (fInventedTemplateParameters == null) {
|
||||||
|
fInventedTemplateParameters = computeInventedTemplateParameterList();
|
||||||
|
}
|
||||||
|
return fInventedTemplateParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICPPTemplateParameter[] computeInventedTemplateParameterList() {
|
||||||
|
ICPPASTFunctionDeclarator lambdaDtor = fLambdaExpression.getDeclarator();
|
||||||
|
ICPPTemplateParameter[] result = ICPPTemplateParameter.EMPTY_TEMPLATE_PARAMETER_ARRAY;
|
||||||
|
if (lambdaDtor != null) {
|
||||||
|
// Create an invented template parameter for every "auto" in the lambda's
|
||||||
|
// function parameter list.
|
||||||
|
int position = 0;
|
||||||
|
ICPPASTParameterDeclaration[] params = lambdaDtor.getParameters();
|
||||||
|
for (ICPPASTParameterDeclaration param : params) {
|
||||||
|
IASTDeclSpecifier declSpec = param.getDeclSpecifier();
|
||||||
|
if (declSpec instanceof IASTSimpleDeclSpecifier) {
|
||||||
|
if (((IASTSimpleDeclSpecifier) declSpec).getType() == IASTSimpleDeclSpecifier.t_auto) {
|
||||||
|
boolean isPack = param.getDeclarator().declaresParameterPack();
|
||||||
|
result = ArrayUtil.append(result, new CPPImplicitTemplateTypeParameter(
|
||||||
|
fLambdaExpression, position, isPack));
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ArrayUtil.trim(result);
|
||||||
|
}
|
||||||
|
|
||||||
private IType[] getParameterTypes() {
|
private IType[] getParameterTypes() {
|
||||||
ICPPASTFunctionDeclarator lambdaDtor = fLambdaExpression.getDeclarator();
|
ICPPASTFunctionDeclarator lambdaDtor = fLambdaExpression.getDeclarator();
|
||||||
if (lambdaDtor != null) {
|
if (lambdaDtor != null) {
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Nathan Ridge.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binding for implicit method templates.
|
||||||
|
*
|
||||||
|
* Used for the function call operator and pointer-to-function conversion operator
|
||||||
|
* of a generic lambda.
|
||||||
|
*/
|
||||||
|
public class CPPImplicitMethodTemplate extends CPPImplicitMethod implements ICPPFunctionTemplate {
|
||||||
|
private ICPPTemplateParameter[] fTemplateParameters;
|
||||||
|
|
||||||
|
public CPPImplicitMethodTemplate(ICPPTemplateParameter[] templateParameters, ICPPClassScope scope,
|
||||||
|
char[] name, ICPPFunctionType type, ICPPParameter[] params, boolean isConstexpr) {
|
||||||
|
super(scope, name, type, params, isConstexpr);
|
||||||
|
fTemplateParameters = templateParameters;
|
||||||
|
for (ICPPTemplateParameter parameter : templateParameters) {
|
||||||
|
if (parameter instanceof CPPImplicitTemplateTypeParameter) {
|
||||||
|
((CPPImplicitTemplateTypeParameter) parameter).setContainingTemplate(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ICPPTemplateParameter[] getTemplateParameters() {
|
||||||
|
return fTemplateParameters;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Nathan Ridge.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ILinkage;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter;
|
||||||
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.Linkage;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||||
|
import org.eclipse.core.runtime.PlatformObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binding for implicit template type parameters.
|
||||||
|
*
|
||||||
|
* Used for the template type parameters of implicit method templates.
|
||||||
|
*/
|
||||||
|
public class CPPImplicitTemplateTypeParameter extends PlatformObject implements ICPPTemplateTypeParameter,
|
||||||
|
ICPPUnknownType, ICPPUnknownBinding {
|
||||||
|
private int fParameterID;
|
||||||
|
private boolean fIsParameterPack;
|
||||||
|
private ICPPScope fUnknownScope;
|
||||||
|
|
||||||
|
// The containing (implicit) template definition.
|
||||||
|
private ICPPTemplateDefinition fContainingTemplate;
|
||||||
|
|
||||||
|
// The AST node that triggered the creation of the implicit template.
|
||||||
|
// For methods of generic lambdas, this is the lambda expression.
|
||||||
|
private IASTNode fNode;
|
||||||
|
|
||||||
|
public CPPImplicitTemplateTypeParameter(IASTNode node, int position, boolean isParameterPack) {
|
||||||
|
fParameterID = computeParameterID(position);
|
||||||
|
fIsParameterPack = isParameterPack;
|
||||||
|
fNode = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int computeParameterID(int position) {
|
||||||
|
int nesting = 0;
|
||||||
|
for (IASTNode node = fNode; node != null; node = node.getParent()) {
|
||||||
|
if (node instanceof ICPPASTInternalTemplateDeclaration) {
|
||||||
|
nesting = ((ICPPASTInternalTemplateDeclaration) node).getNestingLevel();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (nesting << 16) + (position & 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContainingTemplate(ICPPTemplateDefinition containingTemplate) {
|
||||||
|
fContainingTemplate = containingTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getQualifiedName() throws DOMException {
|
||||||
|
return new String[] { getName() };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char[][] getQualifiedNameCharArray() throws DOMException {
|
||||||
|
return new char[][] { getNameCharArray() };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isGloballyQualified() throws DOMException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return new String();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char[] getNameCharArray() {
|
||||||
|
// Implicit template parameters are unnamed.
|
||||||
|
return CharArrayUtils.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ILinkage getLinkage() {
|
||||||
|
return Linkage.CPP_LINKAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinding getOwner() {
|
||||||
|
return fContainingTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IScope getScope() throws DOMException {
|
||||||
|
// TODO: Do we need an implicit template scope for the implicit template
|
||||||
|
// parameter to live in?
|
||||||
|
return CPPVisitor.getContainingScope(fNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public short getParameterPosition() {
|
||||||
|
return (short) fParameterID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public short getTemplateNestingLevel() {
|
||||||
|
return (short) (fParameterID >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getParameterID() {
|
||||||
|
return fParameterID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ICPPTemplateArgument getDefaultValue() {
|
||||||
|
// Implicit template parameters do not have default arguments.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isParameterPack() {
|
||||||
|
return fIsParameterPack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IType getDefault() throws DOMException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSameType(IType type) {
|
||||||
|
if (type == this)
|
||||||
|
return true;
|
||||||
|
if (type instanceof ITypedef)
|
||||||
|
return type.isSameType(this);
|
||||||
|
if (!(type instanceof ICPPTemplateTypeParameter))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return getParameterID() == ((ICPPTemplateParameter) type).getParameterID();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object clone() {
|
||||||
|
return new CPPImplicitTemplateTypeParameter(fNode, getParameterPosition(), fIsParameterPack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ICPPScope asScope() throws DOMException {
|
||||||
|
if (fUnknownScope == null) {
|
||||||
|
fUnknownScope = new CPPUnknownTypeScope(this, null);
|
||||||
|
}
|
||||||
|
return fUnknownScope;
|
||||||
|
}
|
||||||
|
}
|
|
@ -170,6 +170,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.util.ReturnStatementVisitor;
|
import org.eclipse.cdt.core.dom.ast.util.ReturnStatementVisitor;
|
||||||
import org.eclipse.cdt.core.index.IIndex;
|
import org.eclipse.cdt.core.index.IIndex;
|
||||||
|
@ -195,6 +196,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArrayType;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplate;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplate;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassType;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassType;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPConstructor;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPConstructor;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPConstructorTemplate;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPConstructorTemplate;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPEnumeration;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPEnumeration;
|
||||||
|
@ -1887,10 +1889,17 @@ public class CPPVisitor extends ASTQueries {
|
||||||
public static IType createType(final ICPPASTParameterDeclaration pdecl, boolean forFuncType) {
|
public static IType createType(final ICPPASTParameterDeclaration pdecl, boolean forFuncType) {
|
||||||
IASTDeclSpecifier pDeclSpec = pdecl.getDeclSpecifier();
|
IASTDeclSpecifier pDeclSpec = pdecl.getDeclSpecifier();
|
||||||
ICPPASTDeclarator pDtor = pdecl.getDeclarator();
|
ICPPASTDeclarator pDtor = pdecl.getDeclarator();
|
||||||
IType pt = createType(pDeclSpec);
|
IType pt;
|
||||||
|
PlaceholderKind placeholder = usesAuto(pDeclSpec);
|
||||||
|
if (placeholder != null) {
|
||||||
|
pt = createAutoType(pDeclSpec, pDtor, 0, placeholder);
|
||||||
|
} else {
|
||||||
|
pt = createType(pDeclSpec);
|
||||||
if (pDtor != null) {
|
if (pDtor != null) {
|
||||||
pt = createType(pt, pDtor);
|
pt = createType(pt, pDtor);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pt= adjustParameterType(pt, forFuncType);
|
pt= adjustParameterType(pt, forFuncType);
|
||||||
|
|
||||||
if (pDtor != null && findInnermostDeclarator(pDtor).declaresParameterPack()) {
|
if (pDtor != null && findInnermostDeclarator(pDtor).declaresParameterPack()) {
|
||||||
|
@ -2118,6 +2127,40 @@ public class CPPVisitor extends ASTQueries {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IType createAutoParameterType(IASTDeclSpecifier declSpec, IASTDeclarator declarator,
|
||||||
|
ICPPASTParameterDeclaration declaration, PlaceholderKind placeholder) {
|
||||||
|
// decltype(auto) is not allowed in parameters.
|
||||||
|
if (placeholder == PlaceholderKind.DecltypeAuto) {
|
||||||
|
return ProblemType.CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In C++14, auto is only allowed in lambda parameters.
|
||||||
|
// In the Concepts TS (not implemented yet), this restriction is removed.
|
||||||
|
ICPPASTFunctionDeclarator functionDeclarator = (ICPPASTFunctionDeclarator) declaration.getParent();
|
||||||
|
if (functionDeclarator.getParent() instanceof ICPPASTLambdaExpression) {
|
||||||
|
ICPPASTLambdaExpression lambda = (ICPPASTLambdaExpression) functionDeclarator.getParent();
|
||||||
|
CPPClosureType closure = (CPPClosureType) lambda.getExpressionType();
|
||||||
|
ICPPTemplateParameter[] templateParameters = closure.getInventedTemplateParameterList();
|
||||||
|
|
||||||
|
// Find the invented template parameter corresponding to this 'auto'.
|
||||||
|
int templateParameterIndex = -1;
|
||||||
|
for (ICPPASTParameterDeclaration parameter : functionDeclarator.getParameters()) {
|
||||||
|
if (usesAuto(parameter.getDeclSpecifier()) != null) {
|
||||||
|
++templateParameterIndex;
|
||||||
|
}
|
||||||
|
if (parameter == declaration)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (templateParameterIndex >= 0 && templateParameterIndex < templateParameters.length) {
|
||||||
|
ICPPTemplateParameter templateParameter = templateParameters[templateParameterIndex];
|
||||||
|
if (templateParameter instanceof ICPPTemplateTypeParameter) {
|
||||||
|
return createType((ICPPTemplateTypeParameter) templateParameter, declarator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ProblemType.CANNOT_DEDUCE_AUTO_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
private static IType createAutoType(final IASTDeclSpecifier declSpec, IASTDeclarator declarator,
|
private static IType createAutoType(final IASTDeclSpecifier declSpec, IASTDeclarator declarator,
|
||||||
int flags, PlaceholderKind placeholderKind) {
|
int flags, PlaceholderKind placeholderKind) {
|
||||||
IType cannotDeduce = placeholderKind == PlaceholderKind.Auto ?
|
IType cannotDeduce = placeholderKind == PlaceholderKind.Auto ?
|
||||||
|
@ -2134,6 +2177,10 @@ public class CPPVisitor extends ASTQueries {
|
||||||
return createAutoFunctionType(declSpec, (ICPPASTFunctionDeclarator) declarator, flags,
|
return createAutoFunctionType(declSpec, (ICPPASTFunctionDeclarator) declarator, flags,
|
||||||
placeholderKind);
|
placeholderKind);
|
||||||
}
|
}
|
||||||
|
if (declarator.getParent() instanceof ICPPASTParameterDeclaration) {
|
||||||
|
return createAutoParameterType(declSpec, declarator,
|
||||||
|
(ICPPASTParameterDeclaration) declarator.getParent(), placeholderKind);
|
||||||
|
}
|
||||||
ICPPASTInitializerClause autoInitClause= null;
|
ICPPASTInitializerClause autoInitClause= null;
|
||||||
IASTNode parent = declarator.getParent().getParent();
|
IASTNode parent = declarator.getParent().getParent();
|
||||||
if (parent instanceof ICPPASTNewExpression) {
|
if (parent instanceof ICPPASTNewExpression) {
|
||||||
|
|
|
@ -262,14 +262,19 @@ abstract public class IndexerASTVisitor extends ASTVisitor {
|
||||||
final IASTName closureName = lambdaExpr.getClosureTypeName();
|
final IASTName closureName = lambdaExpr.getClosureTypeName();
|
||||||
visit(closureName, fDefinitionName);
|
visit(closureName, fDefinitionName);
|
||||||
|
|
||||||
// Definition of call operator
|
|
||||||
IASTName callOp= lambdaExpr.getFunctionCallOperatorName();
|
// Definition of call operator and conversion operator (if applicable)
|
||||||
visit(callOp, closureName);
|
IASTName[] ops = lambdaExpr.getImplicitNames();
|
||||||
|
for (IASTName op : ops) {
|
||||||
|
visit(op, closureName);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
IBinding owner = CPPVisitor.findDeclarationOwner(lambdaExpr, true);
|
IBinding owner = CPPVisitor.findDeclarationOwner(lambdaExpr, true);
|
||||||
boolean localToFunction = owner instanceof IFunction;
|
boolean localToFunction = owner instanceof IFunction;
|
||||||
if (!localToFunction)
|
if (!localToFunction)
|
||||||
push(callOp, lambdaExpr); // Local closures don't appear in the index, so don't refer to them.
|
// Local closures don't appear in the index, so don't refer to them.
|
||||||
|
push(lambdaExpr.getFunctionCallOperatorName(), lambdaExpr);
|
||||||
|
|
||||||
ICPPASTFunctionDeclarator dtor = lambdaExpr.getDeclarator();
|
ICPPASTFunctionDeclarator dtor = lambdaExpr.getDeclarator();
|
||||||
if (dtor != null && !dtor.accept(this))
|
if (dtor != null && !dtor.accept(this))
|
||||||
|
|
Loading…
Add table
Reference in a new issue