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.C, true);
|
||||||
parseAndCheckBindings(code, ParserLanguage.CPP, 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;
|
IASTTypeId d = null;
|
||||||
IASTExpression unaryExpression = null;
|
IASTExpression unaryExpression = null;
|
||||||
|
|
||||||
IToken m = mark();
|
|
||||||
int lastOffset = 0;
|
int lastOffset = 0;
|
||||||
if (LT(1) == IToken.tLPAREN) {
|
// prefer unary expressions over type-expressions
|
||||||
if (LT(2) == IToken.tLBRACE) {
|
if (LT(1) == IToken.tLPAREN && LT(2) != IToken.tLBRACE) {
|
||||||
unaryExpression = compoundStatementExpression();
|
consume();
|
||||||
lastOffset = calculateEndOffset(unaryExpression);
|
final IToken m = mark();
|
||||||
} else {
|
try {
|
||||||
boolean needBack = false;
|
unaryExpression= unaryExpression();
|
||||||
try {
|
}
|
||||||
consume(); // tLPAREN
|
catch (BacktrackException e) {
|
||||||
d = typeId(false);
|
backup(m);
|
||||||
if (d == null)
|
d = typeId(false);
|
||||||
needBack = true;
|
if (d == null)
|
||||||
else
|
throw new BacktrackException();
|
||||||
lastOffset = consume(IToken.tRPAREN).getEndOffset();
|
}
|
||||||
} catch (BacktrackException bt) {
|
lastOffset = consume(IToken.tRPAREN).getEndOffset();
|
||||||
needBack = true;
|
|
||||||
}
|
|
||||||
if (needBack) {
|
|
||||||
backup(m);
|
|
||||||
d = null;
|
|
||||||
unaryExpression = unaryExpression();
|
|
||||||
lastOffset = calculateEndOffset(unaryExpression);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
unaryExpression = unaryExpression();
|
unaryExpression = unaryExpression();
|
||||||
lastOffset = calculateEndOffset(unaryExpression);
|
lastOffset = calculateEndOffset(unaryExpression);
|
||||||
}
|
}
|
||||||
if (d != null & unaryExpression == null)
|
if (d != null)
|
||||||
return buildTypeIdExpression(IGNUASTTypeIdExpression.op_typeof, d,
|
return buildTypeIdExpression(IGNUASTTypeIdExpression.op_typeof, d, offset, lastOffset);
|
||||||
offset, lastOffset);
|
|
||||||
else if (unaryExpression != null && d == null)
|
if (unaryExpression != null)
|
||||||
return buildUnaryExpression(IGNUASTUnaryExpression.op_typeof,
|
return buildUnaryExpression(IGNUASTUnaryExpression.op_typeof, unaryExpression, offset, lastOffset);
|
||||||
unaryExpression, offset, lastOffset);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2016,6 +2006,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean canBeTypeSpecifier() throws EndOfFileException {
|
protected boolean canBeTypeSpecifier() throws EndOfFileException {
|
||||||
|
|
||||||
switch (LT(1)) {
|
switch (LT(1)) {
|
||||||
// simple type specifiers:
|
// simple type specifiers:
|
||||||
case IToken.tIDENTIFIER:
|
case IToken.tIDENTIFIER:
|
||||||
|
@ -2050,12 +2041,16 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
case IToken.t_const:
|
case IToken.t_const:
|
||||||
case IToken.t_volatile:
|
case IToken.t_volatile:
|
||||||
case IToken.t_restrict:
|
case IToken.t_restrict:
|
||||||
return true;
|
|
||||||
|
// gcc-special
|
||||||
|
case IGCCToken.t_typeof:
|
||||||
|
|
||||||
|
// content assist
|
||||||
case IToken.tCOMPLETION:
|
case IToken.tCOMPLETION:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
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.IASTNode;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
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.IBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IEnumeration;
|
import org.eclipse.cdt.core.dom.ast.IEnumeration;
|
||||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
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.CASTVisitor;
|
||||||
import org.eclipse.cdt.core.dom.ast.c.ICScope;
|
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.IIndex;
|
||||||
import org.eclipse.cdt.core.index.IIndexFileSet;
|
import org.eclipse.cdt.core.index.IIndexFileSet;
|
||||||
import org.eclipse.cdt.core.index.IndexFilter;
|
import org.eclipse.cdt.core.index.IndexFilter;
|
||||||
|
@ -213,42 +216,54 @@ public class CScope implements ICScope, IASTInternalScope {
|
||||||
int type = getNamespaceType( name );
|
int type = getNamespaceType( name );
|
||||||
Object o = bindings[type].get( name.toCharArray() );
|
Object o = bindings[type].get( name.toCharArray() );
|
||||||
|
|
||||||
if( o == null || name == o) {
|
|
||||||
IBinding result= null;
|
|
||||||
if(physicalNode instanceof IASTTranslationUnit) {
|
|
||||||
final IASTTranslationUnit tu = (IASTTranslationUnit)physicalNode;
|
|
||||||
IIndex index= tu.getIndex();
|
|
||||||
if(index!=null) {
|
|
||||||
try {
|
|
||||||
IBinding[] bindings= index.findBindings(name.toCharArray(), INDEX_FILTERS[type], new NullProgressMonitor());
|
|
||||||
if (fileSet != null) {
|
|
||||||
bindings= fileSet.filterFileLocalBindings(bindings);
|
|
||||||
}
|
|
||||||
result= processIndexResults(name, bindings);
|
|
||||||
} catch(CoreException ce) {
|
|
||||||
CCorePlugin.log(ce);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if( o instanceof IBinding )
|
if( o instanceof IBinding )
|
||||||
return (IBinding) o;
|
return (IBinding) o;
|
||||||
|
|
||||||
IASTName foundName= (IASTName) o;
|
if (o != null && o != name) {
|
||||||
if( (resolve || foundName.getBinding() != null) && ( foundName != name ) ) {
|
IASTName foundName= (IASTName) o;
|
||||||
if(!isTypeDefinition(name) || CVisitor.declaredBefore(foundName, name)) {
|
if( (resolve || foundName.getBinding() != null) && ( foundName != name ) ) {
|
||||||
return foundName.resolveBinding();
|
if(!isTypeDefinition(name) || CVisitor.declaredBefore(foundName, name)) {
|
||||||
|
return foundName.resolveBinding();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
IBinding result= null;
|
||||||
|
if(physicalNode instanceof IASTTranslationUnit) {
|
||||||
|
final IASTTranslationUnit tu = (IASTTranslationUnit)physicalNode;
|
||||||
|
IIndex index= tu.getIndex();
|
||||||
|
if(index!=null) {
|
||||||
|
try {
|
||||||
|
IBinding[] bindings= index.findBindings(name.toCharArray(), INDEX_FILTERS[type], new NullProgressMonitor());
|
||||||
|
if (fileSet != null) {
|
||||||
|
bindings= fileSet.filterFileLocalBindings(bindings);
|
||||||
|
}
|
||||||
|
result= processIndexResults(name, bindings);
|
||||||
|
} catch(CoreException ce) {
|
||||||
|
CCorePlugin.log(ce);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTypeDefinition(IASTName name) {
|
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)
|
/* (non-Javadoc)
|
||||||
|
@ -259,17 +274,17 @@ public class CScope implements ICScope, IASTInternalScope {
|
||||||
|
|
||||||
Object[] obj = null;
|
Object[] obj = null;
|
||||||
|
|
||||||
for (int i = 0; i < bindings.length; i++) {
|
for (CharArrayObjectMap binding : bindings) {
|
||||||
if (prefixLookup) {
|
if (prefixLookup) {
|
||||||
Object[] keys = bindings[i].keyArray();
|
Object[] keys = binding.keyArray();
|
||||||
for (int j = 0; j < keys.length; j++) {
|
for (Object key2 : keys) {
|
||||||
char[] key = (char[]) keys[j];
|
char[] key = (char[]) key2;
|
||||||
if (CharArrayUtils.equals(key, 0, c.length, c, true)) {
|
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 {
|
} 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);
|
obj = ArrayUtil.trim(Object.class, obj);
|
||||||
IBinding[] result = null;
|
IBinding[] result = null;
|
||||||
|
|
||||||
for (int i = 0; i < obj.length; i++) {
|
for (Object element : obj) {
|
||||||
if( obj[i] instanceof IBinding )
|
if( element instanceof IBinding )
|
||||||
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, obj[i]);
|
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, element);
|
||||||
|
|
||||||
if( (resolve || ((IASTName)obj[i]).getBinding() != null) && ( obj[i] != name ) )
|
if( (resolve || ((IASTName)element).getBinding() != null) && ( element != name ) )
|
||||||
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, ((IASTName)obj[i]).resolveBinding());
|
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, ((IASTName)element).resolveBinding());
|
||||||
}
|
}
|
||||||
|
|
||||||
return (IBinding[]) ArrayUtil.trim(IBinding.class, result);
|
return (IBinding[]) ArrayUtil.trim(IBinding.class, result);
|
||||||
|
|
|
@ -1234,7 +1234,7 @@ public class CVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean prefix = ( bits & PREFIX_LOOKUP ) != 0;
|
boolean prefix = ( bits & PREFIX_LOOKUP ) != 0;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Object binding = prefix ? new ObjectSet( 2 ) : null;
|
Object binding = prefix ? new ObjectSet( 2 ) : null;
|
||||||
|
|
|
@ -1024,23 +1024,13 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
declSpecifier = declSpecifierSeq(false, true);
|
declSpecifier = declSpecifierSeq(false, true);
|
||||||
} catch (FoundDeclaratorException e) {
|
} catch (FoundDeclaratorException e) {
|
||||||
return null;
|
return null;
|
||||||
// backup(mark);
|
|
||||||
// throwBacktrack( e.currToken );
|
|
||||||
}
|
}
|
||||||
declarator = declarator();
|
declarator = declarator();
|
||||||
} catch (BacktrackException bt) {
|
} catch (BacktrackException bt) {
|
||||||
return null;
|
return null;
|
||||||
// backup(mark);
|
|
||||||
// throwBacktrack(bt);
|
|
||||||
}
|
}
|
||||||
if (declarator == null || declarator.getName().toCharArray().length > 0)
|
if (declarator == null || declarator.getName().toCharArray().length > 0)
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
// backup(mark);
|
|
||||||
// throwBacktrack(startingOffset, figureEndOffset(declSpecifier,
|
|
||||||
// declarator)
|
|
||||||
// - startingOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
IASTTypeId result = createTypeId();
|
IASTTypeId result = createTypeId();
|
||||||
((ASTNode) result).setOffsetAndLength(startingOffset, figureEndOffset(
|
((ASTNode) result).setOffsetAndLength(startingOffset, figureEndOffset(
|
||||||
|
|
Loading…
Add table
Reference in a new issue