Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Ridge2018-02-04 07:21:53 +0000
committerNathan Ridge2018-02-12 00:12:11 +0000
commit276fda83a5d72c6283547708a2707049bfc8e647 (patch)
treeeb8c3b651343bad9ebbbd5cf9af17246ff9d6469
parentbe792e53ea0056150a1bc313ae6c71663750585c (diff)
downloadorg.eclipse.cdt-276fda83a5d72c6283547708a2707049bfc8e647.tar.gz
org.eclipse.cdt-276fda83a5d72c6283547708a2707049bfc8e647.tar.xz
org.eclipse.cdt-276fda83a5d72c6283547708a2707049bfc8e647.zip
Bug 530692 - Avoid EvalFunctionCall storing the evaluation for the implicit 'this' twice
EvalFunctionCall.fImplicitThis is sometimes redundant in that the owner evaluation is already stored by one of the arguments. In such cases, storing the owner separately in fImplicitThis can lead to exponential complexity in chained method calls. We resolve the duplication by computing the implicit this from the function name evaluation instead of storing it where possible. This was already implemented for cases where the function name evaluation is an EvalMemberAccess in commit 659ff8c4a7c9. This commit extends the approach to cases where the function name evaluation is an EvalID. Change-Id: Ic71e81b4692c51ffb8e15b3da9fc2dff1a554f05
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java75
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java16
2 files changed, 90 insertions, 1 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java
index c1f8b07fbed..7afb03ee66f 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java
@@ -10576,4 +10576,79 @@ public class AST2TemplateTests extends AST2CPPTestBase {
public void testTemplateAliasWithVariadicArgs_530086b() throws Exception {
parseAndCheckBindings();
}
+
+ // template<bool, typename _Tp = void>
+ // struct enable_if {};
+ //
+ // template<typename _Tp>
+ // struct enable_if<true, _Tp> { typedef _Tp type; };
+ //
+ // template<typename _Tp> _Tp&& declval();
+ //
+ // template<typename _Signature> class function;
+ //
+ // template<typename _Res, typename... _ArgTypes>
+ // class function<_Res(_ArgTypes...)>
+ // {
+ // template<typename _Func,
+ // typename _Res2 = decltype(declval<_Func&>()(declval<_ArgTypes>()...))>
+ // struct _Callable { };
+ //
+ // public:
+ // template<typename _Functor,
+ // typename = typename enable_if<_Callable<_Functor>::value, void>::type>
+ // function(_Functor);
+ // };
+ //
+ // void do_with_cql_env(function<void(int&)> func);
+ //
+ // void test_range_queries() {
+ // do_with_cql_env([] (auto& e) {
+ // return e.create_table([](auto ks_name) {
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // }).then([&e] {
+ // return e.foo();
+ // });
+ // });
+ // }
+ public void testLongDependentFunctionCallChain_530692() throws Exception {
+ parseAndCheckBindings();
+ }
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java
index a110e575e0e..cc3970425b1 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java
@@ -85,6 +85,8 @@ public final class EvalFunctionCall extends CPPDependentEvaluation {
if (fArguments.length > 0) {
if (fArguments[0] instanceof EvalMemberAccess) {
return ((EvalMemberAccess) fArguments[0]).getOwnerEval();
+ } else if (fArguments[0] instanceof EvalID) {
+ return ((EvalID) fArguments[0]).getFieldOwner();
}
}
@@ -221,6 +223,8 @@ public final class EvalFunctionCall extends CPPDependentEvaluation {
if (args == fArguments)
return this;
+ ICPPEvaluation implicitThis = fImplicitThis;
+
if (args[0] instanceof EvalFunctionSet && getOverload() == null) {
// Resolve the function using the parameters of the function call.
EvalFunctionSet functionSet = (EvalFunctionSet) args[0];
@@ -230,9 +234,19 @@ public final class EvalFunctionCall extends CPPDependentEvaluation {
if (args[0] == EvalFixed.INCOMPLETE) {
return args[0];
}
+
+ // For functions sets of member functions, EvalFunctionSet does not store
+ // the value of the object on which the member function is called.
+ // If this value was previously elided (not stored explicitly in
+ // fImplicitThis to avoid duplication with the copy stored in fArguments[0]),
+ // starts storing it in fImplicitThis because *someone* needs to store
+ // the value for correct constexpr evaluation.
+ if (implicitThis == null) {
+ implicitThis = getImplicitThis();
+ }
}
- ICPPEvaluation newImplicitThis = fImplicitThis != null ? fImplicitThis.instantiate(context, maxDepth) : null;
+ ICPPEvaluation newImplicitThis = implicitThis != null ? implicitThis.instantiate(context, maxDepth) : null;
return new EvalFunctionCall(args, newImplicitThis, getTemplateDefinition());
}

Back to the top