1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-09 18:56:02 +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
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

View file

@ -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;
}

View file

@ -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;
}
}

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
Added Class/Base infrastructure to public interfaces & requestor callback.
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){
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;

View file

@ -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<template-args>::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<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;
}
}
}
do {
if (LT(tokenPos) == IToken.tLT) {
// a case for template instantiation, like CFoobar<A,B>::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 {

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

View file

@ -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();

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");
}
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() {} ");
}
}