diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java index 0a81ee31c95..2cbcdb50f4f 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java @@ -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); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index c2a5370f662..3b6669f02ac 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -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; - try { - consume(); // tLPAREN - d = typeId(false); - if (d == null) - needBack = true; - else - lastOffset = consume(IToken.tRPAREN).getEndOffset(); - } catch (BacktrackException bt) { - needBack = true; - } - if (needBack) { - backup(m); - d = null; - unaryExpression = unaryExpression(); - lastOffset = calculateEndOffset(unaryExpression); - } - } + // prefer unary expressions over type-expressions + if (LT(1) == IToken.tLPAREN && LT(2) != IToken.tLBRACE) { + consume(); + final IToken m = mark(); + try { + unaryExpression= unaryExpression(); + } + catch (BacktrackException e) { + backup(m); + d = typeId(false); + if (d == null) + throw new BacktrackException(); + } + lastOffset = consume(IToken.tRPAREN).getEndOffset(); } 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; } - - return false; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CScope.java index 1648add2bea..9023aaa9a7b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CScope.java @@ -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,42 +216,54 @@ public class CScope implements ICScope, IASTInternalScope { int type = getNamespaceType( name ); 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 ) return (IBinding) o; - IASTName foundName= (IASTName) o; - if( (resolve || foundName.getBinding() != null) && ( foundName != name ) ) { - if(!isTypeDefinition(name) || CVisitor.declaredBefore(foundName, name)) { - return foundName.resolveBinding(); + 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(); + } } } - - 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) { - 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); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java index 03abd908a69..76f59a6b6b0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java @@ -1234,7 +1234,7 @@ public class CVisitor { } } } - + boolean prefix = ( bits & PREFIX_LOOKUP ) != 0; @SuppressWarnings("unchecked") Object binding = prefix ? new ObjectSet( 2 ) : null; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java index 9ad332ff5f9..3aec4eb220e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java @@ -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(