Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-dev] name resolution and index bindings

Hello,

After being away from CDT for a while, I am back and I hope to 
resume working on C++ semantics problems.

Currently I am trying to fix a name resolution problem, and I 
could use a little help.

Here is a code snippet that demonstrates the problem:

    struct Cat { void meow(); };
    struct Dog { void woof(); };
    
    template <typename T>
    Dog bar(T);
    
    template <typename T>
    auto foo(T t) -> decltype(bar(t));
    
    Cat bar(int);
    
    int main() {
        auto x = foo(0);  // type of x is deduced as Cat, not Dog...
        x.woof();         // ... causing an error here
    }

In the above code, the type of x should be Dog, due to the way
C++'s two-phase name lookup works:

  1) At the point of definition of 'foo', an unqualified lookup 
     should be performed, which should find the 'bar' template (only), 
     which returns Dog. The non-template 'bar', which returns Cat, 
     should not be found because it is declared after the point
     of definition of 'foo'.
  2) When instantiating 'foo', a second, argument-dependent lookup 
     should be performed at the point of instantiation. Here, the
     non-template 'bar' is now visible, but it is still not matched
     because it is not in any of the argument type's associated
     namespaces.

CDT messes up step (1) in cases where the translation unit has an
index.

This is what happens in the CPPSemantics.resolveBinding() call 
that performs the unqualified lookup of 'bar' in the definition
of 'foo':

If there is no index:
   - lookup() finds two bindings:
       1. a CPPFunctionTemplate representing the template overload of 'bar'
       2. a CPPFunction representing the non-template overload of 'bar'
   - resolveAmbiguities() then filters out bindings for which
     declaredBefore(<binding>, <point of definition>) returns
     false. The CPPFunction gets filtered out this way.
   - The resulting binding is thus the CPPFunctionTemplate, which is correct.

So far, so good. But, if there is an index:

   - lookup() finds four bindings:
       1. a CPPFunctionTemplate representing the template overload of 'bar'
       2. a CPPFunction representing the non-template overload of 'bar'
       3. a CompositeCPPFunctionTemplate representing the template overload of 'bar'
       4. a CompositeCPPFunction representing the non-template overload of 'bar'
   - resolveAmbiguities() filters out the CPPFunction, but not the 
     CompositeCPPFunction, because declaredBefore() cannot determine
     the point of declaration for the CompositeCPPFunction.
   - Overload resolution then chooses the CompositeCPPFunction over the
     templates, and the result if the CompositeCPPFunction, which is incorrect.

I don't understand composite bindings well enough to determine how this
should be resolved.

   - Should lookup() even be returning the composite binding for the 
     non-template function?
   - If so, should resolveAmbiguities() be filtering it out with
     declaredBefore()? If yes, how should declaredBefore() determine where
     the composite binding for the non-template function was declared?

Any help is appreciated.

Thanks,
Nate 		 	   		  

Back to the top