Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java')
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java2464
1 files changed, 0 insertions, 2464 deletions
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java
deleted file mode 100644
index 134f9159e32..00000000000
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java
+++ /dev/null
@@ -1,2464 +0,0 @@
-/**********************************************************************
- * Copyright (c) 2002,2003,2004 Rational Software 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:
- * Rational Software - Initial API and implementation
- *
-***********************************************************************/
-
-
-package org.eclipse.cdt.internal.core.parser.pst;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-import org.eclipse.cdt.core.parser.ParserLanguage;
-import org.eclipse.cdt.core.parser.ParserMode;
-import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
-import org.eclipse.cdt.core.parser.ast.IASTMember;
-import org.eclipse.cdt.core.parser.ast.IASTNode;
-import org.eclipse.cdt.internal.core.parser.pst.IDerivableContainerSymbol.IParentSymbol;
-import org.eclipse.cdt.internal.core.parser.scanner2.ObjectSet;
-import org.eclipse.cdt.internal.core.parser.scanner2.ObjectMap;
-
-/**
- * @author aniefer
- */
-
-public class ParserSymbolTable {
-
- public static final int TYPE_LOOP_THRESHOLD = 50;
- public static final int TEMPLATE_LOOP_THRESHOLD = 10;
- public static final String EMPTY_NAME = ""; //$NON-NLS-1$
- public static final String THIS = "this"; //$NON-NLS-1$
-
- /**
- * Constructor for ParserSymbolTable.
- */
- public ParserSymbolTable( ParserLanguage language, ParserMode mode ) {
- super();
- _compilationUnit = newContainerSymbol( EMPTY_NAME, ITypeInfo.t_namespace );
- _language = language;
- _mode = mode;
- _typeInfoProvider = new TypeInfoProvider();
- }
-
- public IContainerSymbol getCompilationUnit(){
- return _compilationUnit;
- }
-
- public IContainerSymbol newContainerSymbol( String name ){
- if( name == null ) name = EMPTY_NAME;
- return new ContainerSymbol( this, name );
- }
- public IContainerSymbol newContainerSymbol( String name, ITypeInfo.eType type ){
- if( name == null ) name = EMPTY_NAME;
- return new ContainerSymbol( this, name, type );
- }
-
- public ISymbol newSymbol( String name ){
- if( name == null ) name = EMPTY_NAME;
- return new BasicSymbol( this, name );
- }
- public ISymbol newSymbol( String name, ITypeInfo.eType type ){
- if( name == null ) name = EMPTY_NAME;
- return new BasicSymbol( this, name, type );
- }
-
- public IDerivableContainerSymbol newDerivableContainerSymbol( String name ){
- if( name == null ) name = EMPTY_NAME;
- return new DerivableContainerSymbol( this, name );
- }
- public IDerivableContainerSymbol newDerivableContainerSymbol( String name, ITypeInfo.eType type ){
- if( name == null ) name = EMPTY_NAME;
- return new DerivableContainerSymbol( this, name, type );
- }
- public IParameterizedSymbol newParameterizedSymbol( String name ){
- if( name == null ) name = EMPTY_NAME;
- return new ParameterizedSymbol( this, name );
- }
- public IParameterizedSymbol newParameterizedSymbol( String name, ITypeInfo.eType type ){
- if( name == null ) name = EMPTY_NAME;
- return new ParameterizedSymbol( this, name, type );
- }
- public ITemplateSymbol newTemplateSymbol( String name ){
- if( name == null ) name = EMPTY_NAME;
- return new TemplateSymbol( this, name );
- }
-
- public ISpecializedSymbol newSpecializedSymbol( String name ){
- if( name == null ) name = EMPTY_NAME;
- return new SpecializedSymbol( this, name );
- }
-
- public ITemplateFactory newTemplateFactory(){
- return new TemplateFactory( this );
- }
-
- /**
- * Lookup the name from LookupData starting in the inDeclaration
- * @param data
- * @param inDeclaration
- * @return Declaration
- * @throws ParserSymbolTableException
- */
- static protected void lookup( LookupData data, IContainerSymbol inSymbol ) throws ParserSymbolTableException
- {
- //handle namespace aliases
- if( inSymbol.isType( ITypeInfo.t_namespace ) ){
- ISymbol symbol = inSymbol.getForwardSymbol();
- if( symbol != null && symbol.isType( ITypeInfo.t_namespace ) ){
- inSymbol = (IContainerSymbol) symbol;
- }
- }
-
- ArrayList transitives = null; //list of transitive using directives
-
- //if this name define in this scope?
- Map map = null;
- if( !data.usingDirectivesOnly ){
- map = lookupInContained( data, inSymbol );
- if( data.foundItems == null || data.foundItems.isEmpty() ){
- data.foundItems = map;
- } else {
- mergeResults( data, data.foundItems, map );
- }
- }
-
- if( inSymbol.getSymbolTable().getLanguage() == ParserLanguage.CPP &&
- !data.ignoreUsingDirectives )
- {
- //check nominated namespaces
- //the transitives list is populated in LookupInNominated, and then
- //processed in ProcessDirectives
-
- data.visited.clear(); //each namesapce is searched at most once, so keep track
-
- transitives = lookupInNominated( data, inSymbol, transitives );
-
- //if we are doing a qualified lookup, only process using directives if
- //we haven't found the name yet (and if we aren't ignoring them).
- if( !data.qualified || data.foundItems == null || data.foundItems.isEmpty() ){
- processDirectives( inSymbol, data, transitives );
-
- if( inSymbol.hasUsingDirectives() ){
- processDirectives( inSymbol, data, inSymbol.getUsingDirectives() );
- }
-
- while( data.usingDirectives != null && data.usingDirectives.get( inSymbol ) != null ){
- if( transitives != null )
- transitives.clear();
-
- transitives = lookupInNominated( data, inSymbol, transitives );
-
- if( !data.qualified || data.foundItems == null ){
- processDirectives( inSymbol, data, transitives );
- }
- }
- }
- }
-
- if( !data.isPrefixLookup() && ( ( data.foundItems != null && !data.foundItems.isEmpty()) || data.getStopAt() == inSymbol ) ){
- return;
- }
-
- if( !data.usingDirectivesOnly && inSymbol instanceof IDerivableContainerSymbol ){
- //if we still havn't found it, check any parents we have
- data.visited.clear(); //each virtual base class is searched at most once
- map = lookupInParents( data, inSymbol );
-
- if( data.foundItems == null || data.foundItems.isEmpty() ){
- data.foundItems = map;
- } else {
- mergeInheritedResults( data.foundItems, map );
- }
- }
-
- //if still not found, check our containing scope.
- if( ( data.foundItems == null || data.foundItems.isEmpty() || data.isPrefixLookup() )
- && inSymbol.getContainingSymbol() != null )
- {
- if( data.qualified ){
- if( data.usingDirectives != null && !data.usingDirectives.isEmpty() ){
- data.usingDirectivesOnly = true;
- lookup( data, inSymbol.getContainingSymbol() );
-
- }
- } else {
- lookup( data, inSymbol.getContainingSymbol() );
- }
-
- }
-
- return;
- }
-
- /**
- * function LookupInNominated
- * @param data
- * @param transitiveDirectives
- * @return List
- *
- * for qualified:
- * 3.4.3.2-2 "let S be the set of all declarations of m in X
- * and in the transitive closure of all namespaces nominated by using-
- * directives in X and its used namespaces, except that using-directives are
- * ignored in any namespace, including X, directly containing one or more
- * declarations of m."
- *
- * for unqualified:
- * 7.3.4-2 The using-directive is transitive: if a scope contains a using
- * directive that nominates a second namespace that itself contains using-
- * directives, the effect is as if the using-directives from the second
- * namespace also appeared in the first.
- */
- static private ArrayList lookupInNominated( LookupData data, IContainerSymbol symbol, ArrayList transitiveDirectives ) throws ParserSymbolTableException{
- //if the data.usingDirectives is empty, there is nothing to do.
- if( data.usingDirectives == null ){
- return transitiveDirectives;
- }
-
- //local variables
- ArrayList directives = null; //using directives association with declaration
- IContainerSymbol temp = null;
-
- boolean foundSomething = false;
- int size = 0;
-
- directives = (ArrayList) data.usingDirectives.remove( symbol );
-
- if( directives == null ){
- return transitiveDirectives;
- }
-
- size = directives.size();
- for( int i = 0; i < size; i++ ){
- temp = (IContainerSymbol) directives.get(i);
-
- //namespaces are searched at most once
- if( !data.visited.containsKey( temp ) ){
- data.visited.put( temp );
-
- Map map = lookupInContained( data, temp );
- foundSomething = ( map != null && !map.isEmpty() );
- if( foundSomething ){
- if( data.foundItems == null )
- data.foundItems = map;
- else
- mergeResults( data, data.foundItems, map );
- }
-
- //only consider the transitive using directives if we are an unqualified
- //lookup, or we didn't find the name in decl
- if( (!data.qualified || !foundSomething || data.isPrefixLookup() ) && temp.hasUsingDirectives() ){
- //name wasn't found, add transitive using directives for later consideration
- if( transitiveDirectives == null )
- transitiveDirectives = new ArrayList(4);
- transitiveDirectives.addAll( temp.getUsingDirectives() );
- }
- }
- }
-
- return transitiveDirectives;
- }
-
- /**
- * @param map
- * @param map2
- */
- private static void mergeResults( LookupData data, Map resultMap, Map map ) throws ParserSymbolTableException {
- if( resultMap == null || map == null || map.isEmpty() ){
- return;
- }
-
- Iterator keyIterator = map.keySet().iterator();
- Object key = null;
- while( keyIterator.hasNext() ){
- key = keyIterator.next();
- if( resultMap.containsKey( key ) ){
- List list = new ArrayList();
- Object obj = resultMap.get( key );
-
- if ( obj instanceof List ) list.addAll( (List) obj );
- else list.add( obj );
-
- obj = map.get( key );
-
- if( obj instanceof List ) list.addAll( (List) obj );
- else list.add( obj );
-
- resultMap.put( key, collectSymbol( data, list ) );
- } else {
- resultMap.put( key, map.get( key ) );
- }
- }
- }
-
- /**
- * function LookupInContained
- * @param data
- * @return List
- *
- * Look for data.name in our collection _containedDeclarations
- */
- protected static Map lookupInContained( LookupData data, IContainerSymbol lookIn ) throws ParserSymbolTableException{
- Map found = null;
-
- Object obj = null;
-
- if( data.getAssociated() != null ){
- //we are looking in lookIn, remove it from the associated scopes list
- data.getAssociated().remove( lookIn );
- }
-
- ObjectMap declarations = lookIn.getContainedSymbols();
-
- int numKeys = -1;
- int idx = 0;
- if( data.isPrefixLookup() && declarations != Collections.EMPTY_MAP ){
- numKeys = declarations.size();//iterator = declarations.keySet().iterator();
- }
-
- String name = ( numKeys > 0 ) ? (String) declarations.keyAt( idx++ ) : data.name;
-
- while( name != null ) {
- if( nameMatches( data, name ) ){
- obj = ( declarations.size() > 0 ) ? declarations.get( name ) : null;
- if( obj != null ){
- obj = collectSymbol( data, obj );
-
- if( obj != null ){
- if( found == null ){
- if( data.isPrefixLookup() )
- found = new TreeMap( new ContainerSymbol.SymbolTableComparator() );
- else
- found = new LinkedHashMap();
- }
- found.put( name, obj );
- }
- }
- }
- if( idx < numKeys )
- name = (String) declarations.keyAt( idx++ );
- else
- name = null;
- }
- if( found != null && data.isPrefixLookup() )
- found = new LinkedHashMap( found );
-
- if( found != null && !data.isPrefixLookup() ){
- return found;
- }
-
- if( lookIn instanceof IParameterizedSymbol ){
- found = lookupInParameters(data, lookIn, found);
- }
-
- if( lookIn.isTemplateMember() && data.templateMember == null ){
- IContainerSymbol containing = lookIn.getContainingSymbol();
- IContainerSymbol outer = (containing != null ) ? containing.getContainingSymbol() : null;
- if( ( containing instanceof IDerivableContainerSymbol && outer instanceof ITemplateSymbol) ||
- ( lookIn instanceof IParameterizedSymbol && containing instanceof ITemplateSymbol ) ||
- ( lookIn instanceof IDerivableContainerSymbol && containing instanceof ITemplateSymbol ) )
- {
- data.templateMember = lookIn;
- }
- }
-
- return found;
-
- }
- /**
- * @param data
- * @param lookIn
- * @param found
- * @throws ParserSymbolTableException
- */
- private static Map lookupInParameters(LookupData data, IContainerSymbol lookIn, Map found) throws ParserSymbolTableException {
- Object obj;
- Iterator iterator;
- String name;
-
- if( lookIn instanceof ITemplateSymbol && !((ITemplateSymbol)lookIn).getDefinitionParameterMap().isEmpty() ){
- ITemplateSymbol template = (ITemplateSymbol) lookIn;
- if( data.templateMember != null && template.getDefinitionParameterMap().containsKey( data.templateMember ) ){
- Map map = (Map) template.getDefinitionParameterMap().get( data.templateMember );
- iterator = map.keySet().iterator();
- while( iterator.hasNext() ){
- ISymbol symbol = (ISymbol) iterator.next();
- if( nameMatches( data, symbol.getName() ) ){
- obj = collectSymbol( data, symbol );
- if( obj != null ){
- if( found == null ){
- if( data.isPrefixLookup() )
- found = new TreeMap( new ContainerSymbol.SymbolTableComparator() );
- else
- found = new LinkedHashMap();
- }
- found.put( symbol.getName(), obj );
- }
- }
- }
- return ( found instanceof TreeMap ) ? new LinkedHashMap( found ) : found;
- }
-
- }
- Map parameters = ((IParameterizedSymbol)lookIn).getParameterMap();
- if( parameters != Collections.EMPTY_MAP ){
- iterator = null;
- if( data.isPrefixLookup() ){
- iterator = parameters.keySet().iterator();
- }
-
- name = ( iterator != null && iterator.hasNext() ) ? (String) iterator.next() : data.name;
- while( name != null ){
- if( nameMatches( data, name ) ){
- obj = parameters.get( name );
- obj = collectSymbol( data, obj );
- if( obj != null ){
- if( found == null ){
- if( data.isPrefixLookup() )
- found = new TreeMap( new ContainerSymbol.SymbolTableComparator() );
- else
- found = new LinkedHashMap();
- }
- found.put( name, obj );
- }
- }
-
- if( iterator != null && iterator.hasNext() ){
- name = (String) iterator.next();
- } else {
- name = null;
- }
- }
- }
- return ( found instanceof TreeMap ) ? new LinkedHashMap( found ) : found;
- }
-
- private static boolean nameMatches( LookupData data, String name ){
- if( data.isPrefixLookup() ){
- return name.regionMatches( true, 0, data.name, 0, data.name.length() );
- }
- return name.equals( data.name );
- }
- private static boolean checkType( LookupData data, ISymbol symbol ) {
- if( data.getFilter() == null ){
- return true;
- }
-
- TypeInfoProvider provider = symbol.getSymbolTable().getTypeInfoProvider();
- ITypeInfo typeInfo = ParserSymbolTable.getFlatTypeInfo( symbol.getTypeInfo(), provider );
- boolean accept = data.getFilter().shouldAccept( symbol, typeInfo ) || data.getFilter().shouldAccept( symbol );
- provider.returnTypeInfo( typeInfo );
-
- return accept;
- }
-
- private static Object collectSymbol(LookupData data, Object object ) throws ParserSymbolTableException {
- if( object == null ){
- return null;
- }
-
- ISymbol foundSymbol = null;
-
- List objList = ( object instanceof List ) ? (List)object : null;
- int objListSize = ( objList != null ) ? objList.size() : 0;
- ISymbol symbol = ( objList != null ) ? (ISymbol) objList.get( 0 ) : (ISymbol) object;
-
- ObjectSet functionSet = ObjectSet.EMPTY_SET;
- ObjectSet templateFunctionSet = ObjectSet.EMPTY_SET;
-
- ISymbol obj = null;
- IContainerSymbol cls = null;
- int idx = 1;
- while( symbol != null ){
- if( symbol instanceof ITemplateSymbol ){
- ISymbol temp = ((ITemplateSymbol)symbol).getTemplatedSymbol();
- symbol = ( temp != null ) ? temp : symbol;
- }
-
- if( ( data.returnInvisibleSymbols || !symbol.getIsInvisible() ) && checkType( data, symbol ) ){
- foundSymbol = symbol;
-
- if( foundSymbol.isType( ITypeInfo.t_function ) ){
- if( foundSymbol.isForwardDeclaration() && foundSymbol.getForwardSymbol() != null &&
- foundSymbol.getForwardSymbol().getContainingSymbol() == foundSymbol.getContainingSymbol() )
- {
- foundSymbol = foundSymbol.getForwardSymbol();
- }
- if( foundSymbol.getContainingSymbol().isType( ITypeInfo.t_template ) ){
- if( templateFunctionSet == ObjectSet.EMPTY_SET )
- templateFunctionSet = new ObjectSet( 2 );
- templateFunctionSet.put( foundSymbol );
- } else {
- if( functionSet == ObjectSet.EMPTY_SET )
- functionSet = new ObjectSet( 2 );
- functionSet.put( foundSymbol );
- }
-
- } else {
- //if this is a class-name, other stuff hides it
- if( foundSymbol.isType( ITypeInfo.t_class, ITypeInfo.t_enumeration ) ){
- if( cls == null ){
- cls = (IContainerSymbol) foundSymbol;
- } else {
- if( cls.isForwardDeclaration() && cls.getForwardSymbol() == foundSymbol ){
- //cls is a forward declaration of decl, we want decl.
- cls = (IContainerSymbol) foundSymbol;
- } else if( foundSymbol.isForwardDeclaration() && foundSymbol.getForwardSymbol() == cls ){
- //decl is a forward declaration of cls, we already have what we want (cls)
- } else {
- if( data.isPrefixLookup() ){
- data.addAmbiguity( foundSymbol.getName() );
- } else {
- throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
- }
- }
- }
- } else {
- //an object, can only have one of these
- if( obj == null ){
- obj = foundSymbol;
- } else {
- if( obj.isForwardDeclaration() && obj.getForwardSymbol() == foundSymbol )
- obj = foundSymbol;
- else if( foundSymbol.isForwardDeclaration() && foundSymbol.getForwardSymbol() == obj ){
- //we already have what we want.
- } else if( data.isPrefixLookup() ){
- data.addAmbiguity( foundSymbol.getName() );
- } else {
- throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
- }
- }
- }
- }
- }
-
- if( objList != null && idx < objListSize ){
- symbol = (ISymbol) objList.get( idx++ );
- } else {
- symbol = null;
- }
- }
-
- int numFunctions = functionSet.size();
- int numTemplateFunctions = templateFunctionSet.size();
-
- boolean ambiguous = false;
-
- if( cls != null ){
- //the class is only hidden by other stuff if they are from the same scope
- if( obj != null && cls.getContainingSymbol() != obj.getContainingSymbol()){
- ambiguous = true;
- }
-
- IParameterizedSymbol fn = null;
- if( numTemplateFunctions > 0 ){
- for( int i = 0; i < numTemplateFunctions; i++ ){
- fn = (IParameterizedSymbol) templateFunctionSet.keyAt( i );
- if( cls.getContainingSymbol()!= fn.getContainingSymbol()){
- ambiguous = true;
- break;
- }
- }
- }
- if( numFunctions > 0 ){
- for( int i = 0; i < numFunctions; i++ ){
- fn = (IParameterizedSymbol) functionSet.keyAt( i );
- if( cls.getContainingSymbol()!= fn.getContainingSymbol()){
- ambiguous = true;
- break;
- }
- }
- }
- }
-
- if( numTemplateFunctions > 0 ){
- if( data.getParameters() != null && ( !data.exactFunctionsOnly || data.getTemplateParameters() != null ) ){
- List fns = TemplateEngine.selectTemplateFunctions( templateFunctionSet, data.getParameters(), data.getTemplateParameters() );
- if( fns != null ){
- if( functionSet == ObjectSet.EMPTY_SET )
- functionSet = new ObjectSet( fns.size() );
- functionSet.addAll( fns );
- }
- numFunctions = functionSet.size();
- } else {
- if( functionSet == ObjectSet.EMPTY_SET )
- functionSet = new ObjectSet( templateFunctionSet.size() );
- functionSet.addAll( templateFunctionSet );
- numFunctions += numTemplateFunctions;
- }
- }
-
- if( obj != null && !ambiguous ){
- if( numFunctions > 0 ){
- ambiguous = true;
- } else {
- return obj;
- }
- } else if( numFunctions > 0 ) {
- return functionSet.toList();
- }
-
- if( ambiguous ){
- if( data.isPrefixLookup() ){
- data.addAmbiguity( foundSymbol.getName() );
- } else {
- throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
- }
- }
-
- return cls;
- }
- /**
- *
- * @param data
- * @param lookIn
- * @return Declaration
- * @throws ParserSymbolTableException
- */
- private static Map lookupInParents( LookupData data, ISymbol lookIn ) throws ParserSymbolTableException{
- IDerivableContainerSymbol container = null;
-
- if( lookIn instanceof IDerivableContainerSymbol ){
- container = (IDerivableContainerSymbol) lookIn;
- } else{
- throw new ParserSymbolTableError( ParserSymbolTableError.r_InternalError );
- }
-
- List scopes = container.getParents();
-
- Map temp = null;
- Map symbol = null;
- Map inherited = null;
-
- IDerivableContainerSymbol.IParentSymbol wrapper = null;
-
- if( scopes == null )
- return null;
-
- //use data to detect circular inheritance
- if( data.inheritanceChain == null )
- data.inheritanceChain = new ObjectSet( 2 );
-
- data.inheritanceChain.put( container );
-
- int size = scopes.size();
- for( int i = 0; i < size; i++ )
- {
- wrapper = (IDerivableContainerSymbol.IParentSymbol) scopes.get(i);
- ISymbol parent = wrapper.getParent();
- if( parent == null )
- continue;
-
- if( !wrapper.isVirtual() || !data.visited.containsKey( parent ) ){
- if( wrapper.isVirtual() ){
- data.visited.put( parent );
- }
-
- if( parent instanceof IDeferredTemplateInstance ){
- parent = ((IDeferredTemplateInstance)parent).getTemplate().getTemplatedSymbol();
- } else if( parent instanceof ITemplateSymbol ){
- parent = ((ITemplateSymbol)parent).getTemplatedSymbol();
- }
-
- //if the inheritanceChain already contains the parent, then that
- //is circular inheritance
- if( ! data.inheritanceChain.containsKey( parent ) ){
- //is this name define in this scope?
- if( parent instanceof IDerivableContainerSymbol ){
- temp = lookupInContained( data, (IDerivableContainerSymbol) parent );
- } else {
- throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
- }
-
- if( (temp == null || temp.isEmpty()) || data.isPrefixLookup() ){
- inherited = lookupInParents( data, parent );
- if( temp == null )
- temp = inherited;
- else
- mergeInheritedResults( temp, inherited );
- }
- } else {
- throw new ParserSymbolTableException( ParserSymbolTableException.r_CircularInheritance );
- }
- }
-
- if( temp != null && !temp.isEmpty() ){
- if( symbol == null || symbol.isEmpty() ){
- symbol = temp;
- } else if ( temp != null && !temp.isEmpty() ) {
- Iterator iter = temp.keySet().iterator();
- Object key = null;
- while( iter.hasNext() ){
- key = iter.next();
- if( symbol.containsKey( key ) ){
- Object obj = symbol.get( key );
- List objList = ( obj instanceof List ) ? (List)obj : null;
- int objListSize = ( objList != null ) ? objList.size() : 0, idx = 1;
- ISymbol sym = (ISymbol) (( objList != null && objListSize > 0 ) ? objList.get(0) : obj);
- while( sym != null ){
- if( !checkAmbiguity( sym, temp.get( key ) ) ){
- if( data.isPrefixLookup() ){
- data.addAmbiguity( sym.getName() );
- } else {
- throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
- }
- }
-
- if( objList != null && idx < objListSize ){
- sym = (ISymbol) objList.get( idx++ );
- } else {
- sym = null;
- }
- }
- } else {
- symbol.put( key, temp.get( key ) );
- }
- }
- }
- } else {
- temp = null; //reset temp for next iteration
- }
- }
-
- data.inheritanceChain.remove( container );
-
- return symbol;
- }
-
- private static boolean checkAmbiguity( Object obj1, Object obj2 ){
- //it is not ambiguous if they are the same thing and it is static or an enumerator
- if( obj1 == obj2 ){
- List objList = ( obj1 instanceof List ) ? (List) obj1 : null;
- int objListSize = ( objList != null ) ? objList.size() : 0;
- ISymbol symbol = ( objList != null ) ? (ISymbol) objList.get(0) : ( ISymbol )obj1;
- int idx = 1;
- while( symbol != null ) {
- ITypeInfo type = ((ISymbol)obj1).getTypeInfo();
- if( !type.checkBit( ITypeInfo.isStatic ) && !type.isType( ITypeInfo.t_enumerator ) ){
- return false;
- }
-
- if( objList != null && idx < objListSize ){
- symbol = (ISymbol) objList.get( idx++ );
- } else {
- symbol = null;
- }
- }
- return true;
- }
- return false;
- }
-
- /**
- * Symbols in map are added to the resultMap if a symbol with that name does not already exist there
- * @param resultMap
- * @param map
- * @throws ParserSymbolTableException
- */
- private static void mergeInheritedResults( Map resultMap, Map map ){
- if( resultMap == null || map == null || map.isEmpty() ){
- return;
- }
-
- Iterator keyIterator = map.keySet().iterator();
- Object key = null;
- while( keyIterator.hasNext() ){
- key = keyIterator.next();
- if( !resultMap.containsKey( key ) ){
- resultMap.put( key, map.get( key ) );
- }
- }
- }
-
- /**
- * function isValidOverload
- * @param origDecl
- * @param newDecl
- * @return boolean
- *
- * 3.3.7 "A class name or enumeration name can be hidden by the name of an
- * object, function or enumerator declared in the same scope"
- *
- * 3.4-1 "Name lookup may associate more than one declaration with a name if
- * it finds the name to be a function name"
- */
- protected static boolean isValidOverload( ISymbol origSymbol, ISymbol newSymbol ){
- ITypeInfo.eType origType = origSymbol.getType();
- ITypeInfo.eType newType = newSymbol.getType();
-
- if( origType == ITypeInfo.t_template ){
- ITemplateSymbol template = (ITemplateSymbol) origSymbol;
- origSymbol = template.getTemplatedSymbol();
- if( origSymbol == null )
- return true;
- origType = origSymbol.getType();
- }
-
- if( newType == ITypeInfo.t_template ){
- ITemplateSymbol template = (ITemplateSymbol) newSymbol;
- newSymbol = template.getTemplatedSymbol();
- if( newSymbol == null )
- return true;
- newType = newSymbol.getType();
- }
-
- //handle forward decls
- if( origSymbol.isForwardDeclaration() ){
- if( origSymbol.getForwardSymbol() == newSymbol )
- return true;
-
- //friend class declarations
- if( origSymbol.getIsInvisible() && origSymbol.isType( newSymbol.getType() ) ){
- origSymbol.setForwardSymbol( newSymbol );
- return true;
- }
- }
-
- if( (origType.compareTo(ITypeInfo.t_class) >= 0 && origType.compareTo(ITypeInfo.t_enumeration) <= 0) && //class name or enumeration ...
- ( newType == ITypeInfo.t_type || (newType.compareTo( ITypeInfo.t_function ) >= 0 /*&& newType <= TypeInfo.typeMask*/) ) ){
-
- return true;
- }
- //if the origtype is not a class-name or enumeration name, then the only other
- //allowable thing is if they are both functions.
- if( origSymbol instanceof IParameterizedSymbol && newSymbol instanceof IParameterizedSymbol )
- return isValidFunctionOverload( (IParameterizedSymbol) origSymbol, (IParameterizedSymbol) newSymbol );
- return false;
- }
-
- protected static boolean isValidOverload( List origList, ISymbol newSymbol ){
- if( origList.size() == 1 ){
- return isValidOverload( (ISymbol)origList.get(0), newSymbol );
- } else if ( origList.size() > 1 ){
- if( newSymbol.isType( ITypeInfo.t_template ) ){
- ITemplateSymbol template = (ITemplateSymbol) newSymbol;
- newSymbol = (ISymbol) template.getContainedSymbols().get( template.getName() );
- }
-
- //the first thing can be a class-name or enumeration name, but the rest
- //must be functions. So make sure the newDecl is a function before even
- //considering the list
- if( newSymbol.getType() != ITypeInfo.t_function && newSymbol.getType() != ITypeInfo.t_constructor ){
- return false;
- }
-
- //Iterator iter = origList.iterator();
- ISymbol symbol = (ISymbol) origList.get(0);
- int numSymbols = origList.size();
- if( symbol.isType( ITypeInfo.t_template ) ){
- IParameterizedSymbol template = (IParameterizedSymbol) symbol;
- symbol = (ISymbol) template.getContainedSymbols().get( template.getName() );
- }
-
- boolean valid = isValidOverload( symbol, newSymbol );
- int idx = 1;
- while( valid && idx < numSymbols ){
- symbol = (ISymbol) origList.get(idx++);
- if( symbol.isType( ITypeInfo.t_template ) ){
- ITemplateSymbol template = (ITemplateSymbol) symbol;
- symbol = template.getTemplatedSymbol();
- }
- valid = ( symbol instanceof IParameterizedSymbol) && isValidFunctionOverload( (IParameterizedSymbol)symbol, (IParameterizedSymbol)newSymbol );
- }
-
- return valid;
- }
-
- //empty list, return true
- return true;
- }
-
- private static boolean isValidFunctionOverload( IParameterizedSymbol origSymbol, IParameterizedSymbol newSymbol ){
- if( ( !origSymbol.isType( ITypeInfo.t_function ) && !origSymbol.isType( ITypeInfo.t_constructor ) ) ||
- ( ! newSymbol.isType( ITypeInfo.t_function ) && ! newSymbol.isType( ITypeInfo.t_constructor ) ) ){
- return false;
- }
-
- //handle forward decls
- if( origSymbol.isForwardDeclaration() &&
- origSymbol.getForwardSymbol() == newSymbol )
- {
- return true;
- }
- if( origSymbol.hasSameParameters( newSymbol ) ){
- //functions with the same name and same parameter types cannot be overloaded if any of them
- //is static
- if( origSymbol.getTypeInfo().checkBit( ITypeInfo.isStatic ) || newSymbol.getTypeInfo().checkBit( ITypeInfo.isStatic ) ){
- return false;
- }
-
- //if none of them are static, then the function can be overloaded if they differ in the type
- //of their implicit object parameter.
- if( origSymbol.compareCVQualifiersTo( newSymbol ) != 0 ){
- return true;
- }
-
- return false;
- }
-
- return true;
- }
-
- /**
- *
- * @param data
- * @return Declaration
- * @throws ParserSymbolTableException
- *
- * Resolve the foundItems set down to one declaration and return that
- * declaration.
- * If we successfully resolve, then the data.foundItems list will be
- * cleared. If however, we were not able to completely resolve the set,
- * then the data.foundItems set will be left with those items that
- * survived the partial resolution and we will return null. (currently,
- * this case applies to when we have overloaded functions and no parameter
- * information)
- *
- * NOTE: data.parameters == null means there is no parameter information at
- * all, when looking for functions with no parameters, an empty list must be
- * provided in data.parameters.
- */
- protected ISymbol resolveAmbiguities( LookupData data ) throws ParserSymbolTableException{
- ISymbol resolvedSymbol = null;
-
- if( data.foundItems == null || data.foundItems.isEmpty() || data.isPrefixLookup() ){
- return null;
- }
-
- Object object = data.foundItems.get( data.name );
-
- ArrayList functionList = null;
-
- if( object instanceof List ){
- //if we got this far with a list, they must all be functions
- functionList = new ArrayList( ((List)object).size() );
- functionList.addAll( (List) object );
- } else {
- ISymbol symbol = (ISymbol) object;
- if( symbol.isType( ITypeInfo.t_function ) ){
- functionList = new ArrayList(1);
- functionList.add( symbol );
- } else {
- if( symbol.isTemplateMember() && !symbol.isTemplateInstance() &&
- !symbol.isType( ITypeInfo.t_templateParameter ) && symbol.getContainingSymbol().isType( ITypeInfo.t_template ))
- {
- resolvedSymbol = symbol.getContainingSymbol();
- if( resolvedSymbol instanceof ISpecializedSymbol ){
- resolvedSymbol = ((ISpecializedSymbol)resolvedSymbol).getPrimaryTemplate();
- }
- } else {
- resolvedSymbol = symbol;
- }
- }
- }
-
- if( resolvedSymbol == null ){
- if( data.getParameters() == null ){
- //we have no parameter information, if we only have one function, return
- //that, otherwise we can't decide between them
- if( functionList.size() == 1){
- resolvedSymbol = (ISymbol) functionList.get(0);
- } else {
- throw new ParserSymbolTableException( ParserSymbolTableException.r_UnableToResolveFunction );
- }
- } else {
- resolvedSymbol = resolveFunction( data, functionList );
- }
- }
- return resolvedSymbol;
- }
-
- protected IParameterizedSymbol resolveFunction( LookupData data, List functions ) throws ParserSymbolTableException{
- if( functions == null ){
- return null;
- }
-
- //reduce our set of candidate functions to only those who have the right number of parameters
- reduceToViable( data, functions );
-
- if( data.exactFunctionsOnly && data.getTemplateParameters() == null ){
- if( functions.size() == 1 ){
- return (IParameterizedSymbol) functions.get( 0 );
- } else if( functions.size() == 0 ){
- return null;
- } else {
- throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
- }
- }
-
- int numSourceParams = ( data.getParameters() == null ) ? 0 : data.getParameters().size();
- int numFns = functions.size();
-
- if( numSourceParams == 0 ){
- //no parameters
- //if there is only 1 viable function, return it, if more than one, its ambiguous
- if( numFns == 0 ){
- return null;
- } else if ( numFns == 1 ){
- return (IParameterizedSymbol)functions.get(0);
- } else if ( numFns == 2 ){
- for (int i = 0; i < numFns; i++) {
- IParameterizedSymbol fn = (IParameterizedSymbol) functions.get(i);
- if( fn.isForwardDeclaration() && fn.getForwardSymbol() != null ){
- if( functions.contains( fn.getForwardSymbol() ) ){
- return (IParameterizedSymbol) fn.getForwardSymbol();
- }
- }
- }
- }
-
- if( data.getParameters() == null )
- throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
- }
-
- IParameterizedSymbol bestFn = null; //the best function
- IParameterizedSymbol currFn = null; //the function currently under consideration
- Cost [] bestFnCost = null; //the cost of the best function
- Cost [] currFnCost = null; //the cost for the current function
-
- ITypeInfo source = null; //parameter we are called with
- ITypeInfo target = null; //function's parameter
- ITypeInfo voidInfo = null; //used to compare f() and f(void)
-
- int comparison;
- Cost cost = null; //the cost of converting source to target
- Cost temp = null; //the cost of using a user defined conversion to convert source to target
-
- boolean hasWorse = false; //currFn has a worse parameter fit than bestFn
- boolean hasBetter = false; //currFn has a better parameter fit than bestFn
- boolean ambiguous = false; //ambiguity, 2 functions are equally good
- boolean currHasAmbiguousParam = false; //currFn has an ambiguous parameter conversion (ok if not bestFn)
- boolean bestHasAmbiguousParam = false; //bestFn has an ambiguous parameter conversion (not ok, ambiguous)
-
- List sourceParameters = null; //the parameters the function is being called with
- List targetParameters = null; //the current function's parameters
-
- TypeInfoProvider infoProvider = getTypeInfoProvider();
-
- if( numSourceParams == 0 ){
- //f() is the same as f( void )
- sourceParameters = new ArrayList(1);
- voidInfo = infoProvider.getTypeInfo( ITypeInfo.t_void );
- voidInfo.setType( ITypeInfo.t_void );
- sourceParameters.add( voidInfo );
- numSourceParams = 1;
- } else {
- sourceParameters = data.getParameters();
- }
-
- try {
- for( int fnIdx = 0; fnIdx < numFns; fnIdx++ ){
- currFn = (IParameterizedSymbol) functions.get( fnIdx );
-
- if( bestFn != null ){
- if( bestFn.isForwardDeclaration() && bestFn.getForwardSymbol() == currFn ){
- bestFn = currFn;
- continue;
- } else if( currFn.isForwardDeclaration() && currFn.getForwardSymbol() == bestFn ){
- continue;
- }
- }
-
-
- if( currFn.getParameterList().isEmpty() && !currFn.hasVariableArgs() ){
- //the only way we get here and have no parameters, is if we are looking
- //for a function that takes void parameters ie f( void )
- targetParameters = new ArrayList(1);
- targetParameters.add( currFn.getSymbolTable().newSymbol( "", ITypeInfo.t_void ) ); //$NON-NLS-1$
- } else {
- targetParameters = currFn.getParameterList();
- }
-
- int numTargetParams = targetParameters.size();
- if( currFnCost == null ){
- currFnCost = new Cost [ numSourceParams ];
- }
-
- comparison = 0;
- boolean varArgs = false;
-
- for( int j = 0; j < numSourceParams; j++ ){
- source = (ITypeInfo) sourceParameters.get(j);
-
- if( j < numTargetParams )
- target = ((ISymbol)targetParameters.get(j)).getTypeInfo();
- else
- varArgs = true;
-
- if( varArgs ){
- cost = new Cost( infoProvider, source, null );
- cost.rank = Cost.ELLIPSIS_CONVERSION;
- } else if ( target.getHasDefault() && source.isType( ITypeInfo.t_void ) && !source.hasPtrOperators() ){
- //source is just void, ie no parameter, if target had a default, then use that
- cost = new Cost( infoProvider, source, target );
- cost.rank = Cost.IDENTITY_RANK;
- } else if( source.equals( target ) ){
- cost = new Cost( infoProvider, source, target );
- cost.rank = Cost.IDENTITY_RANK; //exact match, no cost
- } else {
- try{
- cost = checkStandardConversionSequence( source, target );
-
- //12.3-4 At most one user-defined conversion is implicitly applied to
- //a single value. (also prevents infinite loop)
- if( cost.rank == Cost.NO_MATCH_RANK && !data.forUserDefinedConversion ){
- temp = checkUserDefinedConversionSequence( source, target );
- if( temp != null ){
- cost.release( infoProvider );
- cost = temp;
- }
- }
- } catch( ParserSymbolTableException e ) {
- if( cost != null ) { cost.release( infoProvider ); cost = null; }
- if( temp != null ) { temp.release( infoProvider ); temp = null; }
- throw e;
- } catch( ParserSymbolTableError e ) {
- if( cost != null ) { cost.release( infoProvider ); cost = null; }
- if( temp != null ) { temp.release( infoProvider ); temp = null; }
- throw e;
- }
- }
-
- currFnCost[ j ] = cost;
- }
-
-
- hasWorse = false;
- hasBetter = false;
- //In order for this function to be better than the previous best, it must
- //have at least one parameter match that is better that the corresponding
- //match for the other function, and none that are worse.
- for( int j = 0; j < numSourceParams; j++ ){
- if( currFnCost[ j ].rank < 0 ){
- hasWorse = true;
- hasBetter = false;
-
- if( data.isPrefixLookup() ){
- //for prefix lookup, just remove from the function list those functions
- //that don't fit the parameters
- functions.remove( fnIdx-- );
- numFns--;
- }
- break;
- }
-
- //an ambiguity in the user defined conversion sequence is only a problem
- //if this function turns out to be the best.
- currHasAmbiguousParam = ( currFnCost[ j ].userDefined == 1 );
-
- if( bestFnCost != null ){
- comparison = currFnCost[ j ].compare( bestFnCost[ j ] );
- hasWorse |= ( comparison < 0 );
- hasBetter |= ( comparison > 0 );
- } else {
- hasBetter = true;
- }
- }
-
- //during a prefix lookup, we don't need to rank the functions
- if( data.isPrefixLookup() ){
- releaseCosts( currFnCost, infoProvider );
- continue;
- }
-
- //If function has a parameter match that is better than the current best,
- //and another that is worse (or everything was just as good, neither better nor worse).
- //then this is an ambiguity (unless we find something better than both later)
- ambiguous |= ( hasWorse && hasBetter ) || ( !hasWorse && !hasBetter );
-
- if( !hasWorse ){
- if( !hasBetter ){
- //if they are both template functions, we can order them that way
- boolean bestIsTemplate = bestFn.getContainingSymbol() instanceof ITemplateSymbol;
- boolean currIsTemplate = currFn.getContainingSymbol() instanceof ITemplateSymbol;
- if( bestIsTemplate && currIsTemplate )
- {
- try{
- ITemplateSymbol t1 = (ITemplateSymbol) bestFn.getInstantiatedSymbol().getContainingSymbol();
- ITemplateSymbol t2 = (ITemplateSymbol) currFn.getInstantiatedSymbol().getContainingSymbol();
- int order = TemplateEngine.orderTemplateFunctions( t1, t2 );
- if ( order < 0 ){
- hasBetter = true;
- } else if( order > 0 ){
- ambiguous = false;
- }
- } catch( ParserSymbolTableException e ) {
- if( currFnCost != null ) releaseCosts( currFnCost, infoProvider );
- if( bestFnCost != null ) releaseCosts( bestFnCost, infoProvider );
- throw e;
- } catch( ParserSymbolTableError e ) {
- if( currFnCost != null ) releaseCosts( currFnCost, infoProvider );
- if( bestFnCost != null ) releaseCosts( bestFnCost, infoProvider );
- throw e;
- }
- }
- //we prefer normal functions over template functions, unless we specified template arguments
- else if( bestIsTemplate && !currIsTemplate ){
- if( data.getTemplateParameters() == null )
- hasBetter = true;
- else
- ambiguous = false;
- } else if( !bestIsTemplate && currIsTemplate ){
- if( data.getTemplateParameters() == null )
- ambiguous = false;
- else
- hasBetter = true;
- }
- }
- if( hasBetter ){
- //the new best function.
- ambiguous = false;
- releaseCosts( bestFnCost, infoProvider );
- bestFnCost = currFnCost;
- bestHasAmbiguousParam = currHasAmbiguousParam;
- currFnCost = null;
- bestFn = currFn;
- } else {
- releaseCosts( currFnCost, infoProvider );
- }
- } else {
- releaseCosts( currFnCost, infoProvider );
- }
- }
- } finally {
- if( currFnCost != null ){
- releaseCosts( currFnCost, infoProvider );
- currFnCost = null;
- }
- if( bestFnCost != null ){
- releaseCosts( bestFnCost, infoProvider );
- bestFnCost = null;
- }
- if( voidInfo != null )
- infoProvider.returnTypeInfo( voidInfo );
- }
-
- if( ambiguous || bestHasAmbiguousParam ){
- throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
- }
-
- return bestFn;
- }
- static private void releaseCosts( Cost [] costs, TypeInfoProvider provider ){
- if( costs != null && provider != null) {
- for( int i = 0; i < costs.length; i++ ){
- if( costs[i] != null )
- costs[i].release( provider );
- }
- }
- }
-
- static private boolean functionHasParameters( IParameterizedSymbol function, List params ){
- if( params == null ){
- return function.getParameterList().isEmpty();
- }
- //create a new function that has params as its parameters, then use IParameterizedSymbol.hasSameParameters
- IParameterizedSymbol tempFn = function.getSymbolTable().newParameterizedSymbol( EMPTY_NAME, ITypeInfo.t_function );
-
- int size = params.size();
- for( int i = 0; i < size; i++ ){
- ISymbol param = function.getSymbolTable().newSymbol( EMPTY_NAME );
- param.setTypeInfo( (ITypeInfo) params.get(i) );
- tempFn.addParameter( param );
- }
-
- return function.hasSameParameters( tempFn );
- }
-
- static private void reduceToViable( LookupData data, List functions ){
- int numParameters = ( data.getParameters() == null ) ? 0 : data.getParameters().size();
- int num;
-
- if( data.isPrefixLookup() )
- {
- if( numParameters >= 1 )
- numParameters++;
- }
-
- //Trim the list down to the set of viable functions
- IParameterizedSymbol function;
- Object obj = null;
- int size = functions.size();
- for( int i = 0; i < size; i++ ){
- obj = functions.get(i);
- //sanity check
- if( obj instanceof IParameterizedSymbol ){
- function = (IParameterizedSymbol) obj;
- if( !function.isType( ITypeInfo.t_function) && !function.isType( ITypeInfo.t_constructor ) ){
- functions.remove( i-- );
- size--;
- continue;
- }
- } else {
- functions.remove( i-- );
- size--;
- continue;
- }
-
- num = ( function.getParameterList() == null ) ? 0 : function.getParameterList().size();
-
- //if there are m arguments in the list, all candidate functions having m parameters
- //are viable
- if( num == numParameters ){
- if( data.exactFunctionsOnly && !functionHasParameters( function, data.getParameters() ) ){
- functions.remove( i-- );
- size--;
- }
- continue;
- }
- //check for void
- else if( numParameters == 0 && num == 1 ){
- ISymbol param = (ISymbol)function.getParameterList().get(0);
- if( param.isType( ITypeInfo.t_void ) )
- continue;
- }
- else if( numParameters == 1 && num == 0 ){
- ITypeInfo paramType = (ITypeInfo) data.getParameters().get(0);
- if( paramType.isType( ITypeInfo.t_void ) )
- continue;
- }
-
- //A candidate function having fewer than m parameters is viable only if it has an
- //ellipsis in its parameter list.
- if( num < numParameters ){
- if( function.hasVariableArgs() ) {
- continue;
- }
- //not enough parameters, remove it
- functions.remove( i-- );
- size--;
- }
- //a candidate function having more than m parameters is viable only if the (m+1)-st
- //parameter has a default argument
- else {
- if( data.isPrefixLookup() ){
- //during prefix lookup, having more parameters than what is provided is ok
- continue;
- }
- List params = function.getParameterList();
- ITypeInfo param;
- for( int j = num - 1; j > ( numParameters - num); j-- ){
- param = ((ISymbol)params.get(j)).getTypeInfo();
- if( !param.getHasDefault() ){
- functions.remove( i-- );
- size--;
- break;
- }
- }
- }
- }
- }
-
- /**
- * function ProcessDirectives
- * @param Declaration decl
- * @param LookupData data
- * @param LinkedList directives
- *
- * Go through the directives and for each nominated namespace find the
- * closest enclosing declaration for that namespace and decl, then add the
- * nominated namespace to the lookup data for consideration when we reach
- * the enclosing declaration.
- */
- static private void processDirectives( IContainerSymbol symbol, LookupData data, List directives ){
- IContainerSymbol enclosing = null;
- IContainerSymbol temp = null;
-
- if( directives == null )
- return;
-
- int size = directives.size();
- for( int i = 0; i < size; i++ ){
- temp = ((IUsingDirectiveSymbol) directives.get(i)).getNamespace();
-
- //namespaces are searched at most once
- if( !data.visited.containsKey( temp ) ){
- enclosing = getClosestEnclosingDeclaration( symbol, temp );
-
- //the data.usingDirectives is a map from enclosing declaration to
- //a list of namespaces to consider when we reach that enclosing
- //declaration
- ArrayList list = (data.usingDirectives == null )
- ? null
- : (ArrayList) data.usingDirectives.get( enclosing );
- if ( list == null ){
- list = new ArrayList(4);
- list.add( temp );
- if( data.usingDirectives == null ){
- data.usingDirectives = new HashMap();
- }
- data.usingDirectives.put( enclosing, list );
- } else {
- list.add( temp );
- }
- }
- }
- }
-
- /**
- * function getClosestEnclosingDeclaration
- * @param decl1
- * @param decl2
- * @return Declaration
- *
- * 7.3.4-1 "During unqualified lookup, the names appear as if they were
- * declared in the nearest enclosing namespace which contains both the
- * using-directive and the nominated namespace"
- *
- * TBD: Consider rewriting this iteratively instead of recursively, for
- * performance
- */
- static private IContainerSymbol getClosestEnclosingDeclaration( ISymbol symbol1, ISymbol symbol2 ){
- if( symbol1 == symbol2 ){
- return ( symbol1 instanceof IContainerSymbol ) ? (IContainerSymbol) symbol1 : symbol1.getContainingSymbol();
- }
-
- if( symbol1.getDepth() == symbol2.getDepth() ){
- return getClosestEnclosingDeclaration( symbol1.getContainingSymbol(), symbol2.getContainingSymbol() );
- } else if( symbol1.getDepth() > symbol2.getDepth() ) {
- return getClosestEnclosingDeclaration( symbol1.getContainingSymbol(), symbol2 );
- } else {
- return getClosestEnclosingDeclaration( symbol1, symbol2.getContainingSymbol() );
- }
- }
-
- /**
- *
- * @param obj
- * @param base
- * @return int
- * figure out if base is a base class of obj, and return the "distance" to
- * the base class.
- * ie:
- * A -> B -> C
- * the distance from A to B is 1 and from A to C is 2. This distance is used
- * to rank standard pointer conversions.
- *
- * TBD: Consider rewriting iteratively for performance.
- */
- static protected int hasBaseClass( ISymbol obj, ISymbol base ) throws ParserSymbolTableException {
- return hasBaseClass( obj, base, false );
- }
-
- static private int hasBaseClass( ISymbol obj, ISymbol base, boolean throwIfNotVisible ) throws ParserSymbolTableException{
- if( obj == base ){
- return 0;
- }
- IDerivableContainerSymbol symbol = null;
-
- if( obj instanceof IDerivableContainerSymbol ){
- symbol = (IDerivableContainerSymbol) obj;
- } else {
- return -1;
- }
-
- if( symbol.hasParents() ){
- ISymbol temp = null;
- IDerivableContainerSymbol parent = null;
- IDerivableContainerSymbol.IParentSymbol wrapper;
-
- List parents = symbol.getParents();
- int size = parents.size();
-
- for( int i = 0; i < size; i++ ){
- wrapper = (IDerivableContainerSymbol.IParentSymbol) parents.get(i);
- temp = wrapper.getParent();
- boolean isVisible = ( wrapper.getAccess() == ASTAccessVisibility.PUBLIC );
- if ( temp instanceof IDerivableContainerSymbol ){
- parent = (IDerivableContainerSymbol)temp;
- } else {
- continue;
- }
- if( parent == base ){
- if( throwIfNotVisible && !isVisible )
- throw new ParserSymbolTableException( ParserSymbolTableException.r_BadVisibility );
- return 1;
- }
- int n = hasBaseClass( parent, base, throwIfNotVisible );
- if( n > 0 )
- return n + 1;
- }
- }
-
- return -1;
- }
-
- static protected void getAssociatedScopes( ISymbol symbol, ObjectSet associated ){
- if( symbol == null ){
- return;
- }
- //if T is a class type, its associated classes are the class itself,
- //and its direct and indirect base classes. its associated Namespaces are the
- //namespaces in which its associated classes are defined
- //if( symbol.getType() == TypeInfo.t_class ){
- if( symbol instanceof IDerivableContainerSymbol ){
- associated.put( symbol );
- associated.put( symbol.getContainingSymbol() );
- getBaseClassesAndContainingNamespaces( (IDerivableContainerSymbol) symbol, associated );
- }
- //if T is a union or enumeration type, its associated namespace is the namespace in
- //which it is defined. if it is a class member, its associated class is the member's
- //class
- else if( symbol.getType() == ITypeInfo.t_union || symbol.getType() == ITypeInfo.t_enumeration ){
- associated.put( symbol.getContainingSymbol() );
- }
- }
-
- static private void getBaseClassesAndContainingNamespaces( IDerivableContainerSymbol obj, ObjectSet classes ){
- if( obj.getParents() != null ){
- if( classes == null ){
- return;
- }
-
- List parents = obj.getParents();
- int size = parents.size();
- IDerivableContainerSymbol.IParentSymbol wrapper;
- ISymbol base;
-
- for( int i = 0; i < size; i++ ){
- wrapper = (IDerivableContainerSymbol.IParentSymbol) parents.get(i);
- base = wrapper.getParent();
- //TODO: what about IDeferredTemplateInstance parents?
- if( base instanceof IDerivableContainerSymbol ){
- classes.put( base );
- if( base.getContainingSymbol().getType() == ITypeInfo.t_namespace ){
- classes.put( base.getContainingSymbol());
- }
-
- getBaseClassesAndContainingNamespaces( (IDerivableContainerSymbol) base, classes );
- }
-
- }
- }
- }
-
- static protected boolean okToAddUsingDeclaration( ISymbol obj, IContainerSymbol context ){
- boolean okToAdd = false;
-
- //7.3.3-5 A using-declaration shall not name a template-id
- if( obj.isTemplateInstance() && obj.getInstantiatedSymbol().getContainingSymbol().isType( ITypeInfo.t_template ) ){
- okToAdd = false;
- }
- //7.3.3-4
- else if( context.isType( ITypeInfo.t_class, ITypeInfo.t_struct ) ){
- IContainerSymbol container = obj.getContainingSymbol();
-
- try{
- //a member of a base class
- if( obj.getContainingSymbol().getType() == context.getType() ){
- okToAdd = ( hasBaseClass( context, container ) > 0 );
- }
- else if ( obj.getContainingSymbol().getType() == ITypeInfo.t_union ) {
- // TODO : must be an _anonymous_ union
- container = container.getContainingSymbol();
- okToAdd = ( container instanceof IDerivableContainerSymbol )
- ? ( hasBaseClass( context, container ) > 0 )
- : false;
- }
- //an enumerator for an enumeration
- else if ( obj.getType() == ITypeInfo.t_enumerator ){
- container = container.getContainingSymbol();
- okToAdd = ( container instanceof IDerivableContainerSymbol )
- ? ( hasBaseClass( context, container ) > 0 )
- : false;
- }
- } catch ( ParserSymbolTableException e ) {
- //not going to happen since we didn't ask for the visibility exception from hasBaseClass
- }
- } else {
- okToAdd = true;
- }
-
- return okToAdd;
- }
-
- static private Cost lvalue_to_rvalue( TypeInfoProvider provider, ITypeInfo source, ITypeInfo target ){
-
- //lvalues will have type t_type
- if( source.isType( ITypeInfo.t_type ) ){
- source = getFlatTypeInfo( source, null );
- }
-
- if( target.isType( ITypeInfo.t_type ) ){
- target = getFlatTypeInfo( target, null );
- }
-
- Cost cost = new Cost( provider, source, target );
-
- //if either source or target is null here, then there was a problem
- //with the parameters and we can't match them.
- if( cost.getSource() == null || cost.getTarget() == null ){
- return cost;
- }
-
- ITypeInfo.PtrOp op = null;
-
- if( cost.getSource().hasPtrOperators() ){
- List sourcePtrs = cost.getSource().getPtrOperators();
- ITypeInfo.PtrOp ptr = (ITypeInfo.PtrOp)sourcePtrs.get( 0 );
- if( ptr.getType() == ITypeInfo.PtrOp.t_reference ){
- sourcePtrs.remove( 0 );
- }
- int size = sourcePtrs.size();
- for( int i = 0; i < size; i++ ){
- op = (ITypeInfo.PtrOp) sourcePtrs.get( 0 );
- if( op.getType() == ITypeInfo.PtrOp.t_array ){
- op.setType( ITypeInfo.PtrOp.t_pointer );
- }
- }
- }
-
- if( cost.getTarget().hasPtrOperators() ){
- List targetPtrs = cost.getTarget().getPtrOperators();
- //ListIterator iterator = targetPtrs.listIterator();
- ITypeInfo.PtrOp ptr = (ITypeInfo.PtrOp)targetPtrs.get(0);
-
- if( ptr.getType() == ITypeInfo.PtrOp.t_reference ){
- targetPtrs.remove(0);
- cost.targetHadReference = true;
- }
- int size = targetPtrs.size();
- for( int i = 0; i < size; i++ ){
- op = (ITypeInfo.PtrOp) targetPtrs.get(0);
- if( op.getType() == ITypeInfo.PtrOp.t_array ){
- op.setType( ITypeInfo.PtrOp.t_pointer );
- }
- }
- }
-
- return cost;
- }
-
- /**
- * qualificationConversion
- * @param cost
- *
- * see spec section 4.4 regarding qualification conversions
- */
- static private void qualificationConversion( Cost cost ){
- List sourcePtrs = cost.getSource().getPtrOperators();
- List targetPtrs = cost.getTarget().getPtrOperators();
- int size = sourcePtrs.size();
- int size2 = targetPtrs.size();
-
- ITypeInfo.PtrOp op1 = null, op2 = null;
- boolean canConvert = true;
-
- if( size != size2 ){
- canConvert = false;
- } else if( size > 0 ){
- op1 = (ITypeInfo.PtrOp) sourcePtrs.get(0);
- op2 = (ITypeInfo.PtrOp) targetPtrs.get(0);
-
- boolean constInEveryCV2k = true;
-
- for( int j= 1; j < size; j++ ){
- op1 = (ITypeInfo.PtrOp) sourcePtrs.get(j);
- op2 = (ITypeInfo.PtrOp) targetPtrs.get(j);
-
- //pointer types must be similar
- if( op1.getType() != op2.getType() ){
- canConvert = false;
- break;
- }
- //if const is in cv1,j then const is in cv2,j. Similary for volatile
- if( ( op1.isConst() && !op2.isConst() ) ||
- ( op1.isVolatile() && !op2.isVolatile() ) )
- {
- canConvert = false;
- break;
- }
-
- //if cv1,j and cv2,j are different then const is in every cv2,k for 0<k<j
- if( ( op1.compareCVTo( op2 ) != 0 ) && !constInEveryCV2k ){
- canConvert = false;
- break;
- }
-
- constInEveryCV2k &= op2.isConst();
- }
- }
-
- if( ( cost.getSource().checkBit( ITypeInfo.isConst ) && !cost.getTarget().checkBit( ITypeInfo.isConst ) ) ||
- ( cost.getSource().checkBit( ITypeInfo.isVolatile ) && !cost.getTarget().checkBit( ITypeInfo.isVolatile ) ) )
- {
- canConvert = false;
- }
-
- if( canConvert == true ){
- cost.qualification = 1;
- cost.rank = Cost.LVALUE_OR_QUALIFICATION_RANK;
- } else {
- cost.qualification = 0;
- }
- }
-
- /**
- *
- * @param source
- * @param target
- * @return int
- *
- * 4.5-1 char, signed char, unsigned char, short int or unsigned short int
- * can be converted to int if int can represent all the values of the source
- * type, otherwise they can be converted to unsigned int.
- * 4.5-2 wchar_t or an enumeration can be converted to the first of the
- * following that can hold it: int, unsigned int, long unsigned long.
- * 4.5-4 bool can be promoted to int
- * 4.6 float can be promoted to double
- */
- static private void promotion( Cost cost ){
- ITypeInfo src = cost.getSource();
- ITypeInfo trg = cost.getTarget();
-
- int mask = ITypeInfo.isShort | ITypeInfo.isLong | ITypeInfo.isUnsigned | ITypeInfo.isLongLong | ITypeInfo.isSigned;
-
- if( src.isType( ITypeInfo.t__Bool, ITypeInfo.t_float ) &&
- (trg.isType( ITypeInfo.t_int ) || trg.isType( ITypeInfo.t_double )) )
- {
- if( src.getType() == trg.getType() && (( src.getTypeBits() & mask) == (trg.getTypeBits() & mask)) ){
- //same, no promotion needed
- return;
- }
-
- if( src.isType( ITypeInfo.t_float ) ){
- cost.promotion = trg.isType( ITypeInfo.t_double ) ? 1 : 0;
- } else {
- cost.promotion = ( trg.isType( ITypeInfo.t_int ) && trg.canHold( src ) ) ? 1 : 0;
- }
-
- } else {
- cost.promotion = 0;
- }
-
- cost.rank = (cost.promotion > 0 ) ? Cost.PROMOTION_RANK : Cost.NO_MATCH_RANK;
- }
-
- /**
- *
- * @param source
- * @param target
- * @return int
- *
- */
- static private void conversion( Cost cost ){
- ITypeInfo src = cost.getSource();
- ITypeInfo trg = cost.getTarget();
-
- int temp = -1;
-
- cost.conversion = 0;
- cost.detail = 0;
-
- if( !src.hasSamePtrs( trg ) ){
- return;
- }
- if( src.hasPtrOperators() && src.getPtrOperators().size() == 1 ){
- ITypeInfo.PtrOp ptr = (ITypeInfo.PtrOp)src.getPtrOperators().get(0);
- ISymbol srcDecl = src.isType( ITypeInfo.t_type ) ? src.getTypeSymbol() : null;
- ISymbol trgDecl = trg.isType( ITypeInfo.t_type ) ? trg.getTypeSymbol() : null;
- if( ptr.getType() == ITypeInfo.PtrOp.t_pointer ){
- if( srcDecl == null || (trgDecl == null && !trg.isType( ITypeInfo.t_void )) ){
- return;
- }
-
- //4.10-2 an rvalue of type "pointer to cv T", where T is an object type can be
- //converted to an rvalue of type "pointer to cv void"
- if( trg.isType( ITypeInfo.t_void ) ){
- cost.rank = Cost.CONVERSION_RANK;
- cost.conversion = 1;
- cost.detail = 2;
- return;
- }
-
- cost.detail = 1;
-
- //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.
- if( (srcDecl instanceof IDerivableContainerSymbol) && trgDecl.isType( srcDecl.getType() ) ){
- try {
- temp = hasBaseClass( srcDecl, trgDecl );
- } catch (ParserSymbolTableException e) {
- //not going to happen since we didn't ask for the visibility exception
- }
- cost.rank = ( temp > -1 ) ? Cost.CONVERSION_RANK : Cost.NO_MATCH_RANK;
- cost.conversion = ( temp > -1 ) ? temp : 0;
- cost.detail = 1;
- return;
- }
- } else if( ptr.getType() == ITypeInfo.PtrOp.t_memberPointer ){
- //4.11-2 An rvalue of type "pointer to member of B of type cv T", where B is a class type,
- //can be converted to an rvalue of type "pointer to member of D of type cv T" where D is a
- //derived class of B
- if( srcDecl == null || trgDecl == null ){
- return;
- }
-
- ITypeInfo.PtrOp srcPtr = trg.hasPtrOperators() ? (ITypeInfo.PtrOp)trg.getPtrOperators().get(0) : null;
- if( trgDecl.isType( srcDecl.getType() ) && srcPtr != null && srcPtr.getType() == ITypeInfo.PtrOp.t_memberPointer ){
- try {
- temp = hasBaseClass( ptr.getMemberOf(), srcPtr.getMemberOf() );
- } catch (ParserSymbolTableException e) {
- //not going to happen since we didn't ask for the visibility exception
- }
- cost.rank = ( temp > -1 ) ? Cost.CONVERSION_RANK : Cost.NO_MATCH_RANK;
- cost.detail = 1;
- cost.conversion = ( temp > -1 ) ? temp : 0;
- return;
- }
- }
- } else if( !src.hasPtrOperators() ) {
- //4.7 An rvalue of an integer type can be converted to an rvalue of another integer type.
- //An rvalue of an enumeration type can be converted to an rvalue of an integer type.
- if( src.isType( ITypeInfo.t__Bool, ITypeInfo.t_int ) || src.isType( ITypeInfo.t_float, ITypeInfo.t_double ) ||
- src.isType( ITypeInfo.t_enumeration ) || ( src.isType( ITypeInfo.t_type ) && src.getTypeSymbol() != null
- && src.getTypeSymbol().isType( ITypeInfo.t_enumeration ) ) )
- {
- if( trg.isType( ITypeInfo.t__Bool, ITypeInfo.t_int ) ||
- trg.isType( ITypeInfo.t_float, ITypeInfo.t_double ) )
- {
- cost.rank = Cost.CONVERSION_RANK;
- cost.conversion = 1;
- }
- }
- }
- }
-
- static private void derivedToBaseConversion( Cost cost ) throws ParserSymbolTableException{
- ITypeInfo src = cost.getSource();
- ITypeInfo trg = cost.getTarget();
-
- ISymbol srcDecl = src.isType( ITypeInfo.t_type ) ? src.getTypeSymbol() : null;
- ISymbol trgDecl = trg.isType( ITypeInfo.t_type ) ? trg.getTypeSymbol() : null;
-
- if( !src.hasSamePtrs( trg ) || srcDecl == null || trgDecl == null || !cost.targetHadReference ){
- return;
- }
-
- int temp = hasBaseClass( srcDecl, trgDecl, true );
-
- if( temp > -1 ){
- cost.rank = Cost.DERIVED_TO_BASE_CONVERSION;
- cost.conversion = temp;
- }
- }
-
- protected Cost checkStandardConversionSequence( ITypeInfo source, ITypeInfo target ) throws ParserSymbolTableException{
- Cost cost = lvalue_to_rvalue( getTypeInfoProvider(), source, target );
-
- if( cost.getSource() == null || cost.getTarget() == null ){
- return cost;
- }
-
- if( cost.getSource().equals( cost.getTarget() ) ){
- cost.rank = Cost.IDENTITY_RANK;
- return cost;
- }
-
- qualificationConversion( cost );
-
- //if we can't convert the qualifications, then we can't do anything
- if( cost.qualification == 0 ){
- return cost;
- }
-
- //was the qualification conversion enough?
- if( cost.getSource().isType( ITypeInfo.t_type ) && cost.getTarget().isType( ITypeInfo.t_type ) ){
- if( cost.getTarget().hasSamePtrs( cost.getSource() ) ){
- ISymbol srcSymbol = cost.getSource().getTypeSymbol();
- ISymbol trgSymbol = cost.getTarget().getTypeSymbol();
- if( srcSymbol != null && trgSymbol != null ){
- if( srcSymbol.equals( trgSymbol ) )
- {
- return cost;
- }
- }
- }
- } else if( cost.getSource().getType() == cost.getTarget().getType() &&
- (cost.getSource().getTypeBits() & ~ITypeInfo.isConst & ~ITypeInfo.isVolatile) == (cost.getTarget().getTypeBits() & ~ITypeInfo.isConst & ~ITypeInfo.isVolatile) )
- {
- return cost;
- }
- promotion( cost );
- if( cost.promotion > 0 || cost.rank > -1 ){
- return cost;
- }
-
- conversion( cost );
-
- if( cost.rank > -1 )
- return cost;
-
- try{
- derivedToBaseConversion( cost );
- } catch ( ParserSymbolTableException e ){
- cost.release( getTypeInfoProvider() );
- throw e;
- }
-
- return cost;
- }
-
- private Cost checkUserDefinedConversionSequence( ITypeInfo source, ITypeInfo target ) throws ParserSymbolTableException {
- Cost cost = null;
- Cost constructorCost = null;
- Cost conversionCost = null;
-
- ISymbol targetDecl = null;
- ISymbol sourceDecl = null;
- IParameterizedSymbol constructor = null;
- IParameterizedSymbol conversion = null;
-
- //constructors
- if( target.getType() == ITypeInfo.t_type ){
- targetDecl = target.getTypeSymbol();
- if( targetDecl == null ){
- throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
- }
- if( targetDecl.isType( ITypeInfo.t_class, ITypeInfo.t_union ) ){
- LookupData data = new LookupData( EMPTY_NAME){
- public List getParameters() { return parameters; }
- public TypeFilter getFilter() { return CONSTRUCTOR_FILTER; }
- private List parameters = new ArrayList( 1 );
- };
- data.forUserDefinedConversion = true;
- data.getParameters().add( source );
-
- if( targetDecl instanceof IDeferredTemplateInstance ){
- targetDecl = ((IDeferredTemplateInstance)targetDecl).getTemplate().getTemplatedSymbol();
- }
- IDerivableContainerSymbol container = (IDerivableContainerSymbol) targetDecl;
-
- if( !container.getConstructors().isEmpty() ){
- ArrayList constructors = new ArrayList( container.getConstructors() );
- constructor = resolveFunction( data, constructors );
- }
- if( constructor != null && constructor.getTypeInfo().checkBit( ITypeInfo.isExplicit ) ){
- constructor = null;
- }
-
- }
- }
-
- TypeInfoProvider provider = getTypeInfoProvider();
- //conversion operators
- if( source.getType() == ITypeInfo.t_type ){
- source = getFlatTypeInfo( source, provider );
- sourceDecl = ( source != null ) ? source.getTypeSymbol() : null;
- provider.returnTypeInfo( source );
-
- if( sourceDecl != null && (sourceDecl instanceof IContainerSymbol) ){
- String name = target.toString();
-
- if( !name.equals(EMPTY_NAME) ){
- LookupData data = new LookupData( "operator " + name ){ //$NON-NLS-1$
- public List getParameters() { return Collections.EMPTY_LIST; }
- public TypeFilter getFilter() { return FUNCTION_FILTER; }
- };
- data.forUserDefinedConversion = true;
- data.foundItems = lookupInContained( data, (IContainerSymbol) sourceDecl );
- conversion = (data.foundItems != null ) ? (IParameterizedSymbol)resolveAmbiguities( data ) : null;
- }
- }
- }
-
- try {
- if( constructor != null ){
- ITypeInfo info = provider.getTypeInfo( ITypeInfo.t_type );
- info.setTypeSymbol( constructor.getContainingSymbol() );
- constructorCost = checkStandardConversionSequence( info, target );
- provider.returnTypeInfo( info );
- }
- if( conversion != null ){
- ITypeInfo info = provider.getTypeInfo( target.getType() );
- info.setTypeSymbol( target.getTypeSymbol() );
- conversionCost = checkStandardConversionSequence( info, target );
- provider.returnTypeInfo( info );
- }
-
- //if both are valid, then the conversion is ambiguous
- if( constructorCost != null && constructorCost.rank != Cost.NO_MATCH_RANK &&
- conversionCost != null && conversionCost.rank != Cost.NO_MATCH_RANK )
- {
- cost = constructorCost;
- cost.userDefined = Cost.AMBIGUOUS_USERDEFINED_CONVERSION;
- cost.rank = Cost.USERDEFINED_CONVERSION_RANK;
- } else {
- if( constructorCost != null && constructorCost.rank != Cost.NO_MATCH_RANK ){
- cost = constructorCost;
- cost.userDefined = constructor.hashCode();
- cost.rank = Cost.USERDEFINED_CONVERSION_RANK;
- } else if( conversionCost != null && conversionCost.rank != Cost.NO_MATCH_RANK ){
- cost = conversionCost;
- cost.userDefined = conversion.hashCode();
- cost.rank = Cost.USERDEFINED_CONVERSION_RANK;
- }
- }
- } finally {
- if( constructorCost != null && constructorCost != cost )
- constructorCost.release( provider );
- if( conversionCost != null && conversionCost != cost )
- conversionCost.release( provider );
- }
- return cost;
- }
-
- /**
- * Determine the type of a conditional operator based on the second and third operands
- * @param secondOp
- * @param thirdOp
- * @return
- * Spec 5.16
- * Determine if the second operand can be converted to match the third operand, and vice versa.
- * - If both can be converted, or one can be converted but the conversion is ambiguous, the program
- * is illformed (throw ParserSymbolTableException)
- * - If neither can be converted, further checking must be done (return null)
- * - If exactly one conversion is possible, that conversion is applied ( return the other TypeInfo )
- */
- public ITypeInfo getConditionalOperand( ITypeInfo secondOp, ITypeInfo thirdOp ) throws ParserSymbolTableException{
- Cost thirdCost = null, secondCost = null;
- ITypeInfo temp = null;
- TypeInfoProvider provider = getTypeInfoProvider();
- try{
- //can secondOp convert to thirdOp ?
- temp = getFlatTypeInfo( thirdOp, provider );
- secondCost = checkStandardConversionSequence( secondOp, temp );
-
- if( secondCost.rank == Cost.NO_MATCH_RANK ){
- secondCost.release( provider );
- secondCost = checkUserDefinedConversionSequence( secondOp, temp );
- }
- getTypeInfoProvider().returnTypeInfo( temp );
- temp = getFlatTypeInfo( secondOp, provider );
-
- thirdCost = checkStandardConversionSequence( thirdOp, temp );
- if( thirdCost.rank == Cost.NO_MATCH_RANK ){
- thirdCost.release( provider );
- thirdCost = checkUserDefinedConversionSequence( thirdOp, temp );
- }
- } finally {
- if( thirdCost != null ) thirdCost.release( provider );
- if( secondCost != null ) secondCost.release( provider );
- if( temp != null ) provider.returnTypeInfo( temp );
- }
-
- boolean canConvertSecond = ( secondCost != null && secondCost.rank != Cost.NO_MATCH_RANK );
- boolean canConvertThird = ( thirdCost != null && thirdCost.rank != Cost.NO_MATCH_RANK );
-
- if( !canConvertSecond && !canConvertThird ){
- //neither can be converted
- return null;
- } else if ( canConvertSecond && canConvertThird ){
- //both can be converted -> illformed
- throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
- } else {
- if( canConvertSecond ){
- if( secondCost.userDefined == Cost.AMBIGUOUS_USERDEFINED_CONVERSION ){
- //conversion is ambiguous -> ill-formed
- throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
- }
- return thirdOp;
- }
- if( thirdCost.userDefined == Cost.AMBIGUOUS_USERDEFINED_CONVERSION )
- //conversion is ambiguous -> ill-formed
- throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
-
- return secondOp;
- }
- }
-
- /**
- *
- * @param infoProvider - if using the pool, an instance of the symbol table must be provided
- * @param decl
- * @return TypeInfo
- * The top level TypeInfo represents modifications to the object and the
- * remaining TypeInfo's represent the object.
- */
- static protected ITypeInfo getFlatTypeInfo( ITypeInfo topInfo, TypeInfoProvider infoProvider ){
- ITypeInfo returnInfo = null;
- ITypeInfo info = null;
-
- if( topInfo.getType() == ITypeInfo.t_type && topInfo.getTypeSymbol() != null ){
- if( infoProvider != null ) returnInfo = infoProvider.getTypeInfo( ITypeInfo.t_type );
- else returnInfo = TypeInfoProvider.newTypeInfo( ITypeInfo.t_type );
-
- returnInfo.setTypeBits( topInfo.getTypeBits() );
- ISymbol typeSymbol = topInfo.getTypeSymbol();
-
- info = typeSymbol.getTypeInfo();
- int j = 0;
- while( (info.getTypeSymbol() != null && ( info.isType( ITypeInfo.t_type ) || info.isType( ITypeInfo.t_enumerator ) ) ) ||
- (typeSymbol != null && typeSymbol.isForwardDeclaration() && typeSymbol.getForwardSymbol() != null ) ){
-
- typeSymbol = (info.isType( ITypeInfo.t_type) || info.isType(ITypeInfo.t_enumerator))
- ? info.getTypeSymbol()
- : typeSymbol.getForwardSymbol();
-
- returnInfo.addPtrOperator( info.getPtrOperators() );
- returnInfo.setTypeBits( ( returnInfo.getTypeBits() | info.getTypeBits() ) & ~ITypeInfo.isTypedef & ~ITypeInfo.isForward );
- info = typeSymbol.getTypeInfo();
- if( ++j > TYPE_LOOP_THRESHOLD ){
- if( infoProvider != null )
- infoProvider.returnTypeInfo( returnInfo );
- throw new ParserSymbolTableError();
- }
- }
-
- if( info.isType( ITypeInfo.t_class, ITypeInfo.t_enumeration ) || info.isType( ITypeInfo.t_function ) ){
- returnInfo.setType( ITypeInfo.t_type );
- returnInfo.setTypeSymbol( typeSymbol );
- } else {
- returnInfo.setTypeBits( ( returnInfo.getTypeBits() | info.getTypeBits() ) & ~ITypeInfo.isTypedef & ~ITypeInfo.isForward );
- returnInfo.setType( info.getType() );
- returnInfo.setTypeSymbol( null );
- returnInfo.addPtrOperator( info.getPtrOperators() );
- }
- if( returnInfo.isType( ITypeInfo.t_templateParameter ) ){
- returnInfo.setTypeSymbol( typeSymbol );
- }
-
- if( topInfo.hasPtrOperators() ){
- returnInfo.addPtrOperator( topInfo.getPtrOperators() );
- }
- } else {
- if( infoProvider != null ){
- returnInfo = infoProvider.getTypeInfo( topInfo.getType() );
- returnInfo.copy( topInfo );
- } else
- returnInfo = TypeInfoProvider.newTypeInfo( topInfo );
- }
-
- return returnInfo;
- }
-
- private IContainerSymbol _compilationUnit;
- private ParserLanguage _language;
- private TypeInfoProvider _typeInfoProvider;
- private ParserMode _mode;
-
- public void setLanguage( ParserLanguage language ){
- _language = language;
- }
-
- public ParserLanguage getLanguage(){
- return _language;
- }
-
- public ParserMode getParserMode(){
- return _mode;
- }
-
- public TypeInfoProvider getTypeInfoProvider(){
- return _typeInfoProvider;
- }
-
-// protected void pushCommand( Command command ){
-// undoList.addFirst( command );
-// }
-
-// public Mark setMark(){
-// Mark mark = new Mark();
-// undoList.addFirst( mark );
-// markSet.add( mark );
-// return mark;
-// }
-
-// public boolean rollBack( Mark toMark ){
-// if( markSet.contains( toMark ) ){
-// markSet.remove( toMark );
-// Command command = ( Command )undoList.removeFirst();
-// while( command != toMark ){
-// command.undoIt();
-// command = ( Command ) undoList.removeFirst();
-// }
-//
-// return true;
-// }
-//
-// return false;
-// }
-
-// public boolean commit( Mark toMark ){
-// if( markSet.contains( toMark ) ){
-// markSet.remove( toMark );
-// Command command = ( Command )undoList.removeLast();
-// while( command != toMark ){
-// command = (Command) undoList.removeLast();
-// }
-// return true;
-// }
-//
-// return false;
-// }
-
-// static abstract protected class Command{
-// abstract public void undoIt();
-// }
-//
-// static public class Mark extends Command{
-// public void undoIt(){ }
-// }
-
-
-
- static protected class LookupData
- {
- protected static final TypeFilter ANY_FILTER = new TypeFilter( ITypeInfo.t_any );
- protected static final TypeFilter CONSTRUCTOR_FILTER = new TypeFilter( ITypeInfo.t_constructor );
- protected static final TypeFilter FUNCTION_FILTER = new TypeFilter( ITypeInfo.t_function );
-
- public String name;
- public Map usingDirectives;
- public ObjectSet visited = new ObjectSet(0); //used to ensure we don't visit things more than once
- public ObjectSet inheritanceChain; //used to detect circular inheritance
- public ISymbol templateMember; //to assit with template member defs
-
- public boolean qualified = false;
- public boolean ignoreUsingDirectives = false;
- public boolean usingDirectivesOnly = false;
- public boolean forUserDefinedConversion = false;
- public boolean exactFunctionsOnly = false;
- public boolean returnInvisibleSymbols = false;
-
- public Map foundItems = null;
-
- public LookupData( String n ){
- name = n;
- }
-
- //the following function are optionally overloaded by anonymous classes deriving from
- //this LookupData
- public boolean isPrefixLookup(){ return false;} //prefix lookup
- public Set getAmbiguities() { return null; }
- public void addAmbiguity(String n ) { /*nothing*/ }
- public List getParameters() { return null; } //parameter info for resolving functions
- public ObjectSet getAssociated() { return null; } //associated namespaces for argument dependant lookup
- public ISymbol getStopAt() { return null; } //stop looking along the stack once we hit this declaration
- public List getTemplateParameters() { return null; } //template parameters
- public TypeFilter getFilter() { return ANY_FILTER; }
- }
-
-
- static protected class Cost
- {
-
- public Cost( TypeInfoProvider provider, ITypeInfo s, ITypeInfo t ){
- if( s != null ){
- source = provider.getTypeInfo( s.getType() );
- source.copy( s );
- }
- if( t != null ){
- target = provider.getTypeInfo( t.getType() );
- target.copy( t );
- }
- }
-
- private ITypeInfo source;
- private ITypeInfo target;
-
- public boolean targetHadReference = false;
-
- public int lvalue;
- public int promotion;
- public int conversion;
- public int qualification;
- public int userDefined;
- public int rank = -1;
- public int detail;
-
- //Some constants to help clarify things
- public static final int AMBIGUOUS_USERDEFINED_CONVERSION = 1;
-
- public static final int NO_MATCH_RANK = -1;
- public static final int IDENTITY_RANK = 0;
- public static final int LVALUE_OR_QUALIFICATION_RANK = 0;
- public static final int PROMOTION_RANK = 1;
- public static final int CONVERSION_RANK = 2;
- public static final int DERIVED_TO_BASE_CONVERSION = 3;
- public static final int USERDEFINED_CONVERSION_RANK = 4;
- public static final int ELLIPSIS_CONVERSION = 5;
-
- public void release( TypeInfoProvider provider ){
- provider.returnTypeInfo( getSource() );
- provider.returnTypeInfo( getTarget() );
- }
-
- public int compare( Cost cost ){
- int result = 0;
-
- if( rank != cost.rank ){
- return cost.rank - rank;
- }
-
- if( userDefined != 0 || cost.userDefined != 0 ){
- if( userDefined == 0 || cost.userDefined == 0 ){
- return cost.userDefined - userDefined;
- }
- if( (userDefined == AMBIGUOUS_USERDEFINED_CONVERSION || cost.userDefined == AMBIGUOUS_USERDEFINED_CONVERSION) ||
- (userDefined != cost.userDefined ) )
- return 0;
-
- // else they are the same constructor/conversion operator and are ranked
- //on the standard conversion sequence
-
- }
-
- if( promotion > 0 || cost.promotion > 0 ){
- result = cost.promotion - promotion;
- }
- if( conversion > 0 || cost.conversion > 0 ){
- if( detail == cost.detail ){
- result = cost.conversion - conversion;
- } else {
- result = cost.detail - detail;
- }
- }
-
- if( result == 0 ){
- if( cost.qualification != qualification ){
- return cost.qualification - qualification;
- } else if( (cost.qualification == qualification) && qualification == 0 ){
- return 0;
- } else {
- int size = cost.getTarget().hasPtrOperators() ? cost.getTarget().getPtrOperators().size() : 0;
- int size2 = getTarget().hasPtrOperators() ? getTarget().getPtrOperators().size() : 0;
-
- ListIterator iter1 = cost.getTarget().getPtrOperators().listIterator( size );
- ListIterator iter2 = getTarget().getPtrOperators().listIterator( size2 );
-
- ITypeInfo.PtrOp op1 = null, op2 = null;
-
- int subOrSuper = 0;
- for( int i = ( size < size2 ) ? size : size2; i > 0; i-- ){
- op1 = (ITypeInfo.PtrOp)iter1.previous();
- op2 = (ITypeInfo.PtrOp)iter2.previous();
-
- if( subOrSuper == 0)
- subOrSuper = op1.compareCVTo( op2 );
- else if( ( subOrSuper > 0 && ( op1.compareCVTo( op2 ) < 0 )) ||
- ( subOrSuper < 0 && ( op1.compareCVTo( op2 ) > 0 )) )
- {
- result = -1;
- break;
- }
- }
- if( result == -1 ){
- result = 0;
- } else {
- if( size == size2 ){
- result = subOrSuper;
- } else {
- result = size - size2;
- }
- }
- }
- }
-
- return result;
- }
-
- /**
- * @return Returns the source.
- */
- public ITypeInfo getSource() {
- return source;
- }
-
- /**
- * @return Returns the target.
- */
- public ITypeInfo getTarget() {
- return target;
- }
- }
-
- /**
- * The visibility of the symbol is modified by the visibility of the base classes
- * @param symbol
- * @param qualifyingSymbol
- * @return
- */
- public static ASTAccessVisibility getVisibility(ISymbol symbol, IContainerSymbol qualifyingSymbol){
-
- IContainerSymbol container = symbol.getContainingSymbol();
- if( qualifyingSymbol == null || container.equals( qualifyingSymbol ) ){
- ISymbolASTExtension extension = symbol.getASTExtension();
- IASTNode node = extension != null ? extension.getPrimaryDeclaration() : null;
- if( node != null && node instanceof IASTMember ){
- return ((IASTMember)node).getVisiblity();
- }
- throw new ParserSymbolTableError( ParserSymbolTableError.r_InternalError );
- }
-
- if( ! (qualifyingSymbol instanceof IDerivableContainerSymbol) ){
- return ASTAccessVisibility.PUBLIC;
- }
-
- List parents = ((IDerivableContainerSymbol) qualifyingSymbol).getParents();
- int numParents = parents.size();
- IParentSymbol parent = null;
- ASTAccessVisibility symbolAccess = null;
- ASTAccessVisibility parentAccess = null;
-
- for( int i = 0; i < numParents; i++ ){
- parent = (IParentSymbol) parents.get(i);
-
- if( container == parent.getParent() ){
- parentAccess = parent.getAccess();
- symbolAccess = ((IASTMember)symbol.getASTExtension().getPrimaryDeclaration()).getVisiblity();
-
- return ( parentAccess.isGreaterThan( symbolAccess ) )? parentAccess : symbolAccess;
- }
- }
-
- //if static or an enumerator, the symbol could be visible through more than one path through the heirarchy,
- //so we need to check all paths
- boolean checkAllPaths = ( symbol.isType( ITypeInfo.t_enumerator ) || symbol.getTypeInfo().checkBit( ITypeInfo.isStatic ) );
- ASTAccessVisibility resultingAccess = null;
- for( int i = 0; i < numParents; i++ ){
- parent = (IParentSymbol) parents.get(i);
- parentAccess = parent.getAccess();
-
- ISymbol tmp = parent.getParent();
- if( tmp instanceof IDeferredTemplateInstance )
- tmp = ((IDeferredTemplateInstance)tmp).getTemplate().getTemplatedSymbol();
- else if( tmp instanceof ITemplateSymbol ){
- tmp = ((ITemplateSymbol)tmp).getTemplatedSymbol();
- }
-
- if( !( tmp instanceof IContainerSymbol ) )
- return null;
-
- symbolAccess = getVisibility( symbol, (IContainerSymbol) tmp );
-
- if( symbolAccess != null ){
- symbolAccess = ( parentAccess.isGreaterThan( symbolAccess ) ) ? parentAccess : symbolAccess;
- if( checkAllPaths ){
- if( resultingAccess != null )
- resultingAccess = resultingAccess.isGreaterThan( symbolAccess ) ? symbolAccess : resultingAccess;
- else
- resultingAccess = symbolAccess;
- } else {
- return symbolAccess;
- }
- }
- }
- return resultingAccess;
- }
-}

Back to the top