For the purposes of this answer I searched on a very old version on gcc, because it is smaller, and easier to reason about. Implementation in newest versions or in other compilers may be completely different.
The source files searched for can be viewed on opensource.apple.com
gcc has a function is_friend()
, defined in friend.c, which basically returns if a function or a type is a friend. Here is the relevant code for functions:
int
is_friend (type, supplicant)
tree type, supplicant;
{
int declp;
register tree list;
tree context;
if (supplicant == NULL_TREE || type == NULL_TREE)
return 0;
/*
Comment added by me: The following defines are in tree.h
#define TREE_CODE(NODE) ((enum tree_code) (NODE)->common.code)
#define TREE_CODE_CLASS(CODE) tree_code_type[(int) (CODE)]
This is expanded as:
declp = (tree_code_type[(int) (((enum tree_code) (supplicant)->common.code))] == 'd')
*/
declp = (TREE_CODE_CLASS (TREE_CODE (supplicant)) == 'd');
// That is, it will simply search the array for the code of the supplicant and check if it is a function declaration.
if (declp)
/* It's a function decl. */
{
tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type));
tree name = DECL_NAME (supplicant);
tree ctype;
if (DECL_FUNCTION_MEMBER_P (supplicant))
ctype = DECL_CLASS_CONTEXT (supplicant);
else
ctype = NULL_TREE;
for (; list ; list = TREE_CHAIN (list))
{
if (name == FRIEND_NAME (list))
{
tree friends = FRIEND_DECLS (list);
for (; friends ; friends = TREE_CHAIN (friends))
{
if (same_type_p (ctype, TREE_PURPOSE (friends)))
return 1;
if (TREE_VALUE (friends) == NULL_TREE)
continue;
if (supplicant == TREE_VALUE (friends))
return 1;
/* With -fguiding-decls we are more lenient about
friendship. This is bogus in general since two
specializations of a template with non-type
template parameters may have the same type, but
be different.
Temporarily, we are also more lenient to deal
with nested friend functions, for which there can
be more than one FUNCTION_DECL, despite being the
same function. When that's fixed, the
FUNCTION_MEMBER_P bit can go. */
if ((flag_guiding_decls
|| DECL_FUNCTION_MEMBER_P (supplicant))
&& same_type_p (TREE_TYPE (supplicant),
TREE_TYPE (TREE_VALUE (friends))))
return 1;
if (TREE_CODE (TREE_VALUE (friends)) == TEMPLATE_DECL
&& is_specialization_of (supplicant,
TREE_VALUE (friends)))
return 1;
}
break;
}
}
}
else
/* It's a type. */
{
// ...
}
if (declp && DECL_FUNCTION_MEMBER_P (supplicant))
context = DECL_CLASS_CONTEXT (supplicant);
else if (! declp)
/* Local classes have the same access as the enclosing function. */
context = hack_decl_function_context (TYPE_MAIN_DECL (supplicant));
else
context = NULL_TREE;
/* A namespace is not friend to anybody. */
if (context && TREE_CODE (context) == NAMESPACE_DECL)
context = NULL_TREE;
if (context)
return is_friend (type, context);
return 0;
}
Basically, it gets the list of friends of a particular type, and iterates through it, checking if any of them is equal to the function being tested.
Friend functions are added to a type by using similar functions defined in the same source file: add_friend()
, add_friends()
for all member functions of a class, make_friend_class()
for classes, etc.
I'm guessing it uses this function to determine, when checking for access (The moment where it may yell at you for accessing a private member), if the function has access or not.
The answer to your question is(at least for this old version of GCC): The compiler has a list of friends for each class, and iterates this list to determine if a function is a friend(during compile-time, of course.). If it is, it simply grants access. There's no special code generated for this: It is a regular function call.
friend
keyword. The compiler can implement it however it likes, of course. Why would that matter? Normally we're concerned with the difference in compiled output between different compilers. – Josesfriend
function is not like this. It simply influences whether the program will actually compile or not. If you write program that has a function and compiles whether that function isfriend
or not, adding thefriend
keyword has no effect on the compiled output. – Josesfriend
keyword. How it does that is up to the compiler. – Josesfriend
are going to be of a completely different kind of detail than vtables. This reads like "I want to know how sand is used, like how we use axioms to prove theorems" -- it looks like it makes sense, but only if you have no idea what sand, axioms and theorems are. Any analogous answer to your 'like' is a huge stretch. I have no idea what you are asking. – Antungfriend
functions. – Joses