Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Schorn2013-02-06 00:12:47 +0000
committerSergey Prigogin2013-02-06 00:12:47 +0000
commit6dab072dcd68a6387f9a3390ad9ce2ff0febd251 (patch)
treefadf3fa534d96aa515807896a10c64e26002cec5
parent3ea87ef826db98b9f084a6d2a56237567cc49ea5 (diff)
downloadorg.eclipse.cdt-6dab072dcd68a6387f9a3390ad9ce2ff0febd251.tar.gz
org.eclipse.cdt-6dab072dcd68a6387f9a3390ad9ce2ff0febd251.tar.xz
org.eclipse.cdt-6dab072dcd68a6387f9a3390ad9ce2ff0febd251.zip
Bug 393959: Unhandled template id ambiguity.
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateIDAmbiguity.java20
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java165
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/NameOrTemplateIDVariants.java82
3 files changed, 137 insertions, 130 deletions
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateIDAmbiguity.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateIDAmbiguity.java
index 959973e4038..1d03067fe9e 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateIDAmbiguity.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateIDAmbiguity.java
@@ -17,7 +17,6 @@ import java.util.List;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
-import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
@@ -43,17 +42,14 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.NameOrTemplateIDVariants.Var
*/
public class CPPASTTemplateIDAmbiguity extends ASTAmbiguousNode implements IASTAmbiguousExpression,
ICPPASTExpression {
- private BinaryOperator fLastOperator;
- private IASTInitializerClause fLastExpression;
+ private final BinaryOperator fEndOperator;
private final BranchPoint fVariants;
private IASTNode[] fNodes;
private final AbstractGNUSourceCodeParser fParser;
- public CPPASTTemplateIDAmbiguity(AbstractGNUSourceCodeParser parser, BinaryOperator lastOperator, IASTInitializerClause expr,
- BranchPoint variants) {
+ public CPPASTTemplateIDAmbiguity(AbstractGNUSourceCodeParser parser, BinaryOperator endOperator, BranchPoint variants) {
fParser= parser;
- fLastOperator= lastOperator;
- fLastExpression= expr;
+ fEndOperator= endOperator;
fVariants= variants;
}
@@ -92,10 +88,7 @@ public class CPPASTTemplateIDAmbiguity extends ASTAmbiguousNode implements IASTA
if (selected != null) {
minOffset= selected.getRightOffset();
BinaryOperator targetOp = selected.getTargetOperator();
- if (targetOp == null) {
- fLastExpression= selected.getExpression();
- fLastOperator= v.getLeftOperator();
- } else {
+ if (targetOp != null) {
targetOp.exchange(selected.getExpression());
targetOp.setNext(v.getLeftOperator());
}
@@ -106,7 +99,7 @@ public class CPPASTTemplateIDAmbiguity extends ASTAmbiguousNode implements IASTA
owner.replace(nodeToReplace, this);
// Create the expression and replace it
- IASTExpression expr = fParser.buildExpression(fLastOperator, fLastExpression);
+ IASTExpression expr = fParser.buildExpression(fEndOperator.getNext(), fEndOperator.getExpression());
owner.replace(this, expr);
// Resolve further ambiguities within the new expression.
@@ -149,8 +142,7 @@ public class CPPASTTemplateIDAmbiguity extends ASTAmbiguousNode implements IASTA
public IASTNode[] getNodes() {
if (fNodes == null) {
List<IASTNode> nl= new ArrayList<IASTNode>();
- nl.add(fLastExpression);
- BinaryOperator op= fLastOperator;
+ BinaryOperator op= fEndOperator;
while (op != null) {
nl.add(op.getExpression());
op= op.getNext();
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 c3c639093fa..8975cb53967 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
@@ -765,6 +765,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
BinaryOperator lastOperator= null;
NameOrTemplateIDVariants variants= null;
+ IToken variantMark= mark();
if (expr == null) {
Object e = castExpressionForBinaryExpression(strat);
if (e instanceof IASTExpression) {
@@ -774,20 +775,21 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
final Variant variant = (Variant) e;
expr= variant.getExpression();
- variants.addBranchPoint(variant.getNext(), lastOperator, allowAssignment, conditionCount);
+ variants.addBranchPoint(variant.getNext(), null, allowAssignment, conditionCount);
}
}
- boolean doneExpression= false;
- do {
+ boolean stopWithNextOperator= false;
+ castExprLoop: for(;;) {
// Typically after a binary operator there cannot be a throw expression
boolean allowThrow= false;
// Brace initializers are allowed on the right hand side of an expression
boolean allowBraceInitializer= false;
- BacktrackException tryRecovery= null;
- final int operatorOffset= LA().getOffset();
- lt1= LT(1);
+ boolean doneExpression= false;
+ BacktrackException failure= null;
+ final int opOffset= LA().getOffset();
+ lt1= stopWithNextOperator ? IToken.tSEMI : LT(1);
switch (lt1) {
case IToken.tQUESTION:
conditionCount++;
@@ -880,7 +882,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
if (LT(2) != IToken.tGT_in_SHIFTR) {
IToken token = LA(1);
backtrack.initialize(token.getOffset(), token.getLength());
- tryRecovery= backtrack;
+ failure= backtrack;
break;
}
@@ -908,35 +910,46 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
doneExpression= true;
break;
}
-
- if (!doneExpression && tryRecovery == null) {
- consume(); // consumes the operator
-
- // Link variants that are closed by the new operator
- if (variants != null) {
- variants.closeVariants(operatorOffset, lastOperator);
+
+ // Close variants
+ if (failure == null) {
+ if (doneExpression) {
+ if (variants != null && !variants.hasRightBound(opOffset)) {
+ // We have a longer variant, ignore this one.
+ backtrack.initialize(opOffset, 1);
+ failure= backtrack;
+ } else {
+ break castExprLoop;
+ }
+ }
+ // Close variants with matching end
+ if (variants != null && lastOperator != null) {
+ variants.closeVariants(opOffset, lastOperator);
}
+ }
- // Determine next sub-expression
- if (lt1 == IToken.tQUESTION && LT(1) == IToken.tCOLON) {
- // Missing sub-expression after '?' (gnu-extension)
- expr= null;
- } else if (allowThrow && LT(1) == IToken.t_throw) {
- // Throw expression
- expr= throwExpression();
- lt1= LT(1);
- if (lt1 != IToken.tCOLON && lt1 != IToken.tCOMMA)
- break;
- } else if (allowBraceInitializer && LT(1) == IToken.tLBRACE) {
- // Brace initializer
- expr= bracedInitList(true);
- lt1= LT(1);
- if (lt1 != IToken.tCOLON && lt1 != IToken.tCOMMA)
+ if (failure == null && !doneExpression) {
+ // Determine next cast-expression
+ consume(); // consumes the operator
+ stopWithNextOperator= false;
+ try {
+ if (lt1 == IToken.tQUESTION && LT(1) == IToken.tCOLON) {
+ // Missing sub-expression after '?' (gnu-extension)
+ expr= null;
+ } else if (allowThrow && LT(1) == IToken.t_throw) {
+ // Throw expression
+ expr= throwExpression();
+ lt1= LT(1);
+ if (lt1 != IToken.tCOLON && lt1 != IToken.tCOMMA)
+ stopWithNextOperator= true;
break;
- } else {
- // Cast expression
- IToken m= mark();
- try {
+ } else if (allowBraceInitializer && LT(1) == IToken.tLBRACE) {
+ // Brace initializer
+ expr= bracedInitList(true);
+ lt1= LT(1);
+ if (lt1 != IToken.tCOLON && lt1 != IToken.tCOMMA)
+ stopWithNextOperator= true;
+ } else {
Object e = castExpressionForBinaryExpression(strat);
if (e instanceof IASTExpression) {
expr= (IASTExpression) e;
@@ -948,55 +961,49 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
variants.addBranchPoint(ae.getNext(), lastOperator, allowAssignment, conditionCount);
}
- } catch (BacktrackException e) {
- if (variants == null)
- throw e;
- tryRecovery= e;
- backup(m);
}
+ continue castExprLoop;
+ } catch (BacktrackException e) {
+ failure= e;
}
- }
+ }
- if (tryRecovery != null || doneExpression) {
- if (variants != null) {
- if (lt1 == IToken.tEOC) {
- variants.discardOpenVariants(operatorOffset);
- } else {
- // Try fall-back to an open variant
- Variant fallback= variants.findFallback(operatorOffset);
- if (fallback == null) {
- if (tryRecovery != null)
- throw tryRecovery;
- variants.discardOpenVariants(operatorOffset);
- } else {
- // Restore state and continue
- doneExpression= false;
- BranchPoint varPoint= fallback.getOwner();
- allowAssignment= varPoint.isAllowAssignment();
- conditionCount= varPoint.getConditionCount();
- lastOperator= varPoint.getLeftOperator();
- expr= fallback.getExpression();
- variants.useFallback(fallback);
-
- // Advance to the right token
- int offset= fallback.getRightOffset();
- while (LA().getOffset() < offset) {
- consume();
- }
- }
- }
+ // We need a new variant
+ Variant variant= variants == null ? null : variants.selectFallback();
+ if (variant == null) {
+ if (failure != null)
+ throw failure;
+ throwBacktrack(LA(1));
+ } else {
+ // Restore variant and continue
+ BranchPoint varPoint= variant.getOwner();
+ allowAssignment= varPoint.isAllowAssignment();
+ conditionCount= varPoint.getConditionCount();
+ lastOperator= varPoint.getLeftOperator();
+ expr= variant.getExpression();
+
+ backup(variantMark);
+ int offset= variant.getRightOffset();
+ while (LA().getOffset() < offset) {
+ consume();
}
+ variantMark= mark();
}
- } while (!doneExpression);
+ }
// Check for incomplete conditional expression
if (lt1 != IToken.tEOC && conditionCount > 0)
throwBacktrack(LA(1));
-
- if (variants != null && !variants.isEmpty()) {
- CPPASTTemplateIDAmbiguity result = new CPPASTTemplateIDAmbiguity(this, lastOperator, expr, variants.getOrderedBranchPoints());
- setRange(result, startOffset, calculateEndOffset(expr));
- return result;
+
+ if (variants != null) {
+ BinaryOperator end = new BinaryOperator(lastOperator, expr, -1, 0, 0);
+ variants.closeVariants(LA(1).getOffset(), end);
+ variants.removeInvalid(end);
+ if (!variants.isEmpty()) {
+ CPPASTTemplateIDAmbiguity result = new CPPASTTemplateIDAmbiguity(this, end, variants.getOrderedBranchPoints());
+ setRange(result, startOffset, calculateEndOffset(expr));
+ return result;
+ }
}
return buildExpression(lastOperator, expr);
@@ -1010,7 +1017,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
TemplateIdStrategy strat= new TemplateIdStrategy();
Variant variants= null;
- IASTExpression singleExpression= null;
+ IASTExpression singleResult= null;
IASTName[] firstNames= null;
final IToken mark= mark();
@@ -1019,12 +1026,12 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
try {
IASTExpression e = castExpression(CastExprCtx.eDirectlyInBExpr, strat);
if (variants == null) {
- if (singleExpression == null || lastToken == null) {
- singleExpression= e;
+ if (singleResult == null || lastToken == null) {
+ singleResult= e;
firstNames= strat.getTemplateNames();
} else {
- variants= new Variant(null, singleExpression, firstNames, lastToken.getOffset());
- singleExpression= null;
+ variants= new Variant(null, singleResult, firstNames, lastToken.getOffset());
+ singleResult= null;
firstNames= null;
}
}
@@ -1046,7 +1053,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
}
backup(mark);
}
- return variants != null ? variants : singleExpression;
+ return variants != null ? variants : singleResult;
}
@Override
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/NameOrTemplateIDVariants.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/NameOrTemplateIDVariants.java
index 6bc530b875d..489d610c054 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/NameOrTemplateIDVariants.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/NameOrTemplateIDVariants.java
@@ -13,7 +13,6 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
-import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser.BinaryOperator;
/**
@@ -132,59 +131,31 @@ public class NameOrTemplateIDVariants {
if (v.getTargetOperator() == null) {
if (offset == v.getRightOffset()) {
v.setTargetOperator(lastOperator);
- } else if (offset > v.getRightOffset()) {
- // Should not happen
- assert false;
- remove(v);
- }
+ }
}
}
}
}
- public void discardOpenVariants(int operatorOffset) {
- for (BranchPoint p = fFirst; p != null; p= p.getNext()) {
- for (Variant v= p.getFirstVariant(); v != null; v= v.getNext()) {
- if (v.getTargetOperator() == null && v.getRightOffset() != operatorOffset) {
- remove(v);
- }
- }
- }
- }
-
- public Variant findFallback(int operatorOffset) {
+ public Variant selectFallback() {
// Search for an open variant, with a small right offset and a large left offset
- Variant best= null;
for (BranchPoint p = fFirst; p != null; p= p.getNext()) {
+ Variant best= null;
for (Variant v= p.getFirstVariant(); v != null; v= v.getNext()) {
- if (v.fRightOffset > operatorOffset) {
+ if (v.getTargetOperator() == null) {
if (best == null || v.fRightOffset < best.fRightOffset) {
best= v;
}
}
}
- }
- return best;
- }
-
- public void useFallback(Variant fallback) {
- // Discard variants that end within the fallback
- int begin= ((ASTNode) fallback.getExpression()).getOffset();
- int end= fallback.getRightOffset();
- for (BranchPoint p = fFirst; p != null; p= p.getNext()) {
- for (Variant v= p.getFirstVariant(); v != null; v= v.getNext()) {
- if (v == fallback) {
- remove(v);
- } else {
- int vend= v.getRightOffset();
- if (vend > begin && vend < end)
- remove(v);
- }
+ if (best != null) {
+ remove(best);
+ return best;
}
}
+ return null;
}
-
private void remove(Variant remove) {
final BranchPoint owner = remove.fOwner;
final Variant next = remove.getNext();
@@ -236,4 +207,41 @@ public class NameOrTemplateIDVariants {
fFirst= null;
return prev;
}
+
+ public boolean hasRightBound(int opOffset) {
+ // Search for an open variant, with a small right offset and a large left offset
+ for (BranchPoint p = fFirst; p != null; p= p.getNext()) {
+ for (Variant v= p.getFirstVariant(); v != null; v= v.getNext()) {
+ if (v.fRightOffset > opOffset)
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public void removeInvalid(BinaryOperator lastOperator) {
+ for (BranchPoint p = fFirst; p != null; p= p.getNext()) {
+ if (!isReachable(p, lastOperator)) {
+ remove(p);
+ } else {
+ for (Variant v= p.getFirstVariant(); v != null; v= v.getNext()) {
+ if (v.getTargetOperator() == null) {
+ remove(v);
+ }
+ }
+ }
+ }
+ }
+
+ private boolean isReachable(BranchPoint bp, BinaryOperator endOperator) {
+ BinaryOperator op = bp.getLeftOperator();
+ if (op == null)
+ return true;
+
+ for(; endOperator != null; endOperator= endOperator.getNext()) {
+ if (endOperator == op)
+ return true;
+ }
+ return false;
+ }
}

Back to the top