1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-28 19:35:36 +02:00

Patch for Victor Mozgin.

implemented support for pointers to class members;
added handling of declarations for nested scopes (like A::B::C);
fixed handling of parameter lists for typedefs for functions;
some errorhandling in CModelBuilder;
This commit is contained in:
John Camelon 2003-06-16 21:41:54 +00:00
parent 138588dd26
commit 15f0d21085
9 changed files with 259 additions and 62 deletions

View file

@ -6,6 +6,11 @@
with skeleton classes based on the JDT search as a beginning for with skeleton classes based on the JDT search as a beginning for
implementing C/CPP search. 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 2003-06-06 Sean Evoy
Added new interface, IResourceBuildInfo, so clients could Added new interface, IResourceBuildInfo, so clients could

View file

@ -446,7 +446,7 @@ public class DOMBuilder implements IParserCallback, ISourceElementRequestor
* @see org.eclipse.cdt.internal.core.parser.IParserCallback#pointerOperatorName(java.lang.Object) * @see org.eclipse.cdt.internal.core.parser.IParserCallback#pointerOperatorName(java.lang.Object)
*/ */
public void pointerOperatorName(Object ptrOperator) { public void pointerOperatorName(Object ptrOperator) {
// TODO Auto-generated method stub ((PointerOperator)ptrOperator).setNameSpecifier(currName);
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -462,6 +462,10 @@ public class DOMBuilder implements IParserCallback, ISourceElementRequestor
case IToken.tAMPER: case IToken.tAMPER:
ptrOp.setType( PointerOperator.t_reference ); ptrOp.setType( PointerOperator.t_reference );
break; break;
case IToken.tCOLONCOLON:
case IToken.tIDENTIFIER:
ptrOp.setType( PointerOperator.t_pointer_to_member );
break;
default: default:
break; break;
} }

View file

@ -12,6 +12,8 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.internal.core.dom; package org.eclipse.cdt.internal.core.dom;
import org.eclipse.cdt.internal.core.parser.Name;
/** /**
* @author jcamelon * @author jcamelon
* *
@ -20,7 +22,8 @@ public class PointerOperator {
public final static int t_undefined = 0; public final static int t_undefined = 0;
public final static int t_pointer = 1; 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; private int type = t_undefined;
/** /**
@ -83,5 +86,23 @@ public class PointerOperator {
public Declarator getOwnerDeclarator() { public Declarator getOwnerDeclarator() {
return ownerDeclarator; 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;
}
} }

View file

@ -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 2003-06-13 John Camelon
Added Class/Base infrastructure to public interfaces & requestor callback. Added Class/Base infrastructure to public interfaces & requestor callback.
Moved many internal interfaces to external packages. Moved many internal interfaces to external packages.

View file

@ -203,11 +203,11 @@ public class CModelBuilder {
} }
protected void createElement(Parent parent, SimpleDeclaration simpleDeclaration, Declarator declarator){ protected void createElement(Parent parent, SimpleDeclaration simpleDeclaration, Declarator declarator){
ParameterDeclarationClause pdc = declarator.getParms();
// typedef // typedef
if(simpleDeclaration.getDeclSpecifier().isTypedef()){ if(simpleDeclaration.getDeclSpecifier().isTypedef()){
createTypeDef(parent, declarator, simpleDeclaration); createTypeDef(parent, declarator, simpleDeclaration, pdc);
} else { } else {
ParameterDeclarationClause pdc = declarator.getParms();
// variable or field // variable or field
if (pdc == null){ if (pdc == null){
createVariableSpecification(parent, simpleDeclaration, declarator, false); createVariableSpecification(parent, simpleDeclaration, declarator, false);
@ -400,15 +400,40 @@ public class CModelBuilder {
return element; 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 // create the element
Name domName = ( declarator.getDeclarator() != null ) ? declarator.getDeclarator().getName() : Name domName = ( declarator.getDeclarator() != null ) ? declarator.getDeclarator().getName() :
declarator.getName(); declarator.getName();
String declaratorName = domName.toString(); String declaratorName = domName.toString();
TypeDef element = new TypeDef( parent, declaratorName ); TypeDef element = new TypeDef( parent, declaratorName );
String type = getType(simpleDeclaration, declarator); StringBuffer typeName = new StringBuffer(getType(simpleDeclaration, declarator));
element.setTypeName(type);
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 // add to parent
parent.addChild((CElement)element); parent.addChild((CElement)element);
@ -428,6 +453,23 @@ public class CModelBuilder {
declarator.getDeclarator().getName() : declarator.getDeclarator().getName() :
declarator.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(); String variableName = domName.toString();
DeclSpecifier declSpecifier = simpleDeclaration.getDeclSpecifier(); DeclSpecifier declSpecifier = simpleDeclaration.getDeclSpecifier();
@ -682,12 +724,22 @@ public class CModelBuilder {
StringBuffer type = new StringBuffer(); StringBuffer type = new StringBuffer();
// get type from declaration // get type from declaration
type.append(getDeclarationType(declaration)); type.append(getDeclarationType(declaration));
// add pointerr or reference from declarator if any // add pointer or reference from declarator if any
type.append(getDeclaratorPointerOperation(declarator)); 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){ if(declarator.getDeclarator() != null){
// pointer to function or array of functions // pointer to function or array of functions
type.append("("); 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(getDeclaratorPointerOperation(declarator.getDeclarator()));
type.append(")"); type.append(")");
} }
@ -763,6 +815,9 @@ public class CModelBuilder {
while(i.hasNext()){ while(i.hasNext()){
PointerOperator po = (PointerOperator) i.next(); PointerOperator po = (PointerOperator) i.next();
switch (po.getType()){ switch (po.getType()){
case PointerOperator.t_pointer_to_member:
pointerString.append(po.getNameSpecifier());
// Intentional fall-through
case PointerOperator.t_pointer: case PointerOperator.t_pointer:
pointerString.append("*"); pointerString.append("*");
break; break;

View file

@ -972,52 +972,70 @@ c, quickParse);
{ {
if (flags.isForParameterDeclaration()) return false; if (flags.isForParameterDeclaration()) return false;
if (LT(2) == IToken.tLPAREN && flags.isForConstructor()) return true; if (LT(2) == IToken.tLPAREN && flags.isForConstructor()) return true;
boolean continueProcessing = true;
// Portions of qualified name
// ...::secondLastID<template-args>::lastID ...
int secondLastIDTokenPos = -1;
int lastIDTokenPos = 1;
int posTokenAfterTemplateParameters = 2; int tokenPos = 2;
if (LT(posTokenAfterTemplateParameters) == IToken.tLT) { do {
// a case for template constructor, like CFoobar<A,B>::CFoobar if (LT(tokenPos) == IToken.tLT) {
// a case for template instantiation, like CFoobar<A,B>::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;
}
}
}
// for constructors tokenPos++;
return
( // until we get all the names sorted out
( int depth = 1;
(LT(posTokenAfterTemplateParameters) == IToken.tCOLONCOLON)
&& while (depth > 0) {
( switch (LT(tokenPos++)) {
LA(posTokenAfterTemplateParameters+1).getImage().equals( LA(1).getImage() ) || case IToken.tGT :
LT(posTokenAfterTemplateParameters+1) == IToken.tCOMPL --depth;
) break;
) case IToken.tLT :
|| ++depth;
( break;
// for conversion operators }
(LT(posTokenAfterTemplateParameters) == IToken.tCOLONCOLON) }
&& }
(
LT(posTokenAfterTemplateParameters+1) == IToken.t_operator 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 * @param flags input flags that are used to make our decision
* @return whether or not this looks like a a declarator follows * @return whether or not this looks like a a declarator follows
@ -1772,7 +1790,7 @@ c, quickParse);
* ptrOperator * ptrOperator
* : "*" (cvQualifier)* * : "*" (cvQualifier)*
* | "&" * | "&"
* | name "*" (cvQualifier)* * | class-qualifier "*" (cvQualifier)*
* *
* @param owner Declarator that this pointer operator corresponds to. * @param owner Declarator that this pointer operator corresponds to.
* @throws Backtrack request a backtrack * @throws Backtrack request a backtrack
@ -1789,19 +1807,28 @@ c, quickParse);
} }
IToken mark = mark(); IToken mark = mark();
IToken tokenType = LA(1);
boolean hasName = false; boolean hasName = false;
if (t == IToken.tIDENTIFIER || t == IToken.tCOLONCOLON) if (t == IToken.tIDENTIFIER || t == IToken.tCOLONCOLON)
{ {
callback.nameBegin(tokenType);
name(); name();
callback.nameEnd(lastToken);
hasName = true; hasName = true;
t = LT(1);
} }
if (t == IToken.tSTAR) { if (t == IToken.tSTAR) {
if( hasName ) if( hasName ) {
try{ callback.pointerOperatorName( ptrOp );} catch( Exception e ) {} 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 (;;) { for (;;) {
try { try {

View file

@ -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 2003-06-13 John Camelon
Added Class/Base infrastructure to public interfaces & requestor callback. Added Class/Base infrastructure to public interfaces & requestor callback.
Moved many internal interfaces to external packages. Moved many internal interfaces to external packages.

View file

@ -25,10 +25,6 @@ public class LokiFailures extends BaseDOMTest {
super(name); super(name);
} }
public void testBugSingleton192() {
failTest("int Test::* pMember_;" );
}
public void testBugTypeManip151() public void testBugTypeManip151()
{ {
Writer code = new StringWriter(); Writer code = new StringWriter();

View file

@ -2082,4 +2082,81 @@ public class DOMTests extends BaseDOMTest {
parse("template <class A,B> X<A,C>::operator A*() { } \n"); parse("template <class A,B> X<A,C>::operator A*() { } \n");
parse("template <class A,B> X<A,C>::operator A&() { } \n"); parse("template <class A,B> X<A,C>::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 <class B,C> A<B>::nested::nested(){}; ");
parse("template <class B,C> int A::nested<B,D>::foo() {} ");
parse("template <class B,C> int A<B,C>::nested<C,B>::operator+() {} ");
parse("template <class B,C> A::nested::operator int() {} ");
}
} }