[LLVMbugs] [Bug 7185] template evaluated to early

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Fri May 21 03:24:23 PDT 2010


http://llvm.org/bugs/show_bug.cgi?id=7185

Chandler Carruth <chandlerc at gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |chandlerc at gmail.com
         Resolution|                            |INVALID

--- Comment #1 from Chandler Carruth <chandlerc at gmail.com> 2010-05-21 05:24:23 CDT ---
(In reply to comment #0)
> I am not sure if this is a bug.

I'm pretty sure Clang is correct here. I'll try to explain...

> Given the code below, clang states that the function hash is not know. But
> doesn't the C++ standard say, that template expressions are only evaluated
> where they are used?

While this is true, the *name lookup* is more complicated than that. See
[temp.dep.res] 14.6.4 in C++'03 for the details of this. The idea is called
two-phase name lookup -- some names are looked up in the context of the
template definition, others in the context of the instantiation. Even for names
which are dependent (can change based on instantiation due to a type-dependent
expression as an argument), they will not in all cases find names which occur
after the template definition. Let's look at your specific case:

> template <class T>
> struct Hash
>         /// A generic hash function.
> {
>         std::size_t operator () (T value) const
>                 /// Returns the hash for the given value.
>         {
>                 return hash(value);

'value' is type-dependent here, and so 'hash' is a dependent name, so we
*might* consider names only visible in the instantiation context, but...

>         }
> };
> 
> std::size_t Foundation_API hash(Int8 n);

In order for an instantiation to see this declaration for the name 'hash', it
must find it when searching associated namespaces, not via the usual
unqualified-id name lookup. The latter only sees names visible in the template
definition's context. ([temp.dep.candidate] 14.6.4.2)

For the search of associated namespaces to find this declaration, its
argument's type must contribute the namespace in which this function is
declared to the set searched. I assume that 'Int8' is a typedef. However,
C++'03 [basic.lookup.koenig] 3.4.2/2 says "Typedef names and using-declarations
used to specify the types do not contribute to this set." and the first bullet
point in that paragraph goes on to say "If T is a fundamental type, its
associated sets of namespaces and classes are both empty." Because of this I
don't think any associated namespaces will be contributed from the arguments to
this function, and thus this declaration cannot be found.

This is an area where GCC is known to be exceedingly lax, but Clang tries very
hard to precisely enforce the standard's requirements of name lookup. 

Hope this helps! (And if I've missed anything I'm sure dgregor or others will
chime in.)
-Chandler

-- 
Configure bugmail: http://llvm.org/bugs/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.



More information about the llvm-bugs mailing list