From 7768ee8e9ea0d2e630df043a32f405eab678958a Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Wed, 22 Jul 2009 16:04:46 +0000 Subject: [PATCH] Exponential complexity resolving overloaded function calls, bug 283324. --- .../core/parser/tests/ast2/AST2CPPTests.java | 19 +++++++++++++++ .../cdt/internal/core/dom/parser/ASTNode.java | 4 +++- .../parser/cpp/CPPASTBinaryExpression.java | 5 ++-- .../cpp/CPPASTFunctionCallExpression.java | 23 +++++++++++++------ .../dom/parser/cpp/CPPASTUnaryExpression.java | 5 ++-- 5 files changed, 42 insertions(+), 14 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index b9fceec07a0..115c968d6e2 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -7267,4 +7267,23 @@ public class AST2CPPTests extends AST2BaseTest { final String code = getAboveComment(); parseAndCheckBindings(code, ParserLanguage.CPP); } + + // class C { + // C& operator()() {return *this;} + // }; + // void test() { + // C c; + // c()()()()()()()()()()()()()(); + // } + public void testNestedOverloadedFunctionCalls_Bug283324() throws Exception { + final String code = getAboveComment(); + IASTTranslationUnit tu= parseAndCheckBindings(code, ParserLanguage.CPP); + IASTFunctionDefinition test= getDeclaration(tu, 1); + IASTExpressionStatement stmt= getStatement(test, 1); + long now= System.currentTimeMillis(); + IType t= stmt.getExpression().getExpressionType(); + assertInstance(t, ICPPReferenceType.class); + final long time = System.currentTimeMillis() - now; + assertTrue("Lasted " + time + "ms", time < 5000); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java index e3e32bb477e..4ae8d8d3e12 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java @@ -19,9 +19,11 @@ import org.eclipse.cdt.core.dom.ast.IASTImageLocation; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.OffsetLimitReachedException; import org.eclipse.cdt.core.parser.util.CharArrayUtils; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; import org.eclipse.cdt.internal.core.parser.scanner.ILexerLog; import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver; import org.eclipse.cdt.internal.core.parser.scanner.Lexer; @@ -32,7 +34,7 @@ import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions; * Base class for all non-preprocessor nodes in the AST. */ public abstract class ASTNode implements IASTNode { - + protected static final ICPPFunction UNINITIALIZED_FUNCTION = new CPPFunction(null); private static final IASTNodeLocation[] EMPTY_LOCATION_ARRAY = new IASTNodeLocation[0]; private IASTNode parent; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java index 0b0ed39ee45..e7728df1639 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java @@ -33,12 +33,11 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpression, IASTAmbiguityParent { - private static final ICPPFunction UNINITIALIZED = new CPPFunction(null); private int op; private IASTExpression operand1; private IASTExpression operand2; private IType type; - private ICPPFunction overload= UNINITIALIZED; + private ICPPFunction overload= UNINITIALIZED_FUNCTION; private IASTImplicitName[] implicitNames = null; @@ -166,7 +165,7 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr } public ICPPFunction getOverload() { - if (overload != UNINITIALIZED) + if (overload != UNINITIALIZED_FUNCTION) return overload; return overload = CPPSemantics.findOverloadedOperator(this); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java index 4ca80d05e7a..8d5c42cf674 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java @@ -44,6 +44,8 @@ public class CPPASTFunctionCallExpression extends ASTNode implements private IASTExpression parameter; private IASTImplicitName[] implicitNames = null; + private IType type; // cached type of expression + private ICPPFunction overload= UNINITIALIZED_FUNCTION; public CPPASTFunctionCallExpression() { @@ -182,16 +184,23 @@ public class CPPASTFunctionCallExpression extends ASTNode implements } public ICPPFunction getOperator() { - ICPPFunction[] overload = new ICPPFunction[] {null}; - getExpressionType(overload); - return overload[0]; + if (overload == UNINITIALIZED_FUNCTION) { + overload= null; + // as a side effect this computes the overload + getExpressionType(); + } + return overload; } public IType getExpressionType() { - return getExpressionType(null); + if (type == null) { + type= computeExpressionType(); + } + return type; } - private IType getExpressionType(ICPPFunction[] overload) { + private IType computeExpressionType() { + overload= null; try { IType t= null; if (functionName instanceof IASTIdExpression) { @@ -224,8 +233,8 @@ public class CPPASTFunctionCallExpression extends ASTNode implements if (op != null) { // overload can be a surrogate function call, which consists of a conversion and a call to // a dynamically computed function pointer. - if(overload != null && !(op instanceof CPPImplicitFunction)) - overload[0] = op; + if(!(op instanceof CPPImplicitFunction)) + overload = op; return op.getType().getReturnType(); } } else if (t instanceof IPointerType) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java index bb23f377cbd..9f9c5af837b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java @@ -47,11 +47,10 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; * Unary expression in c++ */ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpression, IASTAmbiguityParent { - private static final ICPPFunction UNINITIALIZED = new CPPFunction(null); private int op; private IASTExpression operand; - private ICPPFunction overload = UNINITIALIZED; + private ICPPFunction overload = UNINITIALIZED_FUNCTION; private IASTImplicitName[] implicitNames = null; public CPPASTUnaryExpression() { @@ -158,7 +157,7 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres public ICPPFunction getOverload() { - if (overload != UNINITIALIZED) + if (overload != UNINITIALIZED_FUNCTION) return overload; overload = CPPSemantics.findOverloadedOperator(this);