mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-10 01:35:39 +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:
parent
92c9224591
commit
8649b65570
16 changed files with 472 additions and 25 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue