summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Ridge2013-12-20 03:12:13 (EST)
committerSergey Prigogin2013-12-21 13:04:43 (EST)
commitc1b801b036f93a6b5a484b53613e8bac765f2578 (patch)
tree33521735a78c724e307fde32e6ad55255df4d630
parent9e3bca14b5c06247fb2e16f8b67e48a70b04ed97 (diff)
downloadorg.eclipse.cdt-c1b801b036f93a6b5a484b53613e8bac765f2578.zip
org.eclipse.cdt-c1b801b036f93a6b5a484b53613e8bac765f2578.tar.gz
org.eclipse.cdt-c1b801b036f93a6b5a484b53613e8bac765f2578.tar.bz2
Bug 332829 - Handle ambiguity between a type-id and an expression otherrefs/changes/40/20140/2
than an id-expression in a template argument Change-Id: I1ec6157b09526a1f98850361f903fbea8b8c8a89 Signed-off-by: Nathan Ridge <zeratul976@hotmail.com> Reviewed-on: https://git.eclipse.org/r/20140 Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com> IP-Clean: Sergey Prigogin <eclipse.sprigogin@gmail.com> Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java14
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTAmbiguousTemplateArgument.java14
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousTemplateArgument.java27
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java94
4 files changed, 100 insertions, 49 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 de894db..c5679dc 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
@@ -7265,6 +7265,20 @@ public class AST2TemplateTests extends AST2TestBase {
assertEquals("bool", ASTTypeUtil.getType(td.getType()));
ah.assertProblem("B<int*>::type", "type");
}
+
+ // constexpr int f() { return 1; }
+ //
+ // template <int>
+ // struct A {
+ // static void g() {}
+ // };
+ //
+ // void bar() {
+ // A<f()>::g();
+ // }
+ public void testConstexprFunctionCallInTemplateArgument_332829() throws Exception {
+ parseAndCheckBindings();
+ }
// template <typename From>
// struct is_convertible {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTAmbiguousTemplateArgument.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTAmbiguousTemplateArgument.java
index a11c134..6bad894 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTAmbiguousTemplateArgument.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTAmbiguousTemplateArgument.java
@@ -26,11 +26,11 @@ public interface ICPPASTAmbiguousTemplateArgument extends IASTNode {
/**
* Add an partial parse tree that could be a suitable subtree representing
* the template argument
- * @param idExpression a non-null id-expression or a pack expansion of an id-expression
- * @since 5.2
+ * @param expression a non-null expression
+ * @since 5.6
*/
- public void addIdExpression(IASTExpression idExpression);
-
+ public void addExpression(IASTExpression expression);
+
/**
* Add an partial parse tree that could be a suitable subtree representing
* the template argument
@@ -39,6 +39,12 @@ public interface ICPPASTAmbiguousTemplateArgument extends IASTNode {
public void addTypeId(IASTTypeId typeId);
/**
+ * @deprecated Replaced by {@link #addExpression(IASTExpression)}.
+ */
+ @Deprecated
+ public void addIdExpression(IASTExpression idExpression);
+
+ /**
* @deprecated Replaced by {@link #addIdExpression(IASTExpression)}.
*/
@Deprecated
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousTemplateArgument.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousTemplateArgument.java
index e6b02b0..3314d71 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousTemplateArgument.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousTemplateArgument.java
@@ -31,7 +31,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode;
import org.eclipse.core.runtime.Assert;
/**
- * Ambiguity node for deciding between type-id and id-expression in a template argument.
+ * Ambiguity node for deciding between type-id and expression in a template argument.
*/
public class CPPASTAmbiguousTemplateArgument extends ASTAmbiguousNode implements ICPPASTAmbiguousTemplateArgument {
private List<IASTNode> fNodes;
@@ -43,15 +43,8 @@ public class CPPASTAmbiguousTemplateArgument extends ASTAmbiguousNode implements
public CPPASTAmbiguousTemplateArgument(IASTNode... nodes) {
fNodes= new ArrayList<IASTNode>(2);
for (IASTNode node : nodes) {
- if (node instanceof IASTTypeId || node instanceof IASTIdExpression) {
+ if (node instanceof IASTTypeId || node instanceof IASTExpression) {
fNodes.add(node);
- } else if (node instanceof ICPPASTPackExpansionExpression) {
- final IASTExpression pattern = ((ICPPASTPackExpansionExpression) node).getPattern();
- if (pattern instanceof IASTIdExpression) {
- fNodes.add(node);
- } else {
- Assert.isLegal(false, pattern == null ? "null" : pattern.getClass().getName()); //$NON-NLS-1$
- }
} else {
Assert.isLegal(false, node == null ? "null" : node.getClass().getName()); //$NON-NLS-1$
}
@@ -60,7 +53,9 @@ public class CPPASTAmbiguousTemplateArgument extends ASTAmbiguousNode implements
@Override
protected void beforeAlternative(IASTNode node) {
- // The name may be shared between the alternatives make sure it's parent is set correctly
+ // If the expression is an id-expression, the name may be shared
+ // between the alternatives (see bug 316704), so make sure its parent
+ // is set correctly.
if (node instanceof IASTTypeId) {
IASTDeclSpecifier declSpec = ((IASTTypeId) node).getDeclSpecifier();
if (declSpec instanceof IASTNamedTypeSpecifier) {
@@ -123,15 +118,19 @@ public class CPPASTAmbiguousTemplateArgument extends ASTAmbiguousNode implements
}
@Override
+ public void addExpression(IASTExpression expression) {
+ assertNotFrozen();
+ addNode(expression);
+ }
+
+ @Override
public void addIdExpression(IASTIdExpression idExpression) {
- assertNotFrozen();
- addNode(idExpression);
+ addExpression(idExpression);
}
@Override
public void addIdExpression(IASTExpression idExpression) {
- assertNotFrozen();
- addNode(idExpression);
+ addExpression(idExpression);
}
private void addNode(IASTNode node) {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java
index 0474384..b0176f4 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java
@@ -658,46 +658,78 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
if (typeId != null
&& (lt1 == IToken.tCOMMA || lt1 == IToken.tGT || lt1 == IToken.tGT_in_SHIFTR
|| lt1 == IToken.tEOC || lt1 == IToken.tELLIPSIS)) {
- // This is potentially a type-id, now check ambiguity with id-expression
- IASTDeclSpecifier declspec= typeId.getDeclSpecifier();
- if (declspec instanceof IASTNamedTypeSpecifier) {
- final IASTNamedTypeSpecifier namedDeclspec = (IASTNamedTypeSpecifier) declspec;
- IASTName name= namedDeclspec.getName();
- if (name.contains(typeId)) {
- IToken typeIdEnd= mark();
- IASTIdExpression idExpr= setRange(nodeFactory.newIdExpression(name), name);
- try {
- IASTExpression expression = expression(ExprKind.eAssignment, BinaryExprCtx.eInTemplateID, idExpr, strat);
- boolean isAmbiguous= (expression == idExpr);
- if (LT(1) == IToken.tELLIPSIS) {
- IToken ellipsis= consume();
- if (isAmbiguous) {
- addPackExpansion(typeId, ellipsis);
- }
- expression= addPackExpansion(expression, ellipsis);
- }
- if (isAmbiguous) {
- ICPPASTAmbiguousTemplateArgument ambiguity= createAmbiguousTemplateArgument();
- ambiguity.addTypeId(typeId);
- ambiguity.addIdExpression(expression);
- return ambiguity;
- }
- return expression;
- } catch (BacktrackException e) {
- // Use the typeId
+ // This is potentially a type-id, now check ambiguity with expression.
+ IToken typeIdEnd= mark();
+ IASTNamedTypeSpecifier namedTypeSpec = null;
+ IASTName name = null;
+ try {
+ // If the type-id consists of a name, that name could be or contain
+ // a template-id, with template arguments of its own, which can
+ // themselves be ambiguous. If we parse the name anew as an
+ // id-expression, our complexity becomes exponential in the nesting
+ // depth of template-ids (bug 316704). To avoid this, we do not
+ // re-parse the name, but instead synthesize an id-expression from
+ // it, and then continue parsing an expression from the id-expression
+ // onwards (as the id-expression could be the beginning of a larger
+ // expression).
+ IASTIdExpression idExpression = null;
+ IASTDeclSpecifier declSpec = typeId.getDeclSpecifier();
+ if (declSpec instanceof IASTNamedTypeSpecifier) {
+ namedTypeSpec = (IASTNamedTypeSpecifier) declSpec;
+ name = namedTypeSpec.getName();
+ if (name.contains(typeId)) {
+ idExpression = setRange(nodeFactory.newIdExpression(name), name);
}
- backup(typeIdEnd);
- namedDeclspec.setName(name);
}
+
+ // Parse an expression, starting with the id-expression synthesized
+ // above if there is one, otherwise starting from the beginning of
+ // the argument.
+ if (idExpression == null)
+ backup(argStart);
+ IASTExpression expression = expression(ExprKind.eAssignment, BinaryExprCtx.eInTemplateID, idExpression, strat);
+
+ // At this point we have a valid type-id and a valid expression.
+ // We prefer the longer one.
+ if (!typeId.contains(expression)) {
+ // The expression is longer.
+ if (LT(1) == IToken.tELLIPSIS) {
+ expression = addPackExpansion(expression, consume());
+ }
+ return expression;
+ } else if (expression.contains(typeId)) {
+ // The two are of the same length - ambiguous.
+ if (LT(1) == IToken.tELLIPSIS) {
+ IToken ellipsis = consume();
+ addPackExpansion(typeId, ellipsis);
+ expression = addPackExpansion(expression, ellipsis);
+ }
+ ICPPASTAmbiguousTemplateArgument ambiguity = createAmbiguousTemplateArgument();
+ ambiguity.addTypeId(typeId);
+ ambiguity.addExpression(expression);
+ return ambiguity;
+ }
+ // The type-id is longer, use it.
+ } catch (BacktrackException e) {
+ // Failed to parse an expression, use the type id.
+ }
+
+ // Clean up after our failed attempt to parse an expression.
+ backup(typeIdEnd);
+ if (name != null && namedTypeSpec != null) {
+ // When we synthesized the id-expression, it took ownership
+ // of the name. Give ownership back to the type-id.
+ namedTypeSpec.setName(name);
}
- // There is no ambiguity, use the type-id
+
+ // Use the type-id.
if (LT(1) == IToken.tELLIPSIS) {
addPackExpansion(typeId, consume());
}
return typeId;
}
- // Not a type-id, parse as expression
+ // Not a type-id, parse as expression.
backup(argStart);
IASTExpression expr= expression(ExprKind.eAssignment, BinaryExprCtx.eInTemplateID, null, strat);
if (LT(1) == IToken.tELLIPSIS) {