diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 76d2c6e6846..2300c97d470 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -28,8 +28,10 @@ import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTReturnStatement; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; 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; @@ -49,6 +51,8 @@ import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTOperatorName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPointerToMember; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement; @@ -3194,5 +3198,75 @@ public class AST2CPPTests extends AST2BaseTest { IEnumerator one = (IEnumerator) col.getName(3).resolveBinding(); assertSame( one.getType(), e ); } + + + public void testOperatorConversionNames() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("class Foo {\n"); //$NON-NLS-1$ + buffer.append("public:\n"); //$NON-NLS-1$ + buffer.append("operator int();\n"); //$NON-NLS-1$ + buffer.append("char& operator[](unsigned int);\n"); //$NON-NLS-1$ + buffer.append("};\n"); //$NON-NLS-1$ + + IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP ); //$NON-NLS-1$ + CPPNameCollector col = new CPPNameCollector(); + tu.accept( col ); + + IASTName name1 = col.getName(1); + IASTName name2 = col.getName(2); + + assertNotNull(name1); + assertNotNull(name2); + + assertTrue(name1 instanceof ICPPASTConversionName); + assertTrue(name2 instanceof ICPPASTOperatorName); + + IASTTypeId typeId = ((ICPPASTConversionName)name1).getTypeId(); + assertNotNull(typeId); + assertEquals( ((IASTSimpleDeclSpecifier)typeId.getDeclSpecifier()).getType(), IASTSimpleDeclSpecifier.t_int ); + + } + + public void testBug36769B() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("class X { operator int(); }; \n"); //$NON-NLS-1$ + buffer.append("X::operator int() { } \n"); //$NON-NLS-1$ + buffer.append("template class X { operator int(); }; \n"); //$NON-NLS-1$ + buffer.append("template X::operator int() { } \n"); //$NON-NLS-1$ + + IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP ); //$NON-NLS-1$ + CPPNameCollector col = new CPPNameCollector(); + tu.accept( col ); + + // 1,4,12,21 - conversion + // 2, 16 .isConversion + + assertEquals(col.size(), 22); + + assertNotNull(col.getName(1)); + assertNotNull(col.getName(4)); + assertNotNull(col.getName(12)); + assertNotNull(col.getName(21)); + assertNotNull(col.getName(2)); + assertNotNull(col.getName(16)); + + // ensure the conversions are conversions + assertTrue(col.getName(1) instanceof ICPPASTConversionName); + assertTrue(col.getName(4) instanceof ICPPASTConversionName); + assertTrue(col.getName(12) instanceof ICPPASTConversionName); + assertTrue(col.getName(21) instanceof ICPPASTConversionName); + assertNotNull(((ICPPASTConversionName)col.getName(1)).getTypeId()); + assertNotNull(((ICPPASTConversionName)col.getName(4)).getTypeId()); + assertNotNull(((ICPPASTConversionName)col.getName(12)).getTypeId()); + assertNotNull(((ICPPASTConversionName)col.getName(21)).getTypeId()); + + // ensure qualified name isConversionOrOperator + assertTrue(col.getName(2) instanceof ICPPASTQualifiedName); + assertTrue(col.getName(16) instanceof ICPPASTQualifiedName); + assertTrue(((ICPPASTQualifiedName)col.getName(2)).isConversionOrOperator()); + assertTrue(((ICPPASTQualifiedName)col.getName(16)).isConversionOrOperator()); + } + + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTConversionName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTConversionName.java new file mode 100644 index 00000000000..810c205b2d2 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTConversionName.java @@ -0,0 +1,41 @@ +/********************************************************************** + * Copyright (c) 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.core.dom.ast.cpp; + +import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTTypeId; + +/** + * This interface represents a C++ conversion member function. + * + * @author dsteffle + */ +public interface ICPPASTConversionName extends IASTName { + public static final ASTNodeProperty TYPE_ID=new ASTNodeProperty( + "IASTArrayDeclarator.TYPE_ID - IASTTypeId for ICPPASTConversionName"); //$NON-NLS-1$ + + /** + * Returns the IASTTypeId for the ICPPASTConversionName. + * + * i.e. getTypeId() on operator int(); would return the IASTTypeId for "int" + * + * @return + */ + public IASTTypeId getTypeId(); + + /** + * Sets the IASTTypeId for the ICPPASTConversionName. + * + * @param typeId + */ + public void setTypeId(IASTTypeId typeId); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTOperatorName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTOperatorName.java new file mode 100644 index 00000000000..39895ba541e --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTOperatorName.java @@ -0,0 +1,22 @@ +/********************************************************************** + * Copyright (c) 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.core.dom.ast.cpp; + +import org.eclipse.cdt.core.dom.ast.IASTName; + +/** + * This interface represents a C++ overloaded operator member function. + * + * @author dsteffle + */ +public interface ICPPASTOperatorName extends IASTName { + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTQualifiedName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTQualifiedName.java index 88a537692a9..e3f623740e3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTQualifiedName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTQualifiedName.java @@ -56,4 +56,12 @@ public interface ICPPASTQualifiedName extends IASTName, IASTNameOwner { * boolean */ public void setFullyQualified(boolean value); + + /** + * This is used to check if the ICPPASTQualifiedName's last segment is + * an ICPPASTConversionName or an ICPPASTOperatorName. + * + * @return + */ + public boolean isConversionOrOperator(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ITokenDuple.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ITokenDuple.java index 6bb7203e607..814935351ef 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ITokenDuple.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ITokenDuple.java @@ -69,8 +69,4 @@ public interface ITokenDuple { public void freeReferences( ); public void acceptElement( ISourceElementRequestor requestor ); - /** - * @return - */ - public abstract boolean isConversion(); } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConversionName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConversionName.java new file mode 100644 index 00000000000..a4173977bff --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConversionName.java @@ -0,0 +1,47 @@ +/********************************************************************** + * Copyright (c) 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - 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.IASTTypeId; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; + +/** + * The implemented ICPPASTConversionName. + * + * @author dsteffle + */ +public class CPPASTConversionName extends CPPASTName implements ICPPASTConversionName { + private IASTTypeId typeId=null; + + public CPPASTConversionName() { + super(); + } + + public CPPASTConversionName(char[] name) { + super(name); + } + + public IASTTypeId getTypeId() { + return typeId; + } + + public void setTypeId(IASTTypeId typeId) { + this.typeId=typeId; + } + + public boolean accept(ASTVisitor action) { + boolean why = super.accept(action); + if( why && typeId != null ) + return typeId.accept( action ); + return why; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTOperatorName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTOperatorName.java new file mode 100644 index 00000000000..af3a5d21628 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTOperatorName.java @@ -0,0 +1,28 @@ +/********************************************************************** + * Copyright (c) 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTOperatorName; + +/** + * The imlemented ICPPASTOperatorName. + * + * @author dsteffle + */ +public class CPPASTOperatorName extends CPPASTName implements ICPPASTOperatorName { + public CPPASTOperatorName() { + super(); + } + + public CPPASTOperatorName(char[] name) { + super(name); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTQualifiedName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTQualifiedName.java index e7cb077d6f4..5b8e9dab9e9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTQualifiedName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTQualifiedName.java @@ -15,7 +15,10 @@ import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNameOwner; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTOperatorName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; /** * @author jcamelon @@ -259,4 +262,22 @@ public class CPPASTQualifiedName extends CPPASTNode implements names[names.length - 1].setBinding( binding ); } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName#isConversionOrOperator() + */ + public boolean isConversionOrOperator() { + IASTName[] nonNullNames = getNames(); // ensure no null names + + int len=nonNullNames.length; + if (nonNullNames[len-1] instanceof ICPPASTConversionName || nonNullNames[len-1] instanceof ICPPASTOperatorName) return true; + + // check templateId's name + if (nonNullNames[len-1] instanceof ICPPASTTemplateId) { + IASTName tempName = ((ICPPASTTemplateId)nonNullNames[len-1]).getTemplateName(); + if (tempName instanceof ICPPASTConversionName || tempName instanceof ICPPASTOperatorName) return true; + } + + return false; + } + } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateId.java index bca22ef7b65..a2e52bcba28 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateId.java @@ -22,8 +22,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; * @author jcamelon */ public class CPPASTTemplateId extends CPPASTNode implements ICPPASTTemplateId { - private static final char[] EMPTY_CHAR_ARRAY = { }; - private static final String EMPTY_STRING = ""; //$NON-NLS-1$ +// private static final char[] EMPTY_CHAR_ARRAY = { }; +// private static final String EMPTY_STRING = ""; //$NON-NLS-1$ private IASTName templateName; /* (non-Javadoc) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index db23653ff81..d1dd93711ff 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -81,6 +81,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; @@ -130,12 +131,12 @@ import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.ITokenDuple; import org.eclipse.cdt.core.parser.ParseError; import org.eclipse.cdt.core.parser.ParserMode; -import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser; import org.eclipse.cdt.internal.core.dom.parser.BacktrackException; import org.eclipse.cdt.internal.core.parser.SimpleDeclarationStrategy; import org.eclipse.cdt.internal.core.parser.TemplateParameterManager; +import org.eclipse.cdt.internal.core.parser.token.OperatorTokenDuple; import org.eclipse.cdt.internal.core.parser.token.TokenFactory; /** @@ -148,6 +149,7 @@ import org.eclipse.cdt.internal.core.parser.token.TokenFactory; */ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { + private static final String COMPL = "~"; //$NON-NLS-1$ private static final String CONST_CAST = "const_cast"; //$NON-NLS-1$ private static final String REINTERPRET_CAST = "reinterpret_cast"; //$NON-NLS-1$ private static final String STATIC_CAST = "static_cast"; //$NON-NLS-1$ @@ -422,12 +424,13 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return last; } - protected ITokenDuple operatorId(IToken originalToken, + protected IASTName operatorId(IToken originalToken, TemplateParameterManager templateArgs) throws BacktrackException, EndOfFileException { // we know this is an operator IToken operatorToken = consume(IToken.t_operator); IToken toSend = null; + IASTTypeId typeId = null; if (LA(1).isOperator() || LT(1) == IToken.tLPAREN || LT(1) == IToken.tLBRACKET) { if ((LT(1) == IToken.t_new || LT(1) == IToken.t_delete) @@ -452,7 +455,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } else { // must be a conversion function IToken t = LA(1); - typeId(true, false); + typeId = typeId(true, false); if (t != LA(1)) { while (t.getNext() != LA(1)) { t = t.getNext(); @@ -474,12 +477,18 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { hasTemplateId = true; } - ITokenDuple duple = TokenFactory + ITokenDuple duple = TokenFactory .createTokenDuple(originalToken == null ? operatorToken : originalToken, toSend, (hasTemplateId ? templateArgs .getTemplateArgumentsList() : null)); - return duple; + OperatorTokenDuple operator= new OperatorTokenDuple(duple); + if (typeId!=null) { // if it's a conversion operator + operator.setConversionOperator(true); + operator.setTypeId(typeId); + } + + return createName(operator); } finally { if (grabbedNewInstance) TemplateParameterManager.returnInstance(templateArgs); @@ -1528,7 +1537,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { isTemplate = true; } - IASTName name = createName(idExpression()); + IASTName name = idExpression(); ICPPASTFieldReference fieldReference = createFieldReference(); ((ASTNode) fieldReference).setOffsetAndLength( @@ -1556,7 +1565,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { isTemplate = true; } - name = createName(idExpression()); + name = idExpression(); fieldReference = createFieldReference(); ((ASTNode) fieldReference).setOffsetAndLength( @@ -1728,11 +1737,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { case IToken.t_operator: case IToken.tCOMPL: { - ITokenDuple duple = idExpression(); - IASTName name = createName(duple); + IASTName name = idExpression(); IASTIdExpression idExpression = createIdExpression(); - ((ASTNode) idExpression).setOffsetAndLength(duple.getStartOffset(), - duple.getEndOffset() - duple.getStartOffset()); + ((ASTNode) idExpression).setOffsetAndLength(((ASTNode)name).getOffset(), + ((ASTNode)name).getOffset() + ((ASTNode)name).getLength() - ((ASTNode)name).getOffset()); idExpression.setName(name); name.setParent(idExpression); name.setPropertyInParent(IASTIdExpression.ID_NAME); @@ -1772,11 +1780,11 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return new CPPASTIdExpression(); } - protected ITokenDuple idExpression() throws EndOfFileException, + protected IASTName idExpression() throws EndOfFileException, BacktrackException { - ITokenDuple duple = null; + IASTName name = null; try { - duple = name(); + name = createName(name()); } catch (BacktrackException bt) { IToken mark = mark(); if (LT(1) == IToken.tCOLONCOLON || LT(1) == IToken.tIDENTIFIER) { @@ -1791,16 +1799,16 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } if (LT(1) == IToken.t_operator) - duple = operatorId(start, null); + name = operatorId(start, null); else { backup(mark); throwBacktrack(start.getOffset(), end.getEndOffset() - start.getOffset()); } } else if (LT(1) == IToken.t_operator) - duple = operatorId(null, null); + name = operatorId(null, null); } - return duple; + return name; } @@ -2543,6 +2551,12 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { else // templateID subName = createTemplateID(segments[i]); + + if (i==segments.length-1 && + duple instanceof OperatorTokenDuple) { // make sure the last segment is an OperatorName/ConversionName + subName = createOperatorName((OperatorTokenDuple)duple, subName); + } + subName.setParent(result); subName.setPropertyInParent(ICPPASTQualifiedName.SEGMENT_NAME); ((ASTNode) subName).setOffsetAndLength(segments[i].getStartOffset(), @@ -2598,8 +2612,12 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if( duple.getTemplateIdArgLists() != null ) return createTemplateID( duple ); - // We're a single token - CPPASTName name = new CPPASTName(duple.toCharArray()); + // We're a single name + IASTName name = new CPPASTName(duple.toCharArray()); + if (duple instanceof OperatorTokenDuple) { + name = createOperatorName((OperatorTokenDuple)duple, name); + } + IToken token = duple.getFirstToken(); switch (token.getType()) { case IToken.tCOMPLETION: @@ -2608,10 +2626,32 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { break; } - name.setOffsetAndLength(duple.getStartOffset(), duple.getEndOffset() - - duple.getStartOffset()); + ((ASTNode)name).setOffsetAndLength(duple.getStartOffset(), duple.getEndOffset() + - duple.getStartOffset()); + return name; } + + protected IASTName createOperatorName(OperatorTokenDuple duple, IASTName name) { + IASTName aName=null; + + if (duple.isConversionOperator()) { + aName = new CPPASTConversionName(name.toCharArray()); + IASTTypeId typeId = duple.getTypeId(); + typeId.setParent(aName); + typeId.setPropertyInParent(ICPPASTConversionName.TYPE_ID); + ((CPPASTConversionName)aName).setTypeId(typeId); + } else { + aName = new CPPASTOperatorName(name.toCharArray()); + } + + if (name instanceof ICPPASTTemplateId) { + ((ICPPASTTemplateId)name).setTemplateName(aName); + return name; + } + + return aName; + } /** * @return @@ -2923,7 +2963,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { * @throws EndOfFileException * we could encounter EOF while looking ahead */ - protected boolean lookAheadForConstructorOrConversion(Flags flags) + protected boolean lookAheadForConstructorOrOperator(Flags flags) throws EndOfFileException { if (flags.isForParameterDeclaration()) return false; @@ -2931,9 +2971,9 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return true; IToken mark = mark(); - ITokenDuple duple = null; + IASTName name = null; try { - duple = consumeTemplatedOperatorName(); + name = consumeTemplatedOperatorName(); } catch (BacktrackException e) { backup(mark); return false; @@ -2942,50 +2982,48 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return false; } - if (duple == null) { + if (name == null) { backup(mark); return false; } - ITokenDuple leadingSegments = duple.getLeadingSegments(); - if (leadingSegments == null) { - backup(mark); - return false; - } - ITokenDuple lastSegment = duple.getLastSegment(); - char[] className = lastSegment.extractNameFromTemplateId(); - if (className == null || CharArrayUtils.equals(className, EMPTY_STRING)) { - backup(mark); - return false; - } - - ITokenDuple secondlastSegment = leadingSegments.getLastSegment(); - if (secondlastSegment == null) { - backup(mark); - return false; - } - char[] otherName = secondlastSegment.extractNameFromTemplateId(); - if (otherName == null || CharArrayUtils.equals(otherName, EMPTY_STRING)) { - backup(mark); - return false; - } - - if (lastSegment.isConversion()) { - backup(mark); - return true; - } - - if (CharArrayUtils.equals(className, otherName)) { - backup(mark); - return true; - } - char[] destructorName = CharArrayUtils.concat( - "~".toCharArray(), otherName); //$NON-NLS-1$ - if (CharArrayUtils.equals(destructorName, className)) { - backup(mark); - return true; - } - + // constructor/conversion must be an ICPPASTQualifiedName (i.e. can't be defined for the global scope) + if (name instanceof ICPPASTQualifiedName) { + IASTName[] segments = ((ICPPASTQualifiedName)name).getNames(); + + int len = segments.length; + if (len >= 2) { + if (segments[0].toString().length() == 0) { + backup(mark); + return false; + } + + if (((ICPPASTQualifiedName)name).isConversionOrOperator()) { // conversion or operator + backup(mark); + return true; + } + + if (segments[len-1].toString().equals(segments[len-2].toString())) { // constructor + backup(mark); + return true; + } + + StringBuffer destructorName = new StringBuffer(); + destructorName.append(COMPL); + destructorName.append(segments[len-2]); + if (segments[len-1].toString().equals(destructorName.toString())) { // destructor + backup(mark); + return true; + } + } else { + backup(mark); + return false; + } + } else { + backup(mark); + return false; + } + backup(mark); return false; } @@ -3185,7 +3223,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (parm && flags.haveEncounteredTypename()) break declSpecifiers; - if (lookAheadForConstructorOrConversion(flags)) + if (lookAheadForConstructorOrOperator(flags)) break declSpecifiers; if (lookAheadForDeclarator(flags)) @@ -3600,10 +3638,9 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { declaratorName = createName(); } else { try { - ITokenDuple d = consumeTemplatedOperatorName(); - declaratorName = createName(d); + declaratorName = consumeTemplatedOperatorName(); finalOffset = calculateEndOffset(declaratorName); - if (d.isConversion()) + if (declaratorName instanceof ICPPASTQualifiedName && ((ICPPASTQualifiedName)declaratorName).isConversionOrOperator()) isFunction = true; } catch (BacktrackException bt) { declaratorName = createName(); @@ -3899,7 +3936,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return new CPPASTDeclarator(); } - protected ITokenDuple consumeTemplatedOperatorName() + protected IASTName consumeTemplatedOperatorName() throws EndOfFileException, BacktrackException { TemplateParameterManager argumentList = TemplateParameterManager .getInstance(); @@ -3908,13 +3945,11 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return operatorId(null, null); try { - return name(); + return createName(name()); } catch (BacktrackException bt) { } IToken start = null; - boolean hasTemplateId = false; - IToken mark = mark(); if (LT(1) == IToken.tCOLONCOLON || LT(1) == IToken.tIDENTIFIER) { start = consume(); @@ -3922,28 +3957,22 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (start.getType() == IToken.tIDENTIFIER) { end = consumeTemplateArguments(end, argumentList); - if (end != null && end.getType() == IToken.tGT) - hasTemplateId = true; } while (LT(1) == IToken.tCOLONCOLON || LT(1) == IToken.tIDENTIFIER) { end = consume(); if (end.getType() == IToken.tIDENTIFIER) { end = consumeTemplateArguments(end, argumentList); - if (end.getType() == IToken.tGT) - hasTemplateId = true; } } - if (LT(1) == IToken.t_operator) - end = operatorId(start, (hasTemplateId ? argumentList : null)) - .getLastToken(); - else { - int endOffset = (end != null) ? end.getEndOffset() : 0; - backup(mark); - throwBacktrack(mark.getOffset(), endOffset - mark.getOffset()); + + if (LT(1) == IToken.t_operator) { + return operatorId(start, argumentList ); } - return TokenFactory.createTokenDuple(start, end, argumentList - .getTemplateArgumentsList()); + + int endOffset = (end != null) ? end.getEndOffset() : 0; + backup(mark); + throwBacktrack(mark.getOffset(), endOffset - mark.getOffset()); } int endOffset = (mark != null) ? mark.getEndOffset() : 0; backup(mark); @@ -4533,15 +4562,23 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { * @see org.eclipse.cdt.internal.core.parser2.AbstractGNUSourceCodeParser#createName(org.eclipse.cdt.core.parser.IToken) */ protected IASTName createName(IToken token) { - CPPASTName n = new CPPASTName(token.getCharImage()); + IASTName n = null; + + if (token instanceof OperatorTokenDuple) { + n = createOperatorName((OperatorTokenDuple)token, n); + } else { + n = new CPPASTName(token.getCharImage()); + } + switch (token.getType()) { case IToken.tCOMPLETION: case IToken.tEOC: createCompletionNode(token).addName(n); break; } - n.setOffsetAndLength(token.getOffset(), token.getLength()); - return n; + ((ASTNode)n).setOffsetAndLength(token.getOffset(), token.getLength()); + + return n; } /* diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/BasicTokenDuple.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/BasicTokenDuple.java index 8f8c442b5f1..ac62c4ad16e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/BasicTokenDuple.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/BasicTokenDuple.java @@ -598,15 +598,4 @@ public class BasicTokenDuple implements ITokenDuple { public char[] getFilename() { return firstToken.getFilename(); } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.parser.ITokenDuple#isConversion() - */ - public boolean isConversion() { - int index = findLastTokenType( IToken.t_operator ); - if( index == -1 ) return false; - return true; - } - - } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/OperatorTokenDuple.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/OperatorTokenDuple.java new file mode 100644 index 00000000000..3f416fd0fe3 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/OperatorTokenDuple.java @@ -0,0 +1,220 @@ +/********************************************************************** + * Copyright (c) 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.internal.core.parser.token; + +import java.util.Iterator; +import java.util.List; + +import org.eclipse.cdt.core.dom.ast.IASTTypeId; +import org.eclipse.cdt.core.parser.ISourceElementRequestor; +import org.eclipse.cdt.core.parser.IToken; +import org.eclipse.cdt.core.parser.ITokenDuple; + +/** + * This class is used by the GNUCPPSourceParser as an intermediate determinant of whether a + * BasicTokenDuple represents an IASTConversionFunction or an IASTOperatorFunction. + * + * @author dsteffle + */ +public class OperatorTokenDuple implements ITokenDuple { + + private ITokenDuple token = null; + private IASTTypeId typeId = null; + private boolean isConversionOperator=false; + + /** + * Simple constructor. token is wrapped by this class. + * @param token + */ + public OperatorTokenDuple(ITokenDuple token) { + this.token=token; + } + + // below are functions used by GNUCPPSourceParser, see IOperatorTokenDuple + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.token.IOperatorTokenDuple#isConversionOperator() + */ + public boolean isConversionOperator() { + return isConversionOperator; + } + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.token.IOperatorTokenDuple#setConversionOperator(boolean) + */ + public void setConversionOperator(boolean isConversionOperator) { + this.isConversionOperator = isConversionOperator; + } + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.token.IOperatorTokenDuple#getTypeId() + */ + public IASTTypeId getTypeId() { + return typeId; + } + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.token.IOperatorTokenDuple# + * isConversionOperator(org.eclipse.cdt.core.dom.ast.IASTTypeId) + */ + public void setTypeId(IASTTypeId typeId) { + this.typeId = typeId; + } + + // below are ITokenDuple functions + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#getFirstToken() + */ + public IToken getFirstToken() { + return token.getFirstToken(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#getLastToken() + */ + public IToken getLastToken() { + return token.getLastToken(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#getTemplateIdArgLists() + */ + public List[] getTemplateIdArgLists() { + return token.getTemplateIdArgLists(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#getLastSegment() + */ + public ITokenDuple getLastSegment() { + return token.getLastSegment(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#getLeadingSegments() + */ + public ITokenDuple getLeadingSegments() { + return token.getLeadingSegments(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#getSegmentCount() + */ + public int getSegmentCount() { + return token.getSegmentCount(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#iterator() + */ + public Iterator iterator() { + return token.iterator(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#toCharArray() + */ + public char[] toCharArray() { + return token.toCharArray(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#getFilename() + */ + public char[] getFilename() { + return token.getFilename(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#isIdentifier() + */ + public boolean isIdentifier() { + return token.isIdentifier(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#length() + */ + public int length() { + return token.length(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#getSubrange(int, int) + */ + public ITokenDuple getSubrange(int startIndex, int endIndex) { + return token.getSubrange(startIndex, endIndex); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#getToken(int) + */ + public IToken getToken(int index) { + return token.getToken(index); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#getSegments() + */ + public ITokenDuple[] getSegments() { + return token.getSegments(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#findLastTokenType(int) + */ + public int findLastTokenType(int type) { + return token.findLastTokenType(type); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#getStartOffset() + */ + public int getStartOffset() { + return token.getStartOffset(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#getEndOffset() + */ + public int getEndOffset() { + return token.getEndOffset(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#getLineNumber() + */ + public int getLineNumber() { + return token.getLineNumber(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#syntaxOfName() + */ + public boolean syntaxOfName() { + return token.syntaxOfName(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#extractNameFromTemplateId() + */ + public char[] extractNameFromTemplateId() { + return token.extractNameFromTemplateId(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#contains(org.eclipse.cdt.core.parser.ITokenDuple) + */ + public boolean contains(ITokenDuple duple) { + return token.contains(duple); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#toQualifiedName() + */ + public String[] toQualifiedName() { + return token.toQualifiedName(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple#freeReferences() + */ + public void freeReferences() { + token.freeReferences(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ITokenDuple# + * acceptElement(org.eclipse.cdt.core.parser.ISourceElementRequestor) + */ + public void acceptElement(ISourceElementRequestor requestor) { + token.acceptElement(requestor); + } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + public String toString() { + return token.toString(); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui.tests/src/org/eclipse/cdt/ui/tests/DOMAST/DOMASTNodeLeaf.java b/core/org.eclipse.cdt.ui.tests/src/org/eclipse/cdt/ui/tests/DOMAST/DOMASTNodeLeaf.java index c5862b0e9b3..62d7f5f2fe2 100644 --- a/core/org.eclipse.cdt.ui.tests/src/org/eclipse/cdt/ui/tests/DOMAST/DOMASTNodeLeaf.java +++ b/core/org.eclipse.cdt.ui.tests/src/org/eclipse/cdt/ui/tests/DOMAST/DOMASTNodeLeaf.java @@ -309,6 +309,7 @@ public class DOMASTNodeLeaf implements IAdaptable { } private static class ASTPropertySource implements IPropertySource { + private static final IPropertyDescriptor[] BLANK_DESCRIPTORS = new IPropertyDescriptor[0]; private static final String OPEN_PAREN = " ("; //$NON-NLS-1$ private static final String CLOSE_PAREN = ")"; //$NON-NLS-1$ private static final String L_BRACKET_STRING = "["; //$NON-NLS-1$ @@ -360,6 +361,7 @@ public class DOMASTNodeLeaf implements IAdaptable { private IPropertyDescriptor[] getPropertyDescriptors(Object obj) { IPropertyDescriptor[] desc = new IPropertyDescriptor[DEFAULT_DESCRIPTOR_SIZE]; + if (obj==null) return BLANK_DESCRIPTORS; Class objClass = obj.getClass(); Class[] interfaces = objClass.getInterfaces();