1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-12 10:45:37 +02:00

Bug 84144 - [Parser2] GCC: labels as values

Add support for GNU goto label references.

"http://gcc.gnu.org/onlinedocs/gcc-3.3.2/gcc/Labels-as-Values.html#Labels%20as%20Values
GCC extensions to C allow taking the address of labels. These addresses can be used in a goto statement where any expression of type void * is allowed:

foo:
  void* labelPtr = &&foo;
  goto *labelPtr;", comment from Andrew Niefer

Add new classes and necessary changes in existing classes to support the above.

Change-Id: I60b64957af3fdfd5463e89c2a36eea13bd280887
Signed-off-by: qdagans <anders.xb.dahlberg@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/28826
Tested-by: Hudson CI
Reviewed-by: Elena Laskavaia <elaskavaia.cdt@gmail.com>
This commit is contained in:
qdagans 2014-06-20 03:09:30 +02:00 committed by Elena Laskavaia
parent 92c9224591
commit 8649b65570
16 changed files with 472 additions and 25 deletions

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2013 IBM Corporation and others.
* Copyright (c) 2005, 2014 IBM Corporation and others.
* 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
@ -10,6 +10,7 @@
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
* Nathan Ridge
* Anders Dahlberg (Ericsson) - bug 84144
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.ast2;
@ -1010,6 +1011,19 @@ public class AST2CPPSpecTest extends AST2SpecTestBase {
parse(getAboveComment(), ParserLanguage.CPP, true, 1);
}
// void f()
// {
// // ...
// void* labelPtr;
// labelPtr = &&foo;
// goto *labelPtr;
// foo:
// return;
// }
public void test6_bug84144() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// int foo(int i)
// {
// static int s = foo(2*i); // recursive call - undefined

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2009 IBM Corporation and others.
* Copyright (c) 2005, 2014 IBM Corporation and others.
* 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
@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anders Dahlberg (Ericsson) - bug 84144
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.ast2;
@ -1728,6 +1729,19 @@ public class AST2CSpecTest extends AST2SpecTestBase {
parseCandCPP(buffer.toString(), false, 0);
}
// void f()
// {
// // ...
// void* labelPtr;
// labelPtr = &&foo;
// goto *labelPtr;
// foo:
// return;
// }
public void test6_bug84144() throws Exception {
parseCandCPP(getAboveComment(), true, 0);
}
/**
[--Start Example(C 6.8.6.4-4):
struct s { double i; } f(void);

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2011 IBM Corporation and others.
* Copyright (c) 2004, 2014 IBM Corporation and others.
* 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
@ -7,6 +7,7 @@
*
* Contributors:
* John Camelon (IBM Rational Software) - Initial API and implementation
* Anders Dahlberg (Ericsson) - bug 84144
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast;
@ -104,24 +105,30 @@ public interface IASTUnaryExpression extends IASTExpression {
*/
@Deprecated
public static final int op_typeof = 14;
/**
* For GCC parsers, only. {@code op_labelReference} is used for &&label type
* expressions.
*/
public static final int op_labelReference = 15;
/**
* For GCC parsers, only. {@code op_alignOf} is used for __alignOf( unaryExpression ) type
* expressions.
*/
public static final int op_alignOf = 15;
public static final int op_alignOf = 16;
/**
* For C++, only: 'sizeof... ( parameterPack )'
* @since 5.2
*/
public static final int op_sizeofParameterPack = 16;
public static final int op_sizeofParameterPack = 17;
/**
* For C++, only: noexcept ( expression )
* @since 5.5
*/
public static final int op_noexcept = 17;
public static final int op_noexcept = 18;
/**
* {@code op_last} is made available for subclasses.

View file

@ -10,6 +10,7 @@
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
* Thoams Corbat (IFS)
* Anders Dahlberg (Ericsson) - bug 84144
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast;
@ -120,7 +121,9 @@ public interface INodeFactory {
public IGNUASTCompoundStatementExpression newGNUCompoundStatementExpression(IASTCompoundStatement compoundStatement);
public IASTGotoStatement newGotoStatement(IASTName name);
public IASTStatement newGotoStatement(IASTName name);
public IASTStatement newGotoStatement(IASTExpression expression);
public IASTIdExpression newIdExpression(IASTName name);

View file

@ -0,0 +1,61 @@
/*******************************************************************************
* Copyright (c) 2014 Ericsson
* 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
*
* Contributors:
* Anders Dahlberg (Ericsson) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast.gnu;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
/**
* Represents a GNU goto expression.
*
* <code>
* foo:
* void *labelPtr = &&foo;
* goto *labelPtr;
* </code>
*
* @since 8.4
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface IGNUASTGotoStatement extends IASTStatement, IASTNameOwner {
public static final ASTNodeProperty LABEL_NAME =
new ASTNodeProperty("IASTGotoExpression.LABEL_NAME [IASTExpression]"); //$NON-NLS-1$
/**
* Returns the label-name expression. The expression resolves to a ILabel binding.
*
* @return <code>IASTExpression</code>
*/
public IASTExpression getLabelNameExpression();
/**
* Set the label-name expression.
*
* @param expression
* <code>IASTExpression</code>
*/
public void setLabelNameExpression(IASTExpression expression);
/**
* @since 5.1
*/
@Override
public IGNUASTGotoStatement copy();
/**
* @since 5.3
*/
@Override
public IGNUASTGotoStatement copy(CopyStyle style);
}

View file

@ -12,6 +12,7 @@
* Mike Kucera (IBM) - bug #206952
* Sergey Prigogin (Google)
* Thomas Corbat (IFS)
* Anders Dahlberg (Ericsson) - bug 84144
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser;
@ -23,6 +24,7 @@ import org.eclipse.cdt.core.dom.ast.ASTGenericVisitor;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTASMDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTAttribute;
import org.eclipse.cdt.core.dom.ast.IASTAttributeOwner;
import org.eclipse.cdt.core.dom.ast.IASTAttributeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTBreakStatement;
@ -43,7 +45,6 @@ import org.eclipse.cdt.core.dom.ast.IASTDoStatement;
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.IASTAttributeOwner;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
@ -51,7 +52,6 @@ import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTGotoStatement;
import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
@ -112,7 +112,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
}
}
protected static class Decl extends Exception {
protected static class Decl {
public Decl() {
}
@ -1991,10 +1991,18 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
protected IASTStatement parseGotoStatement() throws EndOfFileException, BacktrackException {
int startOffset = consume().getOffset(); // t_goto
IASTName goto_label_name = identifier();
IASTStatement goto_statement = null;
if (LT(1) == IToken.tSTAR)
{
IASTExpression goto_label_name_expression = expression();
goto_statement = nodeFactory.newGotoStatement(goto_label_name_expression);
} else {
IASTName goto_label_name = identifier();
goto_statement = nodeFactory.newGotoStatement(goto_label_name);
}
int lastOffset = consume(IToken.tSEMI).getEndOffset();
IASTGotoStatement goto_statement = nodeFactory.newGotoStatement(goto_label_name);
((ASTNode) goto_statement).setOffsetAndLength(startOffset, lastOffset - startOffset);
return goto_statement;
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* Copyright (c) 2004, 2014 IBM Corporation and others.
* 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
@ -8,6 +8,7 @@
* Contributors:
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Anders Dahlberg (Ericsson) - bug 84144, indexer optimization
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser;
@ -18,6 +19,8 @@ import org.eclipse.cdt.core.dom.ast.IASTProblem;
* @author jcamelon
*/
public class BacktrackException extends Exception {
private static final StackTraceElement[] EMPTY_STACK = new StackTraceElement[0];
private IASTProblem problem;
private IASTNode nodeBeforeProblem; // a node has been created in spite of the problem.
private int offset, length;
@ -82,4 +85,15 @@ public class BacktrackException extends Exception {
public int getOffset() {
return offset;
}
@Override
public Throwable fillInStackTrace() {
// Do nothing, performance optimization
return this;
}
@Override
public StackTraceElement[] getStackTrace() {
return EMPTY_STACK;
}
}

View file

@ -9,6 +9,7 @@
* Mike Kucera (IBM Corporation) - initial API and implementation
* Markus Schorn (Wind River Systems)
* Thomas Corbat (IFS)
* Anders Dahlberg (Ericsson) - bug 84144
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.c;
@ -40,7 +41,6 @@ import org.eclipse.cdt.core.dom.ast.IASTForStatement;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTGotoStatement;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
@ -298,10 +298,15 @@ public class CNodeFactory extends NodeFactory implements ICNodeFactory {
}
@Override
public IASTGotoStatement newGotoStatement(IASTName name) {
public IASTStatement newGotoStatement(IASTName name) {
return new CASTGotoStatement(name);
}
@Override
public IASTStatement newGotoStatement(IASTExpression expression) {
return new GNUCASTGotoStatement(expression);
}
@Override
public IASTIdExpression newIdExpression(IASTName name) {
return new CASTIdExpression(name);

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2013 IBM Corporation and others.
* Copyright (c) 2005, 2014 IBM Corporation and others.
* 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
@ -13,6 +13,7 @@
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
* Sergey Prigogin (Google)
* Marc-Andre Laperle (Ericsson)
* Anders Dahlberg (Ericsson) - bug 84144
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.c;
@ -57,6 +58,7 @@ import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IArrayType;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
@ -104,6 +106,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.ProblemType;
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPLabel;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
import org.eclipse.cdt.internal.core.parser.util.ContentAssistMatcherFactory;
@ -455,7 +458,17 @@ public class CVisitor extends ASTQueries {
IBinding binding = null;
IASTNode parent = name.getParent();
if (parent instanceof CASTIdExpression) {
// GNU Goto label reference
//
// void* labelPtr = &&foo; <-- label reference
// foo:
//
boolean labelReference = isLabelReference(parent);
if (labelReference) {
IASTUnaryExpression expression = (IASTUnaryExpression) parent.getParent();
binding = createLabelReferenceBinding(name, expression);
} else if (parent instanceof CASTIdExpression) {
binding = resolveBinding(parent);
} else if (parent instanceof ICASTTypedefNameSpecifier) {
binding = resolveBinding(parent);
@ -596,6 +609,56 @@ public class CVisitor extends ASTQueries {
return null;
}
private static boolean isLabelReference(IASTNode node) {
boolean labelReference = false;
IASTNode parent = node.getParent();
if (parent instanceof IASTUnaryExpression) {
int operator = ((IASTUnaryExpression) parent).getOperator();
labelReference = operator == IASTUnaryExpression.op_labelReference;
}
return labelReference;
}
private static IBinding createLabelReferenceBinding(IASTName name, IASTUnaryExpression expression) {
IBinding binding = null;
// Find function scope for r-value expression
// void* labelPtr = &&foo;
// foo: ^^^
// return
IScope scope = getContainingScope(name);
IASTInternalScope s = (IASTInternalScope) scope;
IASTNode node = s.getPhysicalNode();
while (node != null && !(node instanceof IASTFunctionDefinition)) {
node = node.getParent();
}
if (node != null) {
IASTFunctionDefinition definition = (IASTFunctionDefinition) node;
CASTFunctionDeclarator declarator = (CASTFunctionDeclarator) definition.getDeclarator();
scope = declarator.getFunctionScope();
if (scope != null) {
binding = scope.getBinding(name, false);
if (!(binding instanceof ILabel)) {
binding = new CPPLabel(name);
ASTInternal.addName(scope, name);
}
}
}
if (binding == null) {
binding = new ProblemBinding(expression, IProblemBinding.SEMANTIC_BAD_SCOPE,
expression.getRawSignature().toCharArray());
}
return binding;
}
/**
* if prefix == false, return an IBinding or null
* if prefix == true, return an IBinding[] or null

View file

@ -0,0 +1,91 @@
/*******************************************************************************
* Copyright (c) 2014 Ericsson.
* 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
*
* Contributors:
* Anders Dahlberg (Ericsson) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.c;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTGotoStatement;
import org.eclipse.cdt.internal.core.dom.parser.ASTAttributeOwner;
/**
* GNU C goto statement.
*
* <code>
* foo:
* void *labelPtr = &&foo;
* goto *labelPtr; // this is the statement
* </code>
* @since 8.4
*/
public class GNUCASTGotoStatement extends ASTAttributeOwner
implements IGNUASTGotoStatement {
private IASTExpression fExpression;
public GNUCASTGotoStatement() {
}
public GNUCASTGotoStatement(IASTExpression expression) {
setLabelNameExpression(expression);
}
@Override
public GNUCASTGotoStatement copy() {
return copy(CopyStyle.withoutLocations);
}
@Override
public GNUCASTGotoStatement copy(CopyStyle style) {
GNUCASTGotoStatement copy = new GNUCASTGotoStatement();
copy.setLabelNameExpression(fExpression == null ? null : fExpression.copy(style));
return copy(copy, style);
}
@Override
public boolean accept(ASTVisitor action) {
if (action.shouldVisitExpressions) {
switch (action.visit(this)) {
case ASTVisitor.PROCESS_ABORT: return false;
case ASTVisitor.PROCESS_SKIP: return true;
default: break;
}
}
if (fExpression != null && !fExpression.accept(action))
return false;
if (action.shouldVisitExpressions && action.leave(this) == ASTVisitor.PROCESS_ABORT)
return false;
return true;
}
@Override
public IASTExpression getLabelNameExpression() {
return fExpression;
}
@Override
public void setLabelNameExpression(IASTExpression expression) {
assertNotFrozen();
this.fExpression = expression;
if (expression != null) {
expression.setParent(this);
expression.setPropertyInParent(LABEL_NAME);
}
}
@Override
public int getRoleForName(IASTName n) {
return r_unclear;
}
}

View file

@ -12,6 +12,7 @@
* Mike Kucera (IBM) - bug #206952
* Sergey Prigogin (Google)
* Thomas Corbat (IFS)
* Anders Dahlberg (Ericsson) - bug 84144
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.c;
@ -594,6 +595,8 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
return unaryExpression(IASTUnaryExpression.op_star, ctx, strat);
case IToken.tAMPER:
return unaryExpression(IASTUnaryExpression.op_amper, ctx, strat);
case IToken.tAND:
return unaryExpression(IASTUnaryExpression.op_labelReference, ctx, strat);
case IToken.tPLUS:
return unaryExpression(IASTUnaryExpression.op_plus, ctx, strat);
case IToken.tMINUS:

View file

@ -9,6 +9,7 @@
* Mike Kucera (IBM) - initial API and implementation
* Markus Schorn (Wind River Systems)
* Thomas Corbat (IFS)
* Anders Dahlberg (Ericsson) - bug 84144
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -31,7 +32,6 @@ import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTGotoStatement;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
@ -430,10 +430,15 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory {
}
@Override
public IASTGotoStatement newGotoStatement(IASTName name) {
public IASTStatement newGotoStatement(IASTName name) {
return new CPPASTGotoStatement(name);
}
@Override
public IASTStatement newGotoStatement(IASTExpression expression) {
return new GNUCPPASTGotoStatement(expression);
}
@Override
public IASTIdExpression newIdExpression(IASTName name) {
return new CPPASTIdExpression(name);

View file

@ -0,0 +1,94 @@
/*******************************************************************************
* Copyright (c) 2014 Ericsson.
* 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
*
* Contributors:
* Anders Dahlberg (Ericsson) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTGotoStatement;
import org.eclipse.cdt.internal.core.dom.parser.ASTAttributeOwner;
/**
* GNU C++ goto statement.
*
* <code>
* foo:
* void *labelPtr = &&foo;
* goto *labelPtr; // this is the statement
* </code>
*
* @since 8.4
*/
public class GNUCPPASTGotoStatement extends ASTAttributeOwner implements IGNUASTGotoStatement {
private IASTExpression expression;
public GNUCPPASTGotoStatement() {
}
public GNUCPPASTGotoStatement(IASTExpression expression) {
setLabelNameExpression(expression);
}
@Override
public GNUCPPASTGotoStatement copy() {
return copy(CopyStyle.withoutLocations);
}
@Override
public GNUCPPASTGotoStatement copy(CopyStyle style) {
GNUCPPASTGotoStatement copy = new GNUCPPASTGotoStatement(expression == null ? null : expression.copy(style));
return copy(copy, style);
}
@Override
public boolean accept(ASTVisitor action) {
if (action.shouldVisitStatements) {
switch (action.visit(this)) {
case ASTVisitor.PROCESS_ABORT : return false;
case ASTVisitor.PROCESS_SKIP : return true;
default : break;
}
}
if (!acceptByAttributeSpecifiers(action)) return false;
if (expression != null && !expression.accept(action)) return false;
if (action.shouldVisitStatements) {
switch (action.leave(this)) {
case ASTVisitor.PROCESS_ABORT : return false;
case ASTVisitor.PROCESS_SKIP : return true;
default : break;
}
}
return true;
}
@Override
public IASTExpression getLabelNameExpression() {
return expression;
}
@Override
public void setLabelNameExpression(IASTExpression expression) {
assertNotFrozen();
this.expression = expression;
if (expression != null) {
expression.setParent(this);
expression.setPropertyInParent(LABEL_NAME);
}
}
@Override
public int getRoleForName(IASTName n) {
return r_unclear;
}
}

View file

@ -14,6 +14,7 @@
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
* Thomas Corbat (IFS)
* Anders Dahlberg (Ericsson) - bug 84144
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -1327,6 +1328,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return unaryExpression(IASTUnaryExpression.op_star, ctx, strat);
case IToken.tAMPER:
return unaryExpression(IASTUnaryExpression.op_amper, ctx, strat);
case IToken.tAND:
return unaryExpression(IASTUnaryExpression.op_labelReference, ctx, strat);
case IToken.tPLUS:
return unaryExpression(IASTUnaryExpression.op_plus, ctx, strat);
case IToken.tMINUS:

View file

@ -13,6 +13,7 @@
* Thomas Corbat (IFS)
* Nathan Ridge
* Marc-Andre Laperle
* Anders Dahlberg (Ericsson) - bug 84144
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
@ -178,6 +179,7 @@ import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFunctionCallExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFunctionDeclarator;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
@ -299,7 +301,18 @@ public class CPPVisitor extends ASTQueries {
id.resolveBinding();
return name.getBinding();
}
if (parent instanceof IASTIdExpression) {
// GNU Goto label reference
//
// void* labelPtr = &&foo; <-- label reference
// foo:
//
boolean labelReference = isLabelReference(parent);
if (labelReference) {
IASTUnaryExpression expression = (IASTUnaryExpression) parent.getParent();
return createLabelReferenceBinding(name, expression);
} else if (parent instanceof IASTIdExpression) {
return resolveBinding(parent);
} else if (parent instanceof ICPPASTFieldReference) {
return resolveBinding(parent);
@ -376,6 +389,55 @@ public class CPPVisitor extends ASTQueries {
return scope == inScope;
}
private static boolean isLabelReference(IASTNode node) {
boolean labelReference = false;
IASTNode parent = node.getParent();
if (parent instanceof IASTUnaryExpression) {
int operator = ((IASTUnaryExpression) parent).getOperator();
labelReference = operator == IASTUnaryExpression.op_labelReference;
}
return labelReference;
}
private static IBinding createLabelReferenceBinding(IASTName name, IASTUnaryExpression expression) {
IBinding binding = null;
// Find function scope for r-value expression
// void* labelPtr = &&foo;
// foo: ^^^
// return
IScope scope = getContainingScope(name);
IASTInternalScope s = (IASTInternalScope) scope;
IASTNode node = s.getPhysicalNode();
while (node != null && !(node instanceof IASTFunctionDefinition)) {
node = node.getParent();
}
if (node != null) {
IASTFunctionDefinition definition = (IASTFunctionDefinition) node;
CPPASTFunctionDeclarator declarator = (CPPASTFunctionDeclarator) definition.getDeclarator();
scope = declarator.getFunctionScope();
if (scope != null) {
binding = scope.getBinding(name, false);
if (!(binding instanceof ILabel)) {
binding = new CPPLabel(name);
ASTInternal.addName(scope, name);
}
}
}
if (binding == null) {
binding = new CPPScope.CPPScopeProblem(expression, IProblemBinding.SEMANTIC_BAD_SCOPE,
expression.getRawSignature().toCharArray());
}
return binding;
}
private static IBinding createBinding(IASTGotoStatement gotoStatement) {
IASTName name = gotoStatement.getName();
ICPPFunctionScope functionScope = (ICPPFunctionScope) getContainingScope(name);

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 IBM Corporation and others.
* Copyright (c) 2006, 2014 IBM Corporation and others.
* 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
@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anders Dahlberg (Ericsson) - bug 84144
*******************************************************************************/
package org.eclipse.cdt.core.dom.lrparser.action;
@ -44,7 +45,6 @@ import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
import org.eclipse.cdt.core.dom.ast.IASTFieldDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTGotoStatement;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
@ -598,7 +598,7 @@ public abstract class BuildASTParserAction extends AbstractParserAction {
*/
public void consumeStatementGoto() {
IASTName name = createName(stream.getRuleTokens().get(1));
IASTGotoStatement gotoStat = nodeFactory.newGotoStatement(name);
IASTStatement gotoStat = nodeFactory.newGotoStatement(name);
setOffsetAndLength(gotoStat);
astStack.push(gotoStat);
}