mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-09 18:56:02 +02:00
Correct parsing of typeof-expressions, bug 226492.
This commit is contained in:
parent
027bd802aa
commit
1e97408e2b
5 changed files with 94 additions and 84 deletions
|
@ -4474,4 +4474,14 @@ public class AST2Tests extends AST2BaseTest {
|
|||
parseAndCheckBindings(code, ParserLanguage.C, true);
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP, true);
|
||||
}
|
||||
|
||||
// void test(int count) {
|
||||
// __typeof__(count) a= 1;
|
||||
// int ret0 = ((__typeof__(count)) 1);
|
||||
// }
|
||||
public void testTypeofExpression_Bug226492() throws Exception {
|
||||
final String code = getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.C, true);
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -852,41 +852,31 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
IASTTypeId d = null;
|
||||
IASTExpression unaryExpression = null;
|
||||
|
||||
IToken m = mark();
|
||||
int lastOffset = 0;
|
||||
if (LT(1) == IToken.tLPAREN) {
|
||||
if (LT(2) == IToken.tLBRACE) {
|
||||
unaryExpression = compoundStatementExpression();
|
||||
lastOffset = calculateEndOffset(unaryExpression);
|
||||
} else {
|
||||
boolean needBack = false;
|
||||
// prefer unary expressions over type-expressions
|
||||
if (LT(1) == IToken.tLPAREN && LT(2) != IToken.tLBRACE) {
|
||||
consume();
|
||||
final IToken m = mark();
|
||||
try {
|
||||
consume(); // tLPAREN
|
||||
unaryExpression= unaryExpression();
|
||||
}
|
||||
catch (BacktrackException e) {
|
||||
backup(m);
|
||||
d = typeId(false);
|
||||
if (d == null)
|
||||
needBack = true;
|
||||
else
|
||||
throw new BacktrackException();
|
||||
}
|
||||
lastOffset = consume(IToken.tRPAREN).getEndOffset();
|
||||
} catch (BacktrackException bt) {
|
||||
needBack = true;
|
||||
}
|
||||
if (needBack) {
|
||||
backup(m);
|
||||
d = null;
|
||||
unaryExpression = unaryExpression();
|
||||
lastOffset = calculateEndOffset(unaryExpression);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unaryExpression = unaryExpression();
|
||||
lastOffset = calculateEndOffset(unaryExpression);
|
||||
}
|
||||
if (d != null & unaryExpression == null)
|
||||
return buildTypeIdExpression(IGNUASTTypeIdExpression.op_typeof, d,
|
||||
offset, lastOffset);
|
||||
else if (unaryExpression != null && d == null)
|
||||
return buildUnaryExpression(IGNUASTUnaryExpression.op_typeof,
|
||||
unaryExpression, offset, lastOffset);
|
||||
if (d != null)
|
||||
return buildTypeIdExpression(IGNUASTTypeIdExpression.op_typeof, d, offset, lastOffset);
|
||||
|
||||
if (unaryExpression != null)
|
||||
return buildUnaryExpression(IGNUASTUnaryExpression.op_typeof, unaryExpression, offset, lastOffset);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -2016,6 +2006,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
|
||||
protected boolean canBeTypeSpecifier() throws EndOfFileException {
|
||||
|
||||
switch (LT(1)) {
|
||||
// simple type specifiers:
|
||||
case IToken.tIDENTIFIER:
|
||||
|
@ -2050,12 +2041,16 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
case IToken.t_const:
|
||||
case IToken.t_volatile:
|
||||
case IToken.t_restrict:
|
||||
return true;
|
||||
|
||||
// gcc-special
|
||||
case IGCCToken.t_typeof:
|
||||
|
||||
// content assist
|
||||
case IToken.tCOMPLETION:
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,12 +32,15 @@ import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
||||
import org.eclipse.cdt.core.dom.ast.IEnumeration;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.c.CASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICScope;
|
||||
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.index.IIndex;
|
||||
import org.eclipse.cdt.core.index.IIndexFileSet;
|
||||
import org.eclipse.cdt.core.index.IndexFilter;
|
||||
|
@ -213,7 +216,18 @@ public class CScope implements ICScope, IASTInternalScope {
|
|||
int type = getNamespaceType( name );
|
||||
Object o = bindings[type].get( name.toCharArray() );
|
||||
|
||||
if( o == null || name == o) {
|
||||
if( o instanceof IBinding )
|
||||
return (IBinding) o;
|
||||
|
||||
if (o != null && o != name) {
|
||||
IASTName foundName= (IASTName) o;
|
||||
if( (resolve || foundName.getBinding() != null) && ( foundName != name ) ) {
|
||||
if(!isTypeDefinition(name) || CVisitor.declaredBefore(foundName, name)) {
|
||||
return foundName.resolveBinding();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IBinding result= null;
|
||||
if(physicalNode instanceof IASTTranslationUnit) {
|
||||
final IASTTranslationUnit tu = (IASTTranslationUnit)physicalNode;
|
||||
|
@ -233,22 +247,23 @@ public class CScope implements ICScope, IASTInternalScope {
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
if( o instanceof IBinding )
|
||||
return (IBinding) o;
|
||||
|
||||
IASTName foundName= (IASTName) o;
|
||||
if( (resolve || foundName.getBinding() != null) && ( foundName != name ) ) {
|
||||
if(!isTypeDefinition(name) || CVisitor.declaredBefore(foundName, name)) {
|
||||
return foundName.resolveBinding();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isTypeDefinition(IASTName name) {
|
||||
return name.getPropertyInParent()==IASTNamedTypeSpecifier.NAME;
|
||||
if (name.getPropertyInParent()==IASTNamedTypeSpecifier.NAME) {
|
||||
return true;
|
||||
}
|
||||
IASTNode parent= name.getParent();
|
||||
while (parent != null) {
|
||||
if (parent instanceof IASTUnaryExpression) {
|
||||
if (((IASTUnaryExpression) parent).getOperator() == IGNUASTUnaryExpression.op_typeof)
|
||||
return true;
|
||||
}
|
||||
else if (parent instanceof IASTTypeIdExpression) {
|
||||
if (((IASTTypeIdExpression) parent).getOperator() == IASTTypeIdExpression.op_typeof)
|
||||
return true;
|
||||
}
|
||||
parent= parent.getParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -259,17 +274,17 @@ public class CScope implements ICScope, IASTInternalScope {
|
|||
|
||||
Object[] obj = null;
|
||||
|
||||
for (int i = 0; i < bindings.length; i++) {
|
||||
for (CharArrayObjectMap binding : bindings) {
|
||||
if (prefixLookup) {
|
||||
Object[] keys = bindings[i].keyArray();
|
||||
for (int j = 0; j < keys.length; j++) {
|
||||
char[] key = (char[]) keys[j];
|
||||
Object[] keys = binding.keyArray();
|
||||
for (Object key2 : keys) {
|
||||
char[] key = (char[]) key2;
|
||||
if (CharArrayUtils.equals(key, 0, c.length, c, true)) {
|
||||
obj = ArrayUtil.append(obj, bindings[i].get(key));
|
||||
obj = ArrayUtil.append(obj, binding.get(key));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
obj = ArrayUtil.append(obj, bindings[i].get(c));
|
||||
obj = ArrayUtil.append(obj, binding.get(c));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,12 +309,12 @@ public class CScope implements ICScope, IASTInternalScope {
|
|||
obj = ArrayUtil.trim(Object.class, obj);
|
||||
IBinding[] result = null;
|
||||
|
||||
for (int i = 0; i < obj.length; i++) {
|
||||
if( obj[i] instanceof IBinding )
|
||||
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, obj[i]);
|
||||
for (Object element : obj) {
|
||||
if( element instanceof IBinding )
|
||||
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, element);
|
||||
|
||||
if( (resolve || ((IASTName)obj[i]).getBinding() != null) && ( obj[i] != name ) )
|
||||
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, ((IASTName)obj[i]).resolveBinding());
|
||||
if( (resolve || ((IASTName)element).getBinding() != null) && ( element != name ) )
|
||||
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, ((IASTName)element).resolveBinding());
|
||||
}
|
||||
|
||||
return (IBinding[]) ArrayUtil.trim(IBinding.class, result);
|
||||
|
|
|
@ -1024,23 +1024,13 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
declSpecifier = declSpecifierSeq(false, true);
|
||||
} catch (FoundDeclaratorException e) {
|
||||
return null;
|
||||
// backup(mark);
|
||||
// throwBacktrack( e.currToken );
|
||||
}
|
||||
declarator = declarator();
|
||||
} catch (BacktrackException bt) {
|
||||
return null;
|
||||
// backup(mark);
|
||||
// throwBacktrack(bt);
|
||||
}
|
||||
if (declarator == null || declarator.getName().toCharArray().length > 0)
|
||||
{
|
||||
return null;
|
||||
// backup(mark);
|
||||
// throwBacktrack(startingOffset, figureEndOffset(declSpecifier,
|
||||
// declarator)
|
||||
// - startingOffset);
|
||||
}
|
||||
|
||||
IASTTypeId result = createTypeId();
|
||||
((ASTNode) result).setOffsetAndLength(startingOffset, figureEndOffset(
|
||||
|
|
Loading…
Add table
Reference in a new issue