http://llvm.org/bugs/show_bug.cgi?id=7263
Summary: friend declaration confuses name lookup
Product: clang
Version: trunk
Platform: PC
OS/Version: All
Status: NEW
Severity: normal
Priority: P
Component: C++
AssignedTo: [email protected]
ReportedBy: [email protected]
CC: [email protected], [email protected]
During building of the pango 1.28.0 port on FreeBSD, we encountered the
following fragment of code that gave compile errors with clang, but not
with gcc:
========================================
struct LookupSubTable {
};
struct Extension {
const LookupSubTable& get_subtable (void) const;
};
struct ExtensionSubst : Extension {
friend struct SubstLookupSubTable;
inline const struct SubstLookupSubTable& get_subtable (void) const {
return (*(reinterpret_cast<const SubstLookupSubTable
*>((reinterpret_cast<const char *>(&(Extension::get_subtable ()))) + 0)));
}
};
========================================
which produces (with llvm/clang r105165):
pangotest.cpp:11:38: error: unknown type name 'SubstLookupSubTable'
return (*(reinterpret_cast<const SubstLookupSubTable
*>((reinterpret_cast<const char *>(&(Extension::get_subtable ()))) + 0)));
^
pangotest.cpp:11:12: error: reference to type 'struct SubstLookupSubTable
const' could not bind to an lvalue of type 'char const'
return (*(reinterpret_cast<const SubstLookupSubTable
*>((reinterpret_cast<const char *>(&(Extension::get_subtable ()))) + 0)));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The fragment can be further reduced to (thanks Benjamin):
class Bar {
friend class Foo;
class Foo *test() { return (Foo *)0; }
};
giving:
friendtest1.cpp:3:31: error: use of undeclared identifier 'Foo'
class Foo *test() { return (Foo *)0; }
^
Which compiles fine with gcc 4.2.1 (the FreeBSD default compiler), but
also MS VC++ has no problems with it.
This issue is similar to, but not exactly the same as bug 6759: the
"friend class Foo" line is apparently NOT enough to fully declare class
Foo, however the "class Foo *test()" function declaration should be.
In fact, this fragment compiles fine:
class Bar {
class Foo *test() { return (Foo *)0; }
};
so adding the "friend class Foo" really seems to change something in the
name lookup.
It gets even stranger when using a fully specified return type in the
member function:
class Bar {
friend class Foo;
class Foo *test() { return (class Foo *)0; }
};
resulting in:
friendtest2.cpp:3:30: error: cannot initialize return object of type 'class Foo
*' with an rvalue of type 'class Foo *'
class Foo *test() { return (class Foo *)0; }
^~~~~~~~~~~~~~
which is, though quite funny, a rather confusing error message. :)
--
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.
_______________________________________________
LLVMbugs mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/llvmbugs