diff --git a/core/org.eclipse.cdt.core/ChangeLog b/core/org.eclipse.cdt.core/ChangeLog index 6713ff24bad..43f0e7179ad 100644 --- a/core/org.eclipse.cdt.core/ChangeLog +++ b/core/org.eclipse.cdt.core/ChangeLog @@ -6,6 +6,11 @@ with skeleton classes based on the JDT search as a beginning for implementing C/CPP search. +2003-06-14 Victor Mozgin + Added support for pointers to members to DOMBuilder. + Added new kind of pointer operator : t_pointer_to_member (PointerOperator). + Added nameSpecifier field and set/get operations to PointerOperator. + 2003-06-06 Sean Evoy Added new interface, IResourceBuildInfo, so clients could diff --git a/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/DOMBuilder.java b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/DOMBuilder.java index cdfc7399a0b..bf499609e9a 100644 --- a/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/DOMBuilder.java +++ b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/DOMBuilder.java @@ -446,7 +446,7 @@ public class DOMBuilder implements IParserCallback, ISourceElementRequestor * @see org.eclipse.cdt.internal.core.parser.IParserCallback#pointerOperatorName(java.lang.Object) */ public void pointerOperatorName(Object ptrOperator) { - // TODO Auto-generated method stub + ((PointerOperator)ptrOperator).setNameSpecifier(currName); } /* (non-Javadoc) @@ -462,6 +462,10 @@ public class DOMBuilder implements IParserCallback, ISourceElementRequestor case IToken.tAMPER: ptrOp.setType( PointerOperator.t_reference ); break; + case IToken.tCOLONCOLON: + case IToken.tIDENTIFIER: + ptrOp.setType( PointerOperator.t_pointer_to_member ); + break; default: break; } diff --git a/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/PointerOperator.java b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/PointerOperator.java index ce5266e112c..2392d3e0aab 100644 --- a/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/PointerOperator.java +++ b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/PointerOperator.java @@ -12,6 +12,8 @@ ***********************************************************************/ package org.eclipse.cdt.internal.core.dom; +import org.eclipse.cdt.internal.core.parser.Name; + /** * @author jcamelon * @@ -20,7 +22,8 @@ public class PointerOperator { public final static int t_undefined = 0; public final static int t_pointer = 1; - public final static int t_reference = 2; + public final static int t_reference = 2; + public final static int t_pointer_to_member = 3; private int type = t_undefined; /** @@ -83,5 +86,23 @@ public class PointerOperator { public Declarator getOwnerDeclarator() { return ownerDeclarator; } + + // This is not a complete name, it is something like A::B::, i.e. ends with :: + private Name nameSpecifier = null; + + /** + * @return Class name specifier for pointers to members + */ + public Name getNameSpecifier() { + return nameSpecifier; + } + + /** + * Sets the class name specifier for pointers to members. + * @param name The name specifier to set + */ + public void setNameSpecifier(Name name) { + this.nameSpecifier = name; + } } diff --git a/core/org.eclipse.cdt.core/parser/ChangeLog b/core/org.eclipse.cdt.core/parser/ChangeLog index 46425489693..5fd38d6cfba 100644 --- a/core/org.eclipse.cdt.core/parser/ChangeLog +++ b/core/org.eclipse.cdt.core/parser/ChangeLog @@ -1,3 +1,10 @@ +2003-06-14 Victor Mozgin + Fixed handling of parameter lists for typedefs for functions. + More errorhandling in CModelBuilder. + Added handling of pointers to members. + Added handling of declarations for nested scopes (like A::B::C). + This fixes PR 36290, 36931 and partially 38920. + 2003-06-13 John Camelon Added Class/Base infrastructure to public interfaces & requestor callback. Moved many internal interfaces to external packages. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/CModelBuilder.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/CModelBuilder.java index 99fafaa509a..d8c86a125ec 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/CModelBuilder.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/CModelBuilder.java @@ -203,11 +203,11 @@ public class CModelBuilder { } protected void createElement(Parent parent, SimpleDeclaration simpleDeclaration, Declarator declarator){ + ParameterDeclarationClause pdc = declarator.getParms(); // typedef if(simpleDeclaration.getDeclSpecifier().isTypedef()){ - createTypeDef(parent, declarator, simpleDeclaration); + createTypeDef(parent, declarator, simpleDeclaration, pdc); } else { - ParameterDeclarationClause pdc = declarator.getParms(); // variable or field if (pdc == null){ createVariableSpecification(parent, simpleDeclaration, declarator, false); @@ -400,15 +400,40 @@ public class CModelBuilder { return element; } - protected TypeDef createTypeDef(Parent parent, Declarator declarator, SimpleDeclaration simpleDeclaration){ + protected TypeDef createTypeDef(Parent parent, Declarator declarator, SimpleDeclaration simpleDeclaration, ParameterDeclarationClause pdc){ // create the element Name domName = ( declarator.getDeclarator() != null ) ? declarator.getDeclarator().getName() : declarator.getName(); - String declaratorName = domName.toString(); - - TypeDef element = new TypeDef( parent, declaratorName ); - String type = getType(simpleDeclaration, declarator); - element.setTypeName(type); + String declaratorName = domName.toString(); + + TypeDef element = new TypeDef( parent, declaratorName ); + StringBuffer typeName = new StringBuffer(getType(simpleDeclaration, declarator)); + + if (pdc != null) { + // getParameterTypes + List parameterList = pdc.getDeclarations(); + String[] parameterTypes = new String[parameterList.size()]; + + for (int j = 0; j < parameterList.size(); ++j) { + ParameterDeclaration param = (ParameterDeclaration) parameterList.get(j); + parameterTypes[j] = new String(getType(param, (Declarator) param.getDeclarators().get(0))); + } + + if (parameterTypes.length > 0) { + typeName.append("("); + int i = 0; + typeName.append(parameterTypes[i++]); + while (i < parameterTypes.length) { + typeName.append(", "); + typeName.append(parameterTypes[i++]); + } + typeName.append(")"); + } else { + typeName.append("()"); + } + } + + element.setTypeName(typeName.toString()); // add to parent parent.addChild((CElement)element); @@ -428,6 +453,23 @@ public class CModelBuilder { declarator.getDeclarator().getName() : declarator.getName(); + if (domName == null) { + // TODO : improve errorhandling + // When parsing syntactically incorrect code, we might + // end up here. Most often, function/method declaration + // misses return type, and is neither a constructor nor + // a conversion operator. Like + // A::B() {} + // Parser sees A::B, understands that it is not a constructor + // /conversion, then considers it a declaration. So its + // type is read as A::B, no name, and a list of declarations + // in (). + // For now, we just ignore this scenario (and create no + // model elements), but in the future we can process this + // declaration as a function (with undefined/no type) + return null; + } + String variableName = domName.toString(); DeclSpecifier declSpecifier = simpleDeclaration.getDeclSpecifier(); @@ -682,12 +724,22 @@ public class CModelBuilder { StringBuffer type = new StringBuffer(); // get type from declaration type.append(getDeclarationType(declaration)); - // add pointerr or reference from declarator if any - type.append(getDeclaratorPointerOperation(declarator)); + // add pointer or reference from declarator if any + String declaratorPointerOperation = getDeclaratorPointerOperation(declarator); + try { + switch (declaratorPointerOperation.charAt(0)) { + case '*': + case '&': + break; // pointer/reference + default: + type.append(" "); // pointer to member + } + } catch (Exception e) {} // Empty/null strings + type.append(declaratorPointerOperation); if(declarator.getDeclarator() != null){ // pointer to function or array of functions type.append("("); - // add pointerr or reference from declarator if any + // add pointer or reference from declarator if any type.append(getDeclaratorPointerOperation(declarator.getDeclarator())); type.append(")"); } @@ -763,6 +815,9 @@ public class CModelBuilder { while(i.hasNext()){ PointerOperator po = (PointerOperator) i.next(); switch (po.getType()){ + case PointerOperator.t_pointer_to_member: + pointerString.append(po.getNameSpecifier()); + // Intentional fall-through case PointerOperator.t_pointer: pointerString.append("*"); break; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java index e770a88bbfc..ba855a49051 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java @@ -972,52 +972,70 @@ c, quickParse); { if (flags.isForParameterDeclaration()) return false; if (LT(2) == IToken.tLPAREN && flags.isForConstructor()) return true; + + boolean continueProcessing = true; + + // Portions of qualified name + // ...::secondLastID::lastID ... + int secondLastIDTokenPos = -1; + int lastIDTokenPos = 1; - int posTokenAfterTemplateParameters = 2; + int tokenPos = 2; - if (LT(posTokenAfterTemplateParameters) == IToken.tLT) { - // a case for template constructor, like CFoobar::CFoobar - - posTokenAfterTemplateParameters++; - - // until we get all the names sorted out - int depth = 1; - - while (depth > 0) { - switch (LT(posTokenAfterTemplateParameters++)) { - case IToken.tGT : - --depth; - break; - case IToken.tLT : - ++depth; - break; - } - } - } + do { + if (LT(tokenPos) == IToken.tLT) { + // a case for template instantiation, like CFoobar::CFoobar - // for constructors - return - ( - ( - (LT(posTokenAfterTemplateParameters) == IToken.tCOLONCOLON) - && - ( - LA(posTokenAfterTemplateParameters+1).getImage().equals( LA(1).getImage() ) || - LT(posTokenAfterTemplateParameters+1) == IToken.tCOMPL - ) - ) - || - ( - // for conversion operators - (LT(posTokenAfterTemplateParameters) == IToken.tCOLONCOLON) - && - ( - LT(posTokenAfterTemplateParameters+1) == IToken.t_operator - ) - ) - ); - } + tokenPos++; + + // until we get all the names sorted out + int depth = 1; + + while (depth > 0) { + switch (LT(tokenPos++)) { + case IToken.tGT : + --depth; + break; + case IToken.tLT : + ++depth; + break; + } + } + } + + if (LT(tokenPos) == IToken.tCOLONCOLON) { + tokenPos++; + + switch (LT(tokenPos)) { + case IToken.tCOMPL : // for destructors + case IToken.t_operator : // for conversion operators + return true; + case IToken.tIDENTIFIER : + secondLastIDTokenPos = lastIDTokenPos; + lastIDTokenPos = tokenPos; + tokenPos++; + break; + default : + // Something unexpected after :: + return false; + } + } else { + continueProcessing = false; + } + } + while (continueProcessing); + + // for constructors + + if (secondLastIDTokenPos < 0) return false; + + String secondLastID = LA(secondLastIDTokenPos).getImage(); + String lastID = LA(lastIDTokenPos).getImage(); + + return secondLastID.equals(lastID); + } + /** * @param flags input flags that are used to make our decision * @return whether or not this looks like a a declarator follows @@ -1772,7 +1790,7 @@ c, quickParse); * ptrOperator * : "*" (cvQualifier)* * | "&" - * | name "*" (cvQualifier)* + * | class-qualifier "*" (cvQualifier)* * * @param owner Declarator that this pointer operator corresponds to. * @throws Backtrack request a backtrack @@ -1789,19 +1807,28 @@ c, quickParse); } IToken mark = mark(); + IToken tokenType = LA(1); boolean hasName = false; if (t == IToken.tIDENTIFIER || t == IToken.tCOLONCOLON) { + callback.nameBegin(tokenType); name(); + callback.nameEnd(lastToken); hasName = true; + t = LT(1); } if (t == IToken.tSTAR) { - if( hasName ) + if( hasName ) { try{ callback.pointerOperatorName( ptrOp );} catch( Exception e ) {} + // just consume "*", so tokenType is left as "::" or Id + consume(); + } else { + tokenType = consume(); // tokenType = "*" + } - try{ callback.pointerOperatorType( ptrOp, consume());} catch( Exception e ) {} + try{ callback.pointerOperatorType(ptrOp, tokenType);} catch( Exception e ) {} for (;;) { try { diff --git a/core/org.eclipse.cdt.ui.tests/ChangeLog b/core/org.eclipse.cdt.ui.tests/ChangeLog index 04787b93633..e4ef4a47616 100644 --- a/core/org.eclipse.cdt.ui.tests/ChangeLog +++ b/core/org.eclipse.cdt.ui.tests/ChangeLog @@ -1,3 +1,8 @@ +2003-06-14 Victor Mozgin + Moved testBugSingleton192() from LokiFailures to DOMTests. + Added testPointersToMembers() and testPointersToMemberFunctions() to DOMTests. + Added testBug36290() and testBug36931() to DOMTests. + 2003-06-13 John Camelon Added Class/Base infrastructure to public interfaces & requestor callback. Moved many internal interfaces to external packages. diff --git a/core/org.eclipse.cdt.ui.tests/failures/org/eclipse/cdt/core/parser/failedTests/LokiFailures.java b/core/org.eclipse.cdt.ui.tests/failures/org/eclipse/cdt/core/parser/failedTests/LokiFailures.java index 994c7378a7e..22a0e21718a 100644 --- a/core/org.eclipse.cdt.ui.tests/failures/org/eclipse/cdt/core/parser/failedTests/LokiFailures.java +++ b/core/org.eclipse.cdt.ui.tests/failures/org/eclipse/cdt/core/parser/failedTests/LokiFailures.java @@ -25,10 +25,6 @@ public class LokiFailures extends BaseDOMTest { super(name); } - public void testBugSingleton192() { - failTest("int Test::* pMember_;" ); - } - public void testBugTypeManip151() { Writer code = new StringWriter(); diff --git a/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/DOMTests.java b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/DOMTests.java index 8077467077c..a7a0b77fd73 100644 --- a/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/DOMTests.java +++ b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/DOMTests.java @@ -2082,4 +2082,81 @@ public class DOMTests extends BaseDOMTest { parse("template X::operator A*() { } \n"); parse("template X::operator A&() { } \n"); } + + public void testBugSingleton192() throws Exception { + parse("int Test::* pMember_;" ); + } + + public void testPointersToMembers() throws Exception { + // Parse and get the translaton unit + TranslationUnit translationUnit = parse("int A::* x = 0;"); + + List tudeclarations = translationUnit.getDeclarations(); + assertEquals(1, tudeclarations.size()); + SimpleDeclaration decl1 = (SimpleDeclaration) tudeclarations.get(0); + assertEquals(decl1.getDeclSpecifier().getType(), DeclSpecifier.t_int); + + assertEquals(1, decl1.getDeclarators().size()); + + Declarator declarator1 = (Declarator) decl1.getDeclarators().get(0); + assertEquals(declarator1.getName().toString(), "x"); + Expression initValue1 = declarator1.getExpression(); + assertEquals(initValue1.elements().size(), 1); + List ptrOps1 = declarator1.getPointerOperators(); + assertNotNull(ptrOps1); + assertEquals(1, ptrOps1.size()); + PointerOperator po1 = (PointerOperator) ptrOps1.get(0); + assertNotNull(po1); + assertFalse(po1.isConst()); + assertFalse(po1.isVolatile()); + assertEquals(po1.getType(), PointerOperator.t_pointer_to_member); + assertEquals(po1.getNameSpecifier().toString(), "A::"); + } + + public void testPointersToMemberFunctions() throws Exception + { + TranslationUnit tu = parse("void (A::*name)(void);"); + assertEquals( tu.getDeclarations().size(), 1 ); + SimpleDeclaration declaration = (SimpleDeclaration)tu.getDeclarations().get(0); + assertEquals( declaration.getDeclSpecifier().getType(), DeclSpecifier.t_void ); + assertEquals( declaration.getDeclarators().size(), 1); + assertNull( ((Declarator)declaration.getDeclarators().get(0)).getName() ); + assertNotNull( ((Declarator)declaration.getDeclarators().get(0)).getDeclarator() ); + assertEquals( ((Declarator)declaration.getDeclarators().get(0)).getDeclarator().getName().toString(), "name" ); + ParameterDeclarationClause clause = ((Declarator)declaration.getDeclarators().get(0)).getParms(); + assertEquals( clause.getDeclarations().size(), 1 ); + assertEquals( ((ParameterDeclaration)clause.getDeclarations().get(0)).getDeclarators().size(), 1 ); + assertNull( ((Declarator)((ParameterDeclaration)clause.getDeclarations().get(0)).getDeclarators().get(0)).getName() ); + assertEquals( ((ParameterDeclaration)clause.getDeclarations().get(0)).getDeclSpecifier().getType(), DeclSpecifier.t_void ); + + List ptrOps1 = ((Declarator)declaration.getDeclarators().get(0)).getDeclarator().getPointerOperators(); + assertNotNull(ptrOps1); + assertEquals(1, ptrOps1.size()); + PointerOperator po1 = (PointerOperator) ptrOps1.get(0); + assertNotNull(po1); + assertFalse(po1.isConst()); + assertFalse(po1.isVolatile()); + assertEquals(po1.getType(), PointerOperator.t_pointer_to_member); + assertEquals(po1.getNameSpecifier().toString(), "A::"); + } + + public void testBug36290() throws Exception { + parse("typedef void ( A:: * pFunction ) ( void ); "); + parse("typedef void (boo) ( void ); "); + parse("typedef void boo (void); "); + } + + public void testBug36931() throws Exception { + parse("A::nested::nested(){}; "); + parse("int A::nested::foo() {} "); + parse("int A::nested::operator+() {} "); + parse("A::nested::operator int() {} "); + parse("static const int A::nested::i = 1; "); + + parse("template A::nested::nested(){}; "); + parse("template int A::nested::foo() {} "); + parse("template int A::nested::operator+() {} "); + parse("template A::nested::operator int() {} "); + } + }