diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 250f1e50d0d..d87542a3293 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -34,6 +34,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPDelegate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; @@ -1673,4 +1674,78 @@ public class AST2TemplateTests extends AST2BaseTest { assertSame( col.getName(5).resolveBinding(), col.getName(6).resolveBinding() ); } + + public void testBug99254() throws Exception{ + StringBuffer buffer = new StringBuffer(); + buffer.append("template class A { \n"); + buffer.append(" A( T t ); \n"); + buffer.append("}; \n"); + buffer.append("void f( A a ); \n"); + buffer.append("void m(){ \n"); + buffer.append(" f( A(1) ); \n"); + buffer.append("} \n"); + + IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP ); + CPPNameCollector col = new CPPNameCollector(); + tu.accept( col ); + + ICPPConstructor ctor = (ICPPConstructor) col.getName(2).resolveBinding(); + ICPPFunction f = (ICPPFunction) col.getName(5).resolveBinding(); + + ICPPSpecialization spec = (ICPPSpecialization) col.getName(11).resolveBinding(); + assertSame( spec.getSpecializedBinding(), ctor ); + + assertSame( f, col.getName(10).resolveBinding() ); + } + + public void testBug99254_2() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("namespace core { \n"); + buffer.append(" template class A { \n"); + buffer.append(" A( T x, T y ); \n"); + buffer.append(" }; \n"); + buffer.append("} \n"); + buffer.append("class B { \n"); + buffer.append(" int add(const core::A &rect ); \n"); + buffer.append("}; \n"); + buffer.append("void f( B* b ){ \n"); + buffer.append(" b->add( core::A(10, 2) ); \n"); + buffer.append("} \n"); + + IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP ); + CPPNameCollector col = new CPPNameCollector(); + tu.accept( col ); + + ICPPConstructor ctor = (ICPPConstructor) col.getName(3).resolveBinding(); + ICPPMethod add = (ICPPMethod) col.getName(9).resolveBinding(); + + ICPPSpecialization spec = (ICPPSpecialization) col.getName(20).resolveBinding(); + assertSame( spec.getSpecializedBinding(), ctor ); + + assertSame( add, col.getName(19).resolveBinding() ); + } + + public void testBug99254_3() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("template class A { A( T ); }; \n"); + buffer.append("typedef signed int s32; \n"); + buffer.append("class B { \n"); + buffer.append(" int add(const A &rect ); \n"); + buffer.append("}; \n"); + buffer.append("void f( B* b ){ \n"); + buffer.append(" b->add( A(10) ); \n"); + buffer.append("} \n"); + + IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP ); + CPPNameCollector col = new CPPNameCollector(); + tu.accept( col ); + + ICPPConstructor ctor = (ICPPConstructor) col.getName(2).resolveBinding(); + ICPPMethod add = (ICPPMethod) col.getName(7).resolveBinding(); + + ICPPSpecialization spec = (ICPPSpecialization) col.getName(17).resolveBinding(); + assertSame( spec.getSpecializedBinding(), ctor ); + + assertSame( add, col.getName(16).resolveBinding() ); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java index b9d88703645..6b38696fc0a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java @@ -63,6 +63,13 @@ public class CPPBasicType implements ICPPBasicType { return false; CPPBasicType t = (CPPBasicType) object; + if( type != t.type ) + return false; + + if( type == IBasicType.t_int ){ + //signed int and int are equivalent + return (qualifierBits & ~IS_SIGNED ) == (t.qualifierBits & ~IS_SIGNED ); + } return ( type == t.type && qualifierBits == t.qualifierBits ); } /* (non-Javadoc) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassInstance.java index 56035a5b95e..e3f0e539f53 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassInstance.java @@ -104,7 +104,10 @@ public class CPPClassInstance extends CPPInstance implements ICPPClassType, ICPP * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType#getConstructors() */ public ICPPConstructor[] getConstructors() throws DOMException { - return new ICPPConstructor[0]; + CPPClassInstanceScope scope = (CPPClassInstanceScope) getCompositeScope(); + if( scope.isFullyCached() ) + return scope.getConstructors(); + return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY; } /* (non-Javadoc) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassInstanceScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassInstanceScope.java index 96dfcfabc5c..85234acd690 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassInstanceScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassInstanceScope.java @@ -14,6 +14,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; @@ -22,10 +23,12 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.ObjectMap; import org.eclipse.cdt.core.parser.util.ObjectSet; @@ -33,11 +36,15 @@ import org.eclipse.cdt.core.parser.util.ObjectSet; * @author aniefer */ public class CPPClassInstanceScope implements ICPPClassScope { + private static final char[] CONSTRUCTOR_KEY = "!!!CTOR!!!".toCharArray(); //$NON-NLS-1$ + private CharArrayObjectMap bindings; private ObjectMap instanceMap = ObjectMap.EMPTY_MAP; private ICPPTemplateInstance instance; private boolean isFullyCached = false; + private boolean doneConstructors = false; + /** * @param instance */ @@ -60,11 +67,14 @@ public class CPPClassInstanceScope implements ICPPClassScope { } public IBinding getBinding( IASTName name, boolean forceResolve ) { - //ICPPClassScope scope = (ICPPClassScope) getOriginalClass().getCompositeScope(); char [] c = name.toCharArray(); if( bindings == null ) return null; + if( CharArrayUtils.equals( c, instance.getNameCharArray() ) && CPPClassScope.isConstructorReference( name ) ){ + c = CONSTRUCTOR_KEY; + } + Object cache = bindings.get( c ); if( cache != null ){ int i = ( cache instanceof ObjectSet ) ? 0 : -1; @@ -150,13 +160,17 @@ public class CPPClassInstanceScope implements ICPPClassScope { return; if( bindings == null ) - bindings = new CharArrayObjectMap(1); + bindings = new CharArrayObjectMap(1); char [] c = name.toCharArray(); + + IASTNode parent = name.getParent(); + if( parent instanceof IASTDeclarator && CPPVisitor.isConstructor( this, (IASTDeclarator) parent ) ){ + c = CONSTRUCTOR_KEY; + } Object o = bindings.get( c ); if( o != null ){ if( o instanceof ObjectSet ){ ((ObjectSet)o).put( name ); - //bindings.put( c, ArrayUtil.append( Object.class, (Object[]) o, name ) ); } else { ObjectSet temp = new ObjectSet( 2 ); temp.put( o ); @@ -168,6 +182,36 @@ public class CPPClassInstanceScope implements ICPPClassScope { } } + protected ICPPConstructor [] getConstructors( ){ + if( bindings == null ) + return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY; + + if( !doneConstructors ){ + ICPPConstructor[] ctors; + try { + ctors = ((ICPPClassType)instance.getTemplateDefinition()).getConstructors(); + for (int i = 0; i < ctors.length; i++) { + addBinding( ctors[i] ); + } + doneConstructors = true; + } catch (DOMException e) { + } + } + ICPPConstructor[] ctors = CPPClassScope.getConstructors( bindings, true ); + for (int i = 0; i < ctors.length; i++) { + if( instanceMap.containsKey( ctors[i] ) ){ + ctors[i] = (ICPPConstructor) instanceMap.get( ctors[i] ); + } else { + IBinding b = CPPTemplates.createSpecialization( this, ctors[i], instance.getArgumentMap() ); + if( instanceMap == ObjectMap.EMPTY_MAP ) + instanceMap = new ObjectMap(2); + instanceMap.put( ctors[i], b ); + ctors[i] = (ICPPConstructor) b; + } + } + return ctors; + } + /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPScope#setFullyCached(boolean) */ @@ -248,7 +292,7 @@ public class CPPClassInstanceScope implements ICPPClassScope { public void addBinding(IBinding binding) { if( bindings == null ) bindings = new CharArrayObjectMap(1); - char [] c = binding.getNameCharArray(); + char [] c = (binding instanceof ICPPConstructor) ? CONSTRUCTOR_KEY : binding.getNameCharArray(); Object o = bindings.get( c ); if( o != null ){ if( o instanceof ObjectSet ){ 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 6b6cbd84f96..c08c3855425 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 @@ -43,6 +43,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.ObjectSet; @@ -50,8 +51,7 @@ import org.eclipse.cdt.core.parser.util.ObjectSet; * @author aniefer */ public class CPPClassScope extends CPPScope implements ICPPClassScope { - private ObjectSet constructorBindings = ObjectSet.EMPTY_SET; - private ObjectSet constructorNames = ObjectSet.EMPTY_SET; + private static final char [] CONSTRUCTOR_KEY = "!!!CTOR!!!".toCharArray(); //$NON-NLS-1$ private ICPPMethod[] implicits = null; public CPPClassScope( ICPPASTCompositeTypeSpecifier physicalNode ) { @@ -193,17 +193,26 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { } private void addConstructor( Object constructor ){ - if( constructor instanceof IBinding ){ - if( constructorBindings == ObjectSet.EMPTY_SET ) - constructorBindings = new ObjectSet( 2 ); - - constructorBindings.put( constructor ); - } else { - if( constructorNames == ObjectSet.EMPTY_SET ) - constructorNames = new ObjectSet( 2 ); - - constructorNames.put( constructor ); + if( bindings == null ) + bindings = new CharArrayObjectMap(1); + + if( constructor instanceof IASTName && ((IASTName)constructor).getBinding() != null ){ + constructor = ((IASTName)constructor).getBinding(); } + + Object o = bindings.get( CONSTRUCTOR_KEY ); + if( o != null ){ + if( o instanceof ObjectSet ){ + ((ObjectSet)o).put( constructor ); + } else { + ObjectSet set = new ObjectSet(2); + set.put( o ); + set.put( constructor ); + bindings.put( CONSTRUCTOR_KEY, set ); + } + } else { + bindings.put( CONSTRUCTOR_KEY, constructor ); + } } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPScope#getBinding(int, char[]) @@ -219,9 +228,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { } if( CharArrayUtils.equals( c, compName.toCharArray() ) ){ if( isConstructorReference( name ) ){ -// if( constructors == null ) -// return null; - return CPPSemantics.resolveAmbiguities( name, getConstructors( resolve ) ); + return CPPSemantics.resolveAmbiguities( name, getConstructors( bindings, resolve ) ); } //9.2 ... The class-name is also inserted into the scope of the class itself return compName.resolveBinding(); @@ -230,15 +237,47 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { } protected ICPPConstructor [] getConstructors( boolean forceResolve ){ - if( forceResolve && constructorNames.size() > 0 ){ - Object [] names = constructorNames.keyArray(); - for( int i = 0; i < names.length; i++ ){ - ICPPConstructor ctor = (ICPPConstructor) ((IASTName)names[i]).resolveBinding(); - constructorBindings.put( ctor ); - } - constructorNames.clear(); - } - return (ICPPConstructor[]) ArrayUtil.trim( ICPPConstructor.class, constructorBindings.keyArray(), true); + return getConstructors( bindings, forceResolve ); + } + static protected ICPPConstructor [] getConstructors( CharArrayObjectMap bindings, boolean forceResolve ){ + if( bindings == null ) + return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY; + + Object o = bindings.get( CONSTRUCTOR_KEY ); + if( o != null ){ + IBinding binding = null; + if( o instanceof ObjectSet ) { + ObjectSet set = (ObjectSet) o; + IBinding [] bs = null; + for( int i = 0; i < set.size(); i++ ){ + Object obj = set.keyAt( i ); + if( obj instanceof IASTName ){ + IASTName n = (IASTName) obj; + binding = n.getBinding(); + if( binding != null || forceResolve ){ + binding = n.resolveBinding(); + set.remove( n ); + set.put( binding ); + i--; + continue; + } + } else if( obj instanceof ICPPConstructor ) + bs = (IBinding[]) ArrayUtil.append( ICPPConstructor.class, bs, obj ); + } + return (ICPPConstructor[]) ArrayUtil.trim( ICPPConstructor.class, bs ); + } else if( o instanceof IASTName ){ + if( forceResolve || ((IASTName)o).getBinding() != null ){ + binding = ((IASTName)o).resolveBinding(); + bindings.put( CONSTRUCTOR_KEY, binding ); + } + } else if( o instanceof IBinding ){ + binding = (IBinding) o; + } + if( binding != null && binding instanceof ICPPConstructor){ + return new ICPPConstructor[] { (ICPPConstructor) binding }; + } + } + return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY; } /* (non-Javadoc) @@ -253,12 +292,12 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { compName = ns[ ns.length - 1 ]; } if( CharArrayUtils.equals( n, compName.toCharArray() ) ){ - return (IBinding[]) ArrayUtil.addAll( IBinding.class, null, getConstructors( true ) ); + return (IBinding[]) ArrayUtil.addAll( IBinding.class, null, getConstructors( bindings, true ) ); } return super.find( name ); } - private boolean isConstructorReference( IASTName name ){ + static protected boolean isConstructorReference( IASTName name ){ if( name.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY ) return false; IASTNode node = name.getParent(); if( node instanceof ICPPASTTemplateId ) @@ -313,21 +352,9 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { */ public void removeBinding(IBinding binding) { if( binding instanceof ICPPConstructor ){ - if( constructorBindings.containsKey( binding ) ) - constructorBindings.remove( binding ); - setFullyCached( false ); + removeBinding( CONSTRUCTOR_KEY, binding ); } else { - super.removeBinding( binding ); + removeBinding( binding.getNameCharArray(), binding ); } } - - public void flushCache() { - constructorNames.clear(); - for( int i = constructorBindings.size() - 1; i >= 0; i-- ){ - IBinding binding = (IBinding) constructorBindings.keyAt(i); - if( !(binding instanceof CPPImplicitConstructor) ) - constructorBindings.remove( binding ); - } - super.flushCache(); - } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java index 0dfe316730b..0295cd386be 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java @@ -17,6 +17,7 @@ import org.eclipse.cdt.core.dom.ast.DOMException; 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.IASTSimpleDeclaration; @@ -33,6 +34,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; @@ -267,8 +269,37 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType#getConstructors() */ - public ICPPConstructor[] getConstructors() { - return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY; + public ICPPConstructor[] getConstructors() throws DOMException { + if( definition == null ){ + checkForDefinition(); + if( definition == null ){ + IASTNode node = (declarations != null && declarations.length > 0) ? declarations[0] : null; + return new ICPPConstructor [] { new CPPConstructor.CPPConstructorProblem( node, IProblemBinding.SEMANTIC_DEFINITION_NOT_FOUND, getNameCharArray() ) }; + } + } + + ICPPClassScope scope = (ICPPClassScope) getCompositeScope(); + if( scope.isFullyCached() ) + return ((CPPClassScope)scope).getConstructors( true ); + + IASTDeclaration [] members = getCompositeTypeSpecifier().getMembers(); + for( int i = 0; i < members.length; i++ ){ + IASTDeclaration decl = members[i]; + if( decl instanceof ICPPASTTemplateDeclaration ) + decl = ((ICPPASTTemplateDeclaration)decl).getDeclaration(); + if( decl instanceof IASTSimpleDeclaration ){ + IASTDeclarator [] dtors = ((IASTSimpleDeclaration)decl).getDeclarators(); + for( int j = 0; j < dtors.length; j++ ){ + if( dtors[j] == null ) break; + scope.addName( dtors[j].getName() ); + } + } else if( decl instanceof IASTFunctionDefinition ){ + IASTDeclarator dtor = ((IASTFunctionDefinition)decl).getDeclarator(); + scope.addName( dtor.getName() ); + } + } + + return ((CPPClassScope)scope).getConstructors( true ); } /* (non-Javadoc) 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 3480e4e19fa..42b790c24a1 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 @@ -674,14 +674,17 @@ public class CPPClassType implements ICPPClassType, ICPPInternalClassType { IASTDeclaration [] members = getCompositeTypeSpecifier().getMembers(); for( int i = 0; i < members.length; i++ ){ - if( members[i] instanceof IASTSimpleDeclaration ){ - IASTDeclarator [] dtors = ((IASTSimpleDeclaration)members[i]).getDeclarators(); + IASTDeclaration decl = members[i]; + if( decl instanceof ICPPASTTemplateDeclaration ) + decl = ((ICPPASTTemplateDeclaration)decl).getDeclaration(); + if( decl instanceof IASTSimpleDeclaration ){ + IASTDeclarator [] dtors = ((IASTSimpleDeclaration)decl).getDeclarators(); for( int j = 0; j < dtors.length; j++ ){ if( dtors[j] == null ) break; scope.addName( dtors[j].getName() ); } - } else if( members[i] instanceof IASTFunctionDefinition ){ - IASTDeclarator dtor = ((IASTFunctionDefinition)members[i]).getDeclarator(); + } else if( decl instanceof IASTFunctionDefinition ){ + IASTDeclarator dtor = ((IASTFunctionDefinition)decl).getDeclarator(); scope.addName( dtor.getName() ); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorSpecialization.java new file mode 100644 index 00000000000..6fa099311d7 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorSpecialization.java @@ -0,0 +1,46 @@ +/************************************************************************* + * Copyright (c) 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + */ +/* + * Created on June 14, 2005 + */ + +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; +import org.eclipse.cdt.core.parser.util.ObjectMap; + +/** + * @author aniefer + * + */ +public class CPPConstructorSpecialization extends CPPMethodSpecialization + implements ICPPConstructor { + + /** + * @param orig + * @param scope + * @param argMap + */ + public CPPConstructorSpecialization(IBinding orig, ICPPScope scope, ObjectMap argMap) { + super(orig, scope, argMap); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor#isExplicit() + */ + public boolean isExplicit() throws DOMException { + return ((ICPPConstructor)getSpecializedBinding()).isExplicit(); + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorTemplateSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorTemplateSpecialization.java new file mode 100644 index 00000000000..6c601ec131a --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorTemplateSpecialization.java @@ -0,0 +1,46 @@ +/************************************************************************* + * Copyright (c) 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + */ +/* + * Created on June 14, 2005 + */ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; +import org.eclipse.cdt.core.parser.util.ObjectMap; + +/** + * @author aniefer + * + */ +public class CPPConstructorTemplateSpecialization extends + CPPMethodTemplateSpecialization implements ICPPConstructor { + + /** + * @param specialized + * @param scope + * @param argumentMap + */ + public CPPConstructorTemplateSpecialization(IBinding specialized, + ICPPScope scope, ObjectMap argumentMap) { + super(specialized, scope, argumentMap); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor#isExplicit() + */ + public boolean isExplicit() throws DOMException { + return ((ICPPConstructor)getSpecializedBinding()).isExplicit(); + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java index dd80603da13..c6b07fe04ea 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java @@ -141,11 +141,15 @@ abstract public class CPPScope implements ICPPScope{ * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPScope#removeBinding(org.eclipse.cdt.core.dom.ast.IBinding) */ public void removeBinding(IBinding binding) { - char [] name = binding.getNameCharArray(); - if( ! bindings.containsKey( name ) ) + char [] key = binding.getNameCharArray(); + removeBinding( key, binding ); + } + + protected void removeBinding( char [] key, IBinding binding ){ + if( bindings == null || ! bindings.containsKey( key ) ) return; - Object obj = bindings.get( name ); + Object obj = bindings.get( key ); if( obj instanceof ObjectSet ){ ObjectSet set = (ObjectSet) obj; for ( int i = set.size() - 1; i > 0; i-- ) { @@ -157,13 +161,12 @@ abstract public class CPPScope implements ICPPScope{ } } if( set.size() == 0 ) - bindings.remove( name, 0, name.length ); + bindings.remove( key, 0, key.length ); } else if( (obj instanceof IBinding && obj == binding) || (obj instanceof IASTName && ((IASTName)obj).getBinding() == binding) ) { - bindings.remove( name, 0, name.length ); + bindings.remove( key, 0, key.length ); } - isfull = false; } 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 e7339dcb106..b61c6e96445 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 @@ -259,13 +259,17 @@ public class CPPSemantics { return true; if( p1 instanceof ICPPASTNamedTypeSpecifier && p2 instanceof IASTTypeId ) return p2.getParent() instanceof ICPPASTNewExpression; - else if( p1 instanceof ICPPASTQualifiedName && p2 instanceof ICPPASTFunctionDeclarator ){ - IASTName[] names = ((ICPPASTQualifiedName)p1).getNames(); - if( names.length >= 2 && names[ names.length - 1 ] == astName ) - return CPPVisitor.isConstructor( names[ names.length - 2 ], (IASTDeclarator) p2 ); - } else if( p1 instanceof ICPPASTQualifiedName && p2 instanceof ICPPASTNamedTypeSpecifier ){ - IASTNode p3 = p2.getParent(); - return p3 instanceof IASTTypeId && p3.getParent() instanceof ICPPASTNewExpression; + else if( p1 instanceof ICPPASTQualifiedName ){ + if( p2 instanceof ICPPASTFunctionDeclarator ){ + IASTName[] names = ((ICPPASTQualifiedName)p1).getNames(); + if( names.length >= 2 && names[ names.length - 1 ] == astName ) + return CPPVisitor.isConstructor( names[ names.length - 2 ], (IASTDeclarator) p2 ); + } else if( p2 instanceof ICPPASTNamedTypeSpecifier ){ + IASTNode p3 = p2.getParent(); + return p3 instanceof IASTTypeId && p3.getParent() instanceof ICPPASTNewExpression; + } else if( p2 instanceof IASTIdExpression ){ + return p2.getParent() instanceof IASTFunctionCallExpression; + } } else if( p1 instanceof IASTFunctionCallExpression || p2 instanceof IASTFunctionCallExpression ) return true; return false; @@ -585,17 +589,24 @@ public class CPPSemantics { } } if( binding instanceof ICPPClassType && data.considerConstructors ){ - ICPPClassType cls = (ICPPClassType) binding; - try { - //force resolution of constructor bindings - IBinding [] ctors = cls.getConstructors(); - if( ctors.length > 0 && !(ctors[0] instanceof IProblemBinding) ){ - //then use the class scope to resolve which one. - binding = ((ICPPClassScope)cls.getCompositeScope()).getBinding( data.astName, true ); - } - } catch ( DOMException e ) { - binding = e.getProblem(); - } + ICPPClassType cls = (ICPPClassType) binding; + if( data.astName instanceof ICPPASTTemplateId && cls instanceof ICPPInternalTemplate ){ + ICPPASTTemplateId id = (ICPPASTTemplateId) data.astName; + IType [] args = CPPTemplates.createTypeArray( id.getTemplateArguments() ); + cls = (ICPPClassType) ((ICPPInternalTemplate)cls).instantiate( args ); + } + if( cls != null ){ + try { + //force resolution of constructor bindings + IBinding [] ctors = cls.getConstructors(); + if( ctors.length > 0 && !(ctors[0] instanceof IProblemBinding) ){ + //then use the class scope to resolve which one. + binding = ((ICPPClassScope)cls.getCompositeScope()).getBinding( data.astName, true ); + } + } catch ( DOMException e ) { + binding = e.getProblem(); + } + } } IASTName name = data.astName; @@ -2837,7 +2848,7 @@ public class CPPSemantics { //4.10-3 An rvalue of type "pointer to cv D", where D is a class type can be converted //to an rvalue of type "pointer to cv B", where B is a base class of D. else if( tPrev instanceof IPointerType && t instanceof ICPPClassType ){ - temp = hasBaseClass( (ICPPClassType)s, (ICPPClassType) t, true ); + temp = hasBaseClass( (ICPPClassType)s, (ICPPClassType) t, false ); cost.rank = ( temp > -1 ) ? Cost.CONVERSION_RANK : Cost.NO_MATCH_RANK; cost.conversion = ( temp > -1 ) ? temp : 0; cost.detail = 1; @@ -2872,7 +2883,7 @@ public class CPPSemantics { IType t = getUltimateType( cost.target, true ); if( cost.targetHadReference && s instanceof ICPPClassType && t instanceof ICPPClassType ){ - int temp = hasBaseClass( (ICPPClassType) s, (ICPPClassType) t, true ); + int temp = hasBaseClass( (ICPPClassType) s, (ICPPClassType) t, false ); if( temp > -1 ){ cost.rank = Cost.DERIVED_TO_BASE_CONVERSION; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateDefinition.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateDefinition.java index 9916985abc2..ab840a479a2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateDefinition.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateDefinition.java @@ -261,6 +261,8 @@ public abstract class CPPTemplateDefinition implements ICPPTemplateDefinition, I public ICPPTemplateParameter[] getTemplateParameters() { if( templateParameters == null ){ ICPPASTTemplateDeclaration template = CPPTemplates.getTemplateDeclaration( getTemplateName() ); + if( template == null ) + return ICPPTemplateParameter.EMPTY_TEMPLATE_PARAMETER_ARRAY; ICPPASTTemplateParameter [] params = template.getTemplateParameters(); ICPPTemplateParameter p = null; ICPPTemplateParameter [] result = null; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplates.java index 790c18c40c8..8d00a3537b5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplates.java @@ -56,6 +56,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplatedTypeTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate; @@ -390,7 +391,9 @@ public class CPPTemplates { } else { spec = ((ICPPInternalTemplate)function).getInstance( (IType[])map_types[1] ); if( spec == null ) { - if( function instanceof ICPPMethod ) + if( function instanceof ICPPConstructor ) + spec = new CPPConstructorSpecialization( function, scope, (ObjectMap) map_types[0] ); + else if( function instanceof ICPPMethod ) spec = new CPPMethodSpecialization( function, scope, (ObjectMap) map_types[0] ); else spec = new CPPFunctionSpecialization( function, scope, (ObjectMap) map_types[0] ); @@ -574,11 +577,16 @@ public class CPPTemplates { spec = new CPPClassSpecialization( decl, scope, argMap ); } else if( decl instanceof ICPPField ){ spec = new CPPFieldSpecialization( decl, scope, argMap ); - } else if( decl instanceof ICPPFunctionTemplate && decl instanceof ICPPMethod ){ - spec = new CPPMethodTemplateSpecialization( decl, scope, argMap ); } else if( decl instanceof ICPPFunctionTemplate ){ - spec = new CPPFunctionTemplateSpecialization( decl, scope, argMap ); - }else if( decl instanceof ICPPMethod ) { + if( decl instanceof ICPPConstructor ) + spec = new CPPConstructorTemplateSpecialization( decl, scope, argMap ); + else if( decl instanceof ICPPMethod ) + spec = new CPPMethodTemplateSpecialization( decl, scope, argMap ); + else + spec = new CPPFunctionTemplateSpecialization( decl, scope, argMap ); + } else if( decl instanceof ICPPConstructor ){ + spec = new CPPConstructorSpecialization( decl, scope, argMap ); + } else if( decl instanceof ICPPMethod ) { spec = new CPPMethodSpecialization( decl, scope, argMap ); } else if( decl instanceof ICPPFunction ) { spec = new CPPFunctionSpecialization( decl, scope, argMap ); 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 7ca3bbd02fe..ee5094b9cbb 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 @@ -1685,7 +1685,15 @@ public class CPPVisitor { } else if( expression instanceof IASTFunctionCallExpression ){ IBinding binding = resolveBinding( expression ); - if( binding instanceof IFunction ){ + if( binding instanceof ICPPConstructor ){ + ICPPClassScope scope; + try { + scope = (ICPPClassScope) ((ICPPConstructor)binding).getScope(); + } catch (DOMException e) { + return e.getProblem(); + } + return scope.getClassType(); + } else if( binding instanceof IFunction ){ IFunctionType fType; try { fType = ((IFunction)binding).getType(); @@ -1842,6 +1850,8 @@ public class CPPVisitor { } else if( expression instanceof IASTArraySubscriptExpression ){ IType t = getExpressionType( ((IASTArraySubscriptExpression) expression).getArrayExpression() ); try { + if( t instanceof ICPPReferenceType ) + t = ((ICPPReferenceType)t).getType(); while( t instanceof ITypedef ){ t = ((ITypedef)t).getType(); }