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:
parent
138588dd26
commit
15f0d21085
9 changed files with 259 additions and 62 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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() {} ");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue