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 a12a7f93b0f..ff9cf738bd4 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 @@ -9,12 +9,16 @@ * IBM Corporation - initial API and implementation * Ed Swartz (Nokia) * Markus Schorn (Wind River Systems) + * Andrew Ferguson (Symbian) *******************************************************************************/ /* * Created on Nov 29, 2004 */ package org.eclipse.cdt.core.parser.tests.ast2; +import java.io.BufferedReader; +import java.io.StringReader; +import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; @@ -1250,7 +1254,7 @@ public class AST2CPPTests extends AST2BaseTest { public void testConstructors() throws Exception { StringBuffer buffer = new StringBuffer(); - buffer.append("class A { A(); A( const A & ); }; "); //$NON-NLS-1$ + buffer.append("class A { A(void); A( const A & ); }; "); //$NON-NLS-1$ IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP); @@ -1274,7 +1278,223 @@ public class AST2CPPTests extends AST2BaseTest { assertTrue(qt.isConst()); assertSame(qt.getType(), A); } + + // class A {~A(); }; + // class B {~B(void); }; + public void testExplicitDestructor_183160() throws Exception { + // class F {(~)F(); }; + // class G {(~)G(void); }; + + BufferedReader br= new BufferedReader(new StringReader(getContents(1)[0].toString())); + for(String line= br.readLine(); line!=null; line= br.readLine()) { + IASTTranslationUnit tu = parse(line, ParserLanguage.CPP); + IASTSimpleDeclaration decl = (IASTSimpleDeclaration) tu.getDeclarations()[0]; + IASTCompositeTypeSpecifier compSpec = (IASTCompositeTypeSpecifier) decl.getDeclSpecifier(); + ICPPClassType A = (ICPPClassType) compSpec.getName().resolveBinding(); + + ICPPMethod[] methods = ((ICPPClassScope)A.getCompositeScope()).getImplicitMethods(); + assertNotNull(methods); + int count=0; + for(int i=0; i 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; + IType pType = new CPPReferenceType( new CPPQualifierType( clsType, true, false ) ); + IParameter [] ps = new IParameter [] { new CPPParameter( pType ) }; + + int i= 0; + ImplicitsAnalysis ia= new ImplicitsAnalysis( compTypeSpec ); + implicits= new ICPPMethod[ia.getImplicitsToDeclareCount()]; + + if( !ia.hasUserDeclaredConstructor() ) { + //default constructor: A(void) + ICPPMethod m = new CPPImplicitConstructor( this, className, voidPs ); + implicits[i++]=m; + addBinding( m ); + } + + if( !ia.hasUserDeclaredCopyConstructor() ) { + //copy constructor: A( const A & ) + + ICPPMethod m = new CPPImplicitConstructor( this, className, ps ); + implicits[i++]=m; + addBinding( m ); + } + + if( !ia.hasUserDeclaredCopyAssignmentOperator() ) { + //copy assignment operator: A& operator = ( const A & ) + IType refType = new CPPReferenceType( clsType ); + ICPPMethod m = new CPPImplicitMethod( this, ICPPASTOperatorName.OPERATOR_ASSIGN, refType, ps ); + implicits[i++]=m; + addBinding( m ); + } + + if( !ia.hasUserDeclaredDestructor() ) { + //destructor: ~A() + char [] dtorName = CharArrayUtils.concat( "~".toCharArray(), className ); //$NON-NLS-1$ + ICPPMethod m = new CPPImplicitMethod( this, dtorName, new CPPBasicType( IBasicType.t_unspecified, 0 ), voidPs ); + implicits[i++]=m; + addBinding( m ); + } } public IScope getParent() { @@ -390,3 +365,147 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { } } } + +/** + * Helps analyzis of the class declaration for user declared members relevent + * to deciding which implicit bindings to declare. + */ +class ImplicitsAnalysis { + private boolean hasUserDeclaredConstructor; + private boolean hasUserDeclaredCopyConstructor; + private boolean hasUserDeclaredCopyAssignmentOperator; + private boolean hasUserDeclaredDestructor; + + ImplicitsAnalysis( ICPPASTCompositeTypeSpecifier compSpec ) { + ICPPASTFunctionDeclarator[] ctors= getUserDeclaredCtorOrDtor(compSpec, true); + + hasUserDeclaredConstructor= ctors.length> 0; + hasUserDeclaredCopyConstructor= false; + hasUserDeclaredCopyAssignmentOperator= false; + hasUserDeclaredDestructor= getUserDeclaredCtorOrDtor(compSpec, false).length>0; + + outer: for(int i=0; i= 1 ){ + if(paramHasTypeReferenceToTheAssociatedClassType(ps[0])) { + // and all remaining arguments have initializers + for(int j=1; j 0; + hasUserDeclaredCopyAssignmentOperator= hasUserDeclaredCAO; + } + + public int getImplicitsToDeclareCount() { + return (!hasUserDeclaredDestructor ? 1 : 0) + + (!hasUserDeclaredConstructor ? 1 : 0) + + (!hasUserDeclaredCopyConstructor ? 1 : 0) + + (!hasUserDeclaredCopyAssignmentOperator ? 1 : 0); + } + + private static ICPPASTFunctionDeclarator[] getUserDeclaredCtorOrDtor( ICPPASTCompositeTypeSpecifier compSpec, boolean constructor ) { + List result= new ArrayList(); + IASTDeclaration [] members = compSpec.getMembers(); + char [] name = compSpec.getName().toCharArray(); + IASTDeclarator dcltor = 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; + dcltor = dtors[0]; + spec = ((IASTSimpleDeclaration)members[i]).getDeclSpecifier(); + } else if( members[i] instanceof IASTFunctionDefinition ){ + dcltor = ((IASTFunctionDefinition)members[i]).getDeclarator(); + spec = ((IASTFunctionDefinition)members[i]).getDeclSpecifier(); + } + + + if( !(dcltor instanceof ICPPASTFunctionDeclarator) || !(spec instanceof IASTSimpleDeclSpecifier) || + ((IASTSimpleDeclSpecifier)spec).getType() != IASTSimpleDeclSpecifier.t_unspecified) + { + continue; + } + + boolean nameEquals= false; + if(constructor) { + nameEquals= CharArrayUtils.equals( dcltor.getName().toCharArray(), name ); + } else { + char[] cname= dcltor.getName().toCharArray(); + if(cname.length>0 && cname[0]=='~') { + nameEquals= CharArrayUtils.equals( cname, 1, name.length, name ); + } + } + + if(!nameEquals) + continue; + + result.add(dcltor); + } + return (ICPPASTFunctionDeclarator[]) result.toArray(new ICPPASTFunctionDeclarator[result.size()]); + } + + private static ICPPASTFunctionDeclarator[] getUserDeclaredCopyAssignmentOperators( ICPPASTCompositeTypeSpecifier compSpec ) { + List result= new ArrayList(); + IASTDeclaration [] members = compSpec.getMembers(); + IASTDeclarator dcltor = 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; + dcltor = dtors[0]; + } else if( members[i] instanceof IASTFunctionDefinition ){ + dcltor = ((IASTFunctionDefinition)members[i]).getDeclarator(); + } + if( !(dcltor instanceof ICPPASTFunctionDeclarator) || + !CharArrayUtils.equals( dcltor.getName().toCharArray(), ICPPASTOperatorName.OPERATOR_ASSIGN ) ) + { + continue; + } + + IASTParameterDeclaration [] ps = ((ICPPASTFunctionDeclarator)dcltor).getParameters(); + if( ps.length != 1 || !paramHasTypeReferenceToTheAssociatedClassType(ps[0]) ) + continue; + + result.add(dcltor); + } + return (ICPPASTFunctionDeclarator[]) result.toArray(new ICPPASTFunctionDeclarator[result.size()]); + } + + private static boolean paramHasTypeReferenceToTheAssociatedClassType(IASTParameterDeclaration dec) { + boolean result= false; + IASTDeclarator pdtor= dec.getDeclarator(); + if(pdtor.getPointerOperators().length==1 && pdtor.getPointerOperators()[0] instanceof ICPPASTReferenceOperator) { + if(dec.getDeclSpecifier() instanceof ICPPASTNamedTypeSpecifier) { + result= true; + } + } + return result; + } + + public boolean hasUserDeclaredConstructor() { + return hasUserDeclaredConstructor; + } + + public boolean hasUserDeclaredCopyConstructor() { + return hasUserDeclaredCopyConstructor; + } + + public boolean hasUserDeclaredCopyAssignmentOperator() { + return hasUserDeclaredCopyAssignmentOperator; + } + + public boolean hasUserDeclaredDestructor() { + return hasUserDeclaredDestructor; + } +} \ No newline at end of file