From 86baacedc837c93de2d73a8328b62794eab18724 Mon Sep 17 00:00:00 2001 From: Andrew Niefer Date: Thu, 26 May 2005 19:43:59 +0000 Subject: [PATCH] fixing invalid problem bindings: - default constructors via parameters with default values - expression types with typedefs - default values vs void --- .../core/parser/tests/ast2/AST2CPPTests.java | 18 +++++ .../core/dom/parser/cpp/CPPClassScope.java | 65 ++++++++++++++++--- .../core/dom/parser/cpp/CPPClassType.java | 25 ++++--- .../core/dom/parser/cpp/CPPSemantics.java | 5 +- .../core/dom/parser/cpp/CPPVisitor.java | 15 ++++- 5 files changed, 108 insertions(+), 20 deletions(-) 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 0383e762f12..479206d61bf 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 @@ -4498,4 +4498,22 @@ public class AST2CPPTests extends AST2BaseTest { ICPPFunction copy = (ICPPFunction) col.getName(1).resolveBinding(); assertSame( copy, col.getName(5).resolveBinding() ); } + + public void testDefaultConstructor() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("class A { \n"); //$NON-NLS-1$ + buffer.append(" A( int i = 0 ); \n"); //$NON-NLS-1$ + buffer.append("}; \n"); //$NON-NLS-1$ + + IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP ); + CPPNameCollector col = new CPPNameCollector(); + tu.accept(col); + + ICPPClassType A = (ICPPClassType) col.getName(0).resolveBinding(); + ICPPConstructor ctor = (ICPPConstructor) col.getName(1).resolveBinding(); + + ICPPConstructor [] cs = A.getConstructors(); + assertTrue( cs.length == 2 ); + assertSame( cs[1], ctor ); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java index 081f739d386..6b6cbd84f96 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java @@ -14,10 +14,16 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IBasicType; import org.eclipse.cdt.core.dom.ast.IBinding; @@ -26,6 +32,7 @@ import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTOperatorName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; @@ -80,18 +87,19 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { } } char [] className = name.toCharArray(); - - //default constructor: A() - IType voidType = new CPPBasicType( IBasicType.t_void, 0 ); - IParameter [] voidPs = new IParameter [] { new CPPParameter( voidType ) }; - ICPPMethod m = new CPPImplicitConstructor( this, className, voidPs ); - implicits[0] = m; - addBinding( m ); + + IParameter [] voidPs = new IParameter [] { new CPPParameter( CPPSemantics.VOID_TYPE ) }; + if( !hasNonStandardDefaultConstructor( compTypeSpec ) ) { + //default constructor: A(void) + ICPPMethod m = new CPPImplicitConstructor( this, className, voidPs ); + implicits[0] = m; + addBinding( m ); + } //copy constructor: A( const A & ) IType pType = new CPPReferenceType( new CPPQualifierType( clsType, true, false ) ); IParameter [] ps = new IParameter [] { new CPPParameter( pType ) }; - m = new CPPImplicitConstructor( this, className, ps ); + ICPPMethod m = new CPPImplicitConstructor( this, className, ps ); implicits[1] = m; addBinding( m ); @@ -108,6 +116,47 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { addBinding( m ); } + private boolean hasNonStandardDefaultConstructor( ICPPASTCompositeTypeSpecifier compSpec ){ + IASTDeclaration [] members = compSpec.getMembers(); + char [] name = compSpec.getName().toCharArray(); + IASTDeclarator dtor = null; + IASTDeclSpecifier spec = null; + for( int i = 0; i < members.length; i++ ){ + if( members[i] instanceof IASTSimpleDeclaration ){ + IASTDeclarator [] dtors = ((IASTSimpleDeclaration)members[i]).getDeclarators(); + if( dtors.length == 0 || dtors.length > 1 ) + continue; + dtor = dtors[0]; + spec = ((IASTSimpleDeclaration)members[i]).getDeclSpecifier(); + } else if( members[i] instanceof IASTFunctionDefinition ){ + dtor = ((IASTFunctionDefinition)members[i]).getDeclarator(); + spec = ((IASTFunctionDefinition)members[i]).getDeclSpecifier(); + } + if( !(dtor instanceof ICPPASTFunctionDeclarator) || !(spec instanceof IASTSimpleDeclSpecifier) || + ((IASTSimpleDeclSpecifier)spec).getType() != IASTSimpleDeclSpecifier.t_unspecified || + !CharArrayUtils.equals( dtor.getName().toCharArray(), name ) ) + { + continue; + } + + IASTParameterDeclaration [] ps = ((ICPPASTFunctionDeclarator)dtor).getParameters(); + if( ps.length >= 1 ){ + IASTDeclarator d = ps[0].getDeclarator(); + IASTDeclSpecifier s = ps[0].getDeclSpecifier(); + if( s instanceof IASTSimpleDeclSpecifier && + ((IASTSimpleDeclSpecifier)s).getType() == IASTSimpleDeclSpecifier.t_void && + d.getPointerOperators().length == 0 && !(d instanceof IASTArrayDeclarator) ) + { + continue; //A(void) + } + + if( d.getInitializer() != null ) + return true; + } + } + return false; + } + public IScope getParent() { ICPPASTCompositeTypeSpecifier compType = (ICPPASTCompositeTypeSpecifier) getPhysicalNode(); IASTName compName = compType.getName(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java index acebbe5d402..bb74e9462ac 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java @@ -172,7 +172,7 @@ public class CPPClassType implements ICPPClassType, ICPPInternalClassType { private IASTName definition; private IASTName [] declarations; - + private boolean checked = false; public CPPClassType( IASTName name ){ if( name instanceof ICPPASTQualifiedName ){ IASTName [] ns = ((ICPPASTQualifiedName)name).getNames(); @@ -250,17 +250,19 @@ public class CPPClassType implements ICPPClassType, ICPPInternalClassType { } private void checkForDefinition(){ - FindDefinitionAction action = new FindDefinitionAction(); - IASTNode node = CPPVisitor.getContainingBlockItem( getPhysicalNode() ).getParent(); - - node.accept( action ); - definition = action.result; - - if( definition == null ){ - node.getTranslationUnit().accept( action ); + if( !checked ) { + FindDefinitionAction action = new FindDefinitionAction(); + IASTNode node = CPPVisitor.getContainingBlockItem( getPhysicalNode() ).getParent(); + + node.accept( action ); definition = action.result; + + if( definition == null ){ + node.getTranslationUnit().accept( action ); + definition = action.result; + } + checked = true; } - return; } @@ -365,6 +367,9 @@ public class CPPClassType implements ICPPClassType, ICPPInternalClassType { * @see org.eclipse.cdt.core.dom.ast.ICompositeType#getCompositeScope() */ public IScope getCompositeScope() { + if( definition == null ){ + checkForDefinition(); + } return (definition != null ) ? getCompositeTypeSpecifier().getScope() : null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java index 4182b9472c9..944df4ecca8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java @@ -1969,6 +1969,7 @@ public class CPPSemantics { IType [] sourceParameters = getSourceParameterTypes( data.functionParameters ); //the parameters the function is being called with IType [] targetParameters = null; + boolean sourceVoid = ( data.functionParameters == null || data.functionParameters.length == 0 ); int numSourceParams = 0; int targetLength = 0; int numFns = fns.length; @@ -2028,7 +2029,9 @@ public class CPPSemantics { } else if( varArgs ){ cost = new Cost( source, null ); cost.rank = Cost.ELLIPSIS_CONVERSION; - } else if( source.isSameType( target ) ){ + } else if( source.isSameType( target ) || + ( sourceVoid && ((useImplicitObj && j == 1)||(!useImplicitObj && j == 0)) ) ) + { cost = new Cost( source, target ); cost.rank = Cost.IDENTITY_RANK; //exact match, no cost } else { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java index df433c770cb..14d7a48e13e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java @@ -1679,6 +1679,9 @@ public class CPPVisitor { } else if( binding instanceof IVariable ){ try { IType t = ((IVariable)binding).getType(); + while( t instanceof ITypedef ){ + t = ((ITypedef)t).getType(); + } if( t instanceof IPointerType && ((IPointerType)t).getType() instanceof IFunctionType ){ IFunctionType ftype = (IFunctionType) ((IPointerType)t).getType(); if( ftype != null ) @@ -1751,7 +1754,7 @@ public class CPPVisitor { else if( expression instanceof IASTUnaryExpression ) { int op = ((IASTUnaryExpression)expression).getOperator(); - if( op == IASTTypeIdExpression.op_sizeof ){ + if( op == IASTUnaryExpression.op_sizeof ){ IScope scope = getContainingScope( expression ); try { IBinding [] bs = scope.find( SIZE_T ); @@ -1764,6 +1767,13 @@ public class CPPVisitor { } IType type = getExpressionType(((IASTUnaryExpression)expression).getOperand() ); + while( type instanceof ITypedef ){ + try { + type = ((ITypeContainer)type).getType(); + } catch (DOMException e) { + break; + } + } if( op == IASTUnaryExpression.op_star && (type instanceof IPointerType || type instanceof IArrayType) ){ try { return ((ITypeContainer)type).getType(); @@ -1814,6 +1824,9 @@ public class CPPVisitor { } else if( expression instanceof IASTArraySubscriptExpression ){ IType t = getExpressionType( ((IASTArraySubscriptExpression) expression).getArrayExpression() ); try { + while( t instanceof ITypedef ){ + t = ((ITypedef)t).getType(); + } if( t instanceof IPointerType ) return ((IPointerType)t).getType(); else if( t instanceof IArrayType )