tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Tinycc-devel] Why missing #includes don't cause warning/fail?


From: Thomas Preud'homme
Subject: Re: [Tinycc-devel] Why missing #includes don't cause warning/fail?
Date: Sun, 29 Jun 2014 17:12:11 +0800
User-agent: KMail/4.12.4 (Linux/3.14-1-amd64; KDE/4.13.1; x86_64; ; )

Le samedi 31 mai 2014, 16:27:32 David Mertens a écrit :
> I have encountered this behavior before as well. I am pretty sure that the
> compiler is making a guess as to the form of the function based on how it's
> called. Then, it links to libc by default, so it is able to link against
> those functions without trouble. If you enable certain warnings (not sure
> which ones off the top of my head), tcc will complain about this behavior.

TL;DR: a function not defined will be assumed to return an int and no check 
will be performed on its arguments. When linking, the function will be found 
if it is part of the libc. See below for a more complete explanation if you 
are interested.

The code responsible for this is in unary(void) just after the label 
tok_identifier:

        s = sym_find(t);

We search a symbol with that name

        if (!s) {

We cannot find such a symbol

            const char *name = get_tok_str(t, NULL);
            if (tok != '(')
                tcc_error("'%s' undeclared", name);

For variable, this is a hard error and tcc stops right now.

            /* for simple function calls, we tolerate undeclared
               external reference to int() function */
            if (tcc_state->warn_implicit_function_declaration
#ifdef TCC_TARGET_PE
                /* people must be warned about using undeclared WINAPI 
functions
                   (which usually start with uppercase letter) */
                || (name[0] >= 'A' && name[0] <= 'Z')
#endif
            )
                tcc_warning("implicit declaration of function '%s'", name);

A warning is emitted if -Wall is specified (-Wall enable several warning, 
including this one).

            s = external_global_sym(t, &func_old_type, 0); 
        }

Consider the function is an int() one, that is a function that returns an int 
and take any parameter. func_old_type is defined in libtcc.c:

    func_old_type.t = VT_FUNC;
    func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);

Int_type is the return type. FUNC_OLD is the interesting part as it indicates 
that it is compatible with any function, no matter the parameters. This check 
is done in is_compatible_func:

    if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
        return 1;

If one of the two compared function is FUNC_OLD, return 1 to say it's 
compatible.

This is for the compilation. As you noticed, it also passes linkage. The 
reason is that in -run functionality, tcc will resolve functions by way of 
dlsym (on Unices, on Windows it's probably a similar mechanism). So since tcc 
is linked with libc, any function part of libc will be found and there will be 
no error.

If you appreciated this detailed description let me know and I'll try to do 
such a detailed analysis with code snipped on some other occasions. Some 
people who want to contribute to tcc could learn a bit about its internals.

Best regards,

Thomas

Attachment: signature.asc
Description: This is a digitally signed message part.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]