ISO C Proposal:
Function Aliases


By David R. Tribble

Revision: Draft 6, 2000-12-28

 This document is still under construction

Contents


Cover Sheet

                    Document Number:  WG14 N___/X3J11 __-___

                              C200X Revision Proposal
                              =======================

 Title:              Function Aliases
 Author:             David R. Tribble
 Author Affiliation: Self
 Postal Address:     #################
                     Plano, TX ##########
                     USA
 E-mail Address:     david@tribble.com
 Web URL:            http://david.tribble.com
 Telephone Number:   +1 972 943 5125 (15:00-00:00 Z)
                     +1 ############ (00:00-03:00 Z)
 Fax Number:         +1 972 943 5111
 Sponsor:            ________________________________________
 Revision:           Draft 6
 Date:               2000-12-28
 Supersedes:         None
 Proposal Category:
    __ Editorial change/non-normative contribution
    __ Correction
    X_ New feature
    __ Addition to obsolescent feature list
    __ Addition to Future Directions
    __ Other (please specify)  _____________________________
 Area of Standard Affected:
    __ Environment
    X_ Language
    __ Preprocessor
    __ Library
       __ Macro/typedef/tag name
       __ Function
       X_ Header
    __ Other (please specify)  _____________________________
 Prior Art:          C++ function overloading, and
                     C99 type-generic function macros (<tgmath.h>).
 Target Audience:    C programmers.
 Related Documents (if any): None
 Proposal Attached: X_ Yes __ No, but what's your interest?
 Abstract:
    The addition of language syntax to provide function aliases, which are
    akin to C++ overloaded functions but without any of the complications to
    the linker model.  This feature will also provide for an efficient,
    standard means of implementing the type-generic function macros defined
    in <tgmath.h>.


Problem Description

Problem 1

There is a desire to provide a language feature similar in functionality to the function overloading feature provided in C++, i.e., a mechanism to allow for the definition of more than one function having the same identifier but different prototypes.

Problem 2

There is a desire to provide a language feature that allows for an efficient, standard way to implement the type-generic function macros declared in the <tgmath.h> header. These macros are essentially overloaded functions, having the same number of parameters but of different primitive types.


Summary

There is a desire to provide a method for overloading function names. This would allow the same identifier to be used for more than one function, i.e., to provide for multiple definitions of the same function, each having different parameter prototypes.

For example, a programmer might have a group of functions with similar functionality, but with different parameter types. Defining aliases for the functions, all with the same identifier, unifies them into a single group.

    extern double  log2_d(double x);
    extern float   log2_d(float x);
    extern long    log2_l(long x);

    _Alias double  log2(double x) = log2_d;
    _Alias float   log2(float x) =  log2_f;
    _Alias long    log2(long x) =   log2_l;

These alias definitions provide set set of functions, all with the same identifier (log2), and all distiguished by their parameter types. Each alias invokes a different function, depending on the types of its parameters.


Terms

The following terms are used throughout this proposal.

alias
Same as function alias.

call-compatible
A function call expression is call-compatible with a particular function if the expression has the same number of arguments as the function has parameters, and each argument of the expression is assignment-compatible with the corresponding parameter of the function. A function having a trailing ellipsis ('...') parameter is considered to have any number of parameters of any type. Any arguments in the call expression that correspond to the ellipsis parameter of a function (i.e., arguments beyond the fixed parameters preceding the ellipsis parameter) are assignment-compatible with the ellipsis parameter, regardless of their type (other than type void), and are assumed to be subject to default argument type promotions. Functions with no prototype information are call-compatible with any function call expression, and the arguments are assumed to be subject to default argument type promotions.

call expression
Same as function call expression.

designated replacement function
The function identifier that is specified in the replacement portion of an alias definition. This can be the name of a function (a.k.a. a regular function), or the name of another alias that resolves to a function identifier. In either case, the function must have a declaration with a prototype in scope at the point of the alias definition.

exact type match
A given function or alias parameter or call expression argument type exactly matches a second parameter type of another function or alias if no type conversions are required (other than the usual array-to-pointer and function-to-pointer decay conversions) to assign an object of the first type to an object of the second type.

function alias
A definition of an identifier, called an alias, that acts like a function identifier, but which is associated with another function identifier, called a replacement function. The alias has a signature and return type identical to its replacement function. After the point of the alias definition, the alias identifier is treated like a function identifier in all subsequent function call expressions. Multiple alias definitions can be provided for the same identifier, but each must have a prototype different from all other alias definitions of the same identifier. (We use the term function alias to distinguish the concept from other concepts, such as pointer alias. In this proposal, the term alias by itself is synonymous with function alias.)

function call expression
A postfix expression signifying the invocation of a function. The function designated by the expression (i.e., the left operand of the postfix expression) may be a function identifier or a function alias identifier.

function signature
The number and types of parameters of a function or alias as specified by its prototype. Any cv-qualifiers that directly modify the parameters are not included in the signature. Parameters of function types and array types that are not variable-length are equivalent to pointer types. Parameters of structure, union, or enumeration types having different tags have different types. An empty function prototype conveys no parameter type information, and has no corresponding signature (a.k.a. an empty signature). The signature does not include the return type of the function. Functions may be referred to unambiguously without specifying their signatures, e.g. sin(). Aliases may be referred to as a group by omitting the signature, e.g., foo(), or referred to individually by including a specific signature, e.g., foo(int).

prototype matching
The process of applying rules for determining the best matching alias or function to the function identifier designated in a function call expression. If an appropriate unique match is found, the call is replaced by an invocation of a function.

regular function
A function that is not a function alias (i.e., a static, extern, or inline function). Normally, we use the term function by itself to specify a regular function, which is distinct from the term function alias.

replacement function
Same as designated replacement function.

signature
Same as function signature.


Syntax

The following reserved keyword [ISO § 6.4.1] is added to the language:

_Alias

The following syntactic item [ISO § 6.7.1] is altered thus:

storage-class-specifier:
auto
extern
register
static
_Alias

[[ Alternatively, the syntax [ISO § 6.7.4] could be altered thus:

function-specifier:
inline
_Alias
]]

For convenience, this is shown here as being effectively the same syntax as:

function-alias-definition:
_Alias  function-declarator  =  identifier  ;
 
function-declarator:
declaration-specifiers  direct-declarator  (  parameter-list  )

A function-specifier of _Alias shall be used only in the definition of an alias.

The declarator of an alias definition specifies the name of an alias. Such a declarator shall have a (non-empty) prototype.

The initializer expression following the '=' operator in an alias definition shall evaluate to a single identifier, and is known as the designated replacement function of the alias.

The function-declarator in the alias definition must contain a non-empty prototype. The prototype specifies the signature of the alias, and also specifies the expected signature for the designated replacement function.

[ Rationale:
It is sufficient to specify only the name of the replacement function, since the prototype of the alias fully specifies the expected signature of the replacement function.
-End. ]

[ Rationale:
The return type and prototype information is not technically necessary in order to establish an association between an alias and its designated replacement function. By requiring an alias definition to specify a prototype, however, there is less chance for programmer error, specifically, the error of specifying an incorrectly matching signature for a given replacement function will be caught at compilation time.

While requiring a prototype to appear on the alias might seem redundant, it is advantageous for the programmer. Without a prototype, the programmer would need to search back in the source stream, perhaps among several header files, to find the parameter type information for the replacement function and thus also for the alias itself.
-End. ]

Examples

    extern int          qstat(void);
    extern double       sin(double x);
    extern float        sinf(float x);
    extern long double  sinl(long double x);
    extern void         pr(char *f, ...);
    extern int          setf(int (*f)(int));
    extern void         setCol(enum Color col);
    extern int          (*getf(int n))(int i);

    _Alias int          foo(void) =             qstat;  // A
    _Alias double       foo(double x) =         sin;    // B
    _Alias float        foo(float a) =          sinf;   // C
    _Alias long double  foo(long double d) =    sinl;   // D
    _Alias void         bar(char *c, ...) =     pr;     // E
    _Alias void         foo(char *s, ...) =     bar;    // F
    _Alias int          foo(int (*)(int i)) =   setf;   // G
    _Alias void         foo(enum Color c) =     setCol; // H
    _Alias int          (*foo(int i))(int j) =  getf;   // I 


Semantics


Examples

Example 1

Aliases are generally useful for defining sets of functions with similar functionality.

    extern void swap_i(int *a, int *b);
    extern void swap_l(long *a, long *b);
    extern void swap_f(float *a, float *b);
    extern void swap_f(double *a, double *b);
    extern void swap_t(struct T *a, struct T *b);

    _Alias void swap(int *a, int *b) =            swap_i;
    _Alias void swap(long *a, long *b) =          swap_l;
    _Alias void swap(float *a, float *b) =        swap_f;
    _Alias void swap(double *a, double *b) =      swap_d;
    _Alias void swap(struct T *a, struct T *b) =  swap_t; 

Example 2

The type-generic function macros defined in the standard <tgmath.h> header [ISO § 7.22] are ideal examples of groups of functions with similar functionality. Here is a possible implementation for them that uses aliases.

    // Sample partial <tgmath.h> implementation

    #include <math.h>
    #include <complex.h>

    /* Functions declared:
    *   extern double               sin(double x);                // A
    *   extern float                sinf(float x);
    *   extern long double          sinld(long double);
    *   extern complex double       csin(complex double x);
    *   extern complex float        csinf(complex float x);
    *   extern complex long double  csinld(complex long double x);
    */

    // Define aliases
    _Alias float               __tg_sin(float x)                  // B
        = sinf;
    _Alias complex double      __tg_sin(complex double x)         // C
        = csin;
    _Alias complex float       __tg_sin(complex float x)          // D
        = csinf;
    _Alias complex long double __tg_sin(complex long double x)    // E
        = csinld;

    // Define helper functions
    static inline double __tg_sin_i(int x)
    { return sin((double) x); }

    static inline double __tg_sin_ui(unsigned int x)
    { return sin((double) x); }

    static inline double __tg_sin_l(long x)
    { return sin((double) x); }

    static inline double __tg_sin_ul(unsigned long x)
    { return sin((double) x); }

    static inline double __tg_sin_ll(long long x)
    { return sin((double) x); }

    static inline double __tg_sin_ull(unsigned long long x)
    { return sin((double) x); }

    // Define aliases involving default type promotions
    _Alias double __tg_sin(int x) =                __tg_sin_i;    // F
    _Alias double __tg_sin(unsigned int x) =       __tg_sin_ui;   // G
    _Alias double __tg_sin(long x) =               __tg_sin_l;    // H
    _Alias double __tg_sin(unsigned long x) =      __tg_sin_ul;   // I
    _Alias double __tg_sin(long long x) =          __tg_sin_ll;   // J
    _Alias double __tg_sin(unsigned long long x) = __tg_sin_ull;  // K

    // Define type-generic function macros
    #define sin(x)  __tg_sin(x)

    ...and so forth for the other type-generic macros... 

The following code illustrates the use of these function macros:

    #include <tgmath.h>

    // Use the aliases
    void tgcalls()
    {
        double          x;
        complex double  z;
        double          (*f)(double x);

        x = sin(17.8);                // 1. Matches A, calls sin()
        x = sin(43.6f);               // 2. Matches B, calls sinf()
        x = sin(87);                  // 3. Matches F, calls sin()
        z = sin(19.2 + I*37.3);       // 4. Matches C, calls csin()
        z = sin(21.0f + I*44.5f);     // 5. Matches D, calls csinf()
        x = (sin)(32.1f);             // 6. Matches A, calls sin()
        f = sin;                      // 7. Matches A, &sin
    } 

In case 1, sin() is passed an argument of type double, which matches alias A exactly, so sin() is called.

In case 2, the argument is of type float, which matches alias B exactly, so sinf() is called.

In case 3, the argument is of type int, which matches alias F exactly, so helper function __tg_sin_i() is called, which in turn calls sin().

(The ISO rules [ISO § 7.22, paragraph 3] imply that integer arguments, i.e., arguments that are not one of the floating-point types of the appropriate library math functions, result in the function taking a float parameter to be invoked. However, the ISO example [ISO § 7.22, paragraph 7] implies that calls with integer arguments cause the regular library functions, which take parameters of type double, to be invoked. We have included code here to show one possible method for implementing such calls, which assumes the latter semantics and converts the arguments to type double.)

In case 4, the argument is of type complex double, which matches alias C exactly, so csin() is called.

In case 5, the argument is of type complex float, which matches alias D exactly, so csinf() is called.

In case 6, the identifier sin is parenthesized, so the preprocessor macro identifier is no longer visible. Thus the regular function sin() is called after converting the float argument to type double.

In case 7, the identifier sin by itself refers to the address of function sin(), which is then assigned to the function pointer variable f. (There is no conflict here because the macro named sin is not followed by a parenthesized argument list, and thus the identifier refers only to the regular function named sin.)

Example 3

The following code is another example of using a combination of aliases and inline helper functions.

    // Type-generic output functions

    #include <stddef.h>
    #include <stdio.h>

    static inline int output_i(long x)
    {
        return printf("%ld", x);
    }

    static inline int output_f(double x)
    {
        return printf("%lf", x);
    }

    static inline int output_p(const void *x)
    {
        return printf("%p", x);
    }

    static inline int output_s(const char *x)
    {
        return printf("%s", x);
    }

    static inline int output_s2(const char *x, size_t m)
    {
        return printf("%.*s", m, x);
    }

    static inline int output_s3(const char *x, size_t w, size_t m)
    {
        return printf("%*.*s", w, m, x);
    }

    _Alias int output(long x) =        output_i;           // A
    _Alias int output(double x) =      output_f;           // B
    _Alias int output(const void *x) = output_p;           // C

    _Alias int output(const char *x)                       // D
        = output_s;
    _Alias int output(const char *x, size_t m)             // E
        = output_s2;
    _Alias int output(const char *x, size_t w, size_t m)   // F
        = output_s3; 

Example uses of these aliases:


    void print_some(struct Buf *bp, const char *id)
    {
        output(42);             // 1. Calls output_i()
        output(38L);            // 2. Calls output_i()
        output(3.14);           // 3. Calls output_d()
        output(+6.22e+22f);     // 4. Calls output_d()
        output(bp);             // 5. Calls output_p()
        output("abc");          // 6. Calls output_s()
        output(id, 8);          // 7. Calls output_s2()
        output(bp->name, 8, sizeof(bp->name));
                                // 8. Calls output_s3()
    } 

Example 4

Aliases can be overloaded such that different numbers of arguments in function call expressions cause different functions to be invoked.

    // Declare functions
    extern int  sys_open(const char *fn, int mode);
    extern int  sys_create(const char *fn, int mode, int perm);

    // Define aliases
    _Alias int openf(const char *fn, int m)          // A
        = sys_open;
    _Alias int openf(const char *fn, int m, int p)   // B
        = sys_create;

    // Use the aliases
    void test(const char *name, int mode, int perm)
    {
        int     fd;

        fd = openf(name, mode);         // 1. Calls sys_open()
        fd = openf(name, mode, perm);   // 2. Calls sys_create()
    } 

Example 5

Aliases can be combined with inline functions to produce interesting replacements, such as argument reordering and the supplying of default argument values.

    extern int sysfunc(int op, void *a, void *b);

    static inline int syscall_readb(char *buf, int len)
    {
        // Provide default argument values and argument reordering
        return sysfunc(SYS_READ, &len, buf);
    }

    static inline int syscall_read1(char *buf)
    {
        int     len = 1;

        // Provide default argument values and argument reordering
        return sysfunc(SYS_READ, &len, buf);
    }

    static inline int syscall_readc(void)
    {
        int     len = 1;
        char    ch;

        // Provide default argument values and argument reordering
        sysfunc(SYS_READ, &len, &ch);
        return ch;
    }

    _Alias int read(char *buf, int len) = syscall_readb;
    _Alias int read(char *buf) =          syscall_read1;
    _Alias int read(void) =               syscall_readc; 

Example 6

This is another example of using aliases and inline forwarding functions to simulate default arguments.

    extern Rect * makeRect(int x, int y, int width, int height);  // A

    static inline Rect * makeRect2(int w, int h)
    {
        // Provide default X and Y coordinate values
        return makeRect(0, 0, w, h);
    }

    _Alias Rect * makeRect(int w, int h) = makeRect2;             // B

    void make(int w, int h)
    {
        Rect *  r;

        r = makeRect(10, 20, w, h);     // 1. Okay
        r = makeRect(w, h);             // 2. Okay, default X and Y values
        r = makeRect(17, w, h);         // 3. Error, no match
        r = makeRect(w);                // 4. Error, no match
        r = makeRect();                 // 5. Error, no match
    } 

Example 7

An appropriate combination of aliases and forwarding inline functions can be used to provide functions with return types or parameter types with more restrictive cv-qualifiers.

    extern char *  strchr(const char *s, int c);
    extern void    free(void *p);

    // Define inline helper functions
    static inline const char * my_strchr_c(const char *s, int c)
    {
        // Return type is converted
        return strchr(s, c);
    }

    static inline void my_freec(const char *p)
    {
        // Argument type is converted
        return free((void *) p);
    }

    // Define aliases
    _Alias const char * my_strchr(const char *s, int c)  // A
        = my_strchr_c;

    _Alias void my_free(const char *p) = my_freec;       // B

    // Use the aliases
    void f(char *s)
    {
        const char *  cp = s;

        cp = my_strchr(s,  'a');              // 1. Okay
        cp = my_strchr(cp, 'b');              // 2. Okay

        s =  my_strchr(s,  'c');              // 3. Error
        s =  my_strchr(cp, 'd');              // 4. Error

        my_free(s);                           // 5. Okay
        my_free(cp);                          // 6. Okay
    } 

Example 8-A

Aliases can be defined having the same name as existing regular functions by using separately compiled translation units and extern helper functions.

    //----------------------------------------
    // mysin.c 

    extern double sin(double x);

    double sin_helper(double n)
    {
        return sin(x);
    }


    //----------------------------------------
    // mysin.h

    extern double sin_helper(double x);
    extern float  sinf(float x);

    _Alias double sin(double x) = sin_helper;   // A
    _Alias float  sin(float x) =  sinf;         // B


    //----------------------------------------
    // code.c

    #include "mysin.h"

    void calls()
    {
        double  (*pf)(double);

        sin(1.50);      // 1. Calls sin_helper(), which calls sin()
        sin(3.14f);     // 2. Calls sinf()
        (sin)(6.28f);   // 3. Calls sinf(), not sin()
        pf = sin;       // 4. &sin_helper
        pf = (sin);     // 5. &sin_helper
    } 

Example 8-B

As in the previous example, an alias can be defined having the same name as an existing regular function by using a preprocessor macro to hide the regular function name. (This method does not require separately compiled files like the previous example.)

    //----------------------------------------
    // mystrchr.h 

    #include <string.h>

    /* Functions declared:
    *   extern char * strchr(const char *s, int c);                 // A
    */

    static inline char * strchr_nc(char *s, int c)
    {
        return strchr(s, c);
    }

    static inline const char * strchr_c(const char *s, int c)
    {
        return strchr(s, c);
    }

    _Alias char *       xstrchr(char *s, int c) = strchr_nc;        // B
    _Alias const char * xstrchr(const char *s, int c) = strchr_c;   // C

    #define strchr  xstrchr


    //----------------------------------------
    // code.c

    #include <string.h>
    #include "mystrchr.h"

    void calls(char *st)
    {
        const char *  cp = st;
        char *        (*pf)(char *, int);

        st = strchr(st, 'a');     // 1. Calls strchr_nc()
        cp = strchr(cp, 'b');     // 2. Calls strchr_c()

        cp = strchr(st, 'c');     // 3. Calls strchr_nc()
        st = strchr(cp, 'd');     // 4. Error, loss of const

        cp = (strchr)(cp, 'e');   // 5. Calls strchr_c()

        pf = strchr;              // 6. &strchr_nc
        pf = (strchr);            // 7. &strchr_nc
    } 

If we use the following directive instead:

    #define strchr(...)  xstrchr(__VA_ARGS__)

then the last cases have slightly different results:

        cp = (strchr)(cp, 'e');   // 5b. Calls strchr() directly

        pf = strchr;              // 6b. &strchr
        pf = (strchr);            // 7b. &strchr 


Notes


Design Constraints

  1. We want to add a feature to the language that is genuinely useful to programmers.

  2. We want such a feature to make sense to programmers. Specifically, the semantics should be reasonably comprehensible and explainable, and the syntax should be relatively straightforward and obvious.

  3. We do not want any new language feature to impose unreasonably heavy burdens on the compiler (or the compiler implementor).

  4. We do not want to create unreasonably heavy additions or changes to the existing standard library.

  5. We want to add to the existing semantic model of the language, but change as few of the existing rules as possible.

  6. We want to add new syntax to the language without changing any of the existing syntax.

  7. We want to limit the syntactic additions to at most one new keyword or punctuator token.

  8. We do not want to change the existing linker model of the language; specifically, we do not want to require the use of name mangling or its moral equivalent, as in C++.

  9. Nothing in the language currently requires the compiler to remember arbitrary sequences of tokens for later use, so any new language feature should not require this either. In other words, we do not want to invent a simple token replacement facility.

  10. We want the new language feature to be designed so that it can be implemented efficiently and incur little or no runtime overhead.

  11. We want to preserve existing (conforming) code. For example, the following code should still compile correctly if aliases are added to the language:
        extern double  foo(double x);
        extern float   bar(float x);
        extern double  baz(double x);
        extern double  ind(double (*func)(double x));
    
        #if DEFINE_ALIASES
        _Alias float   foo(float x) = bar;
        #endif
    
        void works()
        {
            double  x;
            double  (*pf)(double x);
    
            x = foo(1.5);
            x = foo(2.6f);
            x = foo(579);
            pf = foo;
            pf = &foo;
            x = (*pf)(7.8);
            x = ind(foo);
    
            if (foo == baz)
                return;
            if (foo == NULL)
                return;
        } 

  12. Finally, we want any new language feature to abide by the "spirit of C".


Prior Art

Type-Generic Function Macros

The type-generic function macros defined in the standard <tgmath.h> header are effectively overloaded function names. It is unspecified as to what mechanism or syntax is used to support these macros, however. Presumably, they are defined with special identifiers or operators known to the compiler, e.g.:

    // Theoretical <tgmath.h> implementation

    // Note that the '__tg_xxx' names are special identifiers known
    // to the compiler.

    #define cos(x)  __tg_cos(x)
    #define sin(x)  __tg_sin(x)
    #define tan(x)  __tg_tan(x)
    ...etc... 
Or perhaps:
    // Theoretical <tgmath.h> implementation

    // Note that '__typeof()' is a special compiler operator

    extern double      __tg_sin_double(double);
    extern float       __tg_sin_float(float);
    extern long double __tg_sin_long_double(long double);
    ...etc...

    #define __tg_splice(a,b)  a##b

    #define cos(x)  __tg_splice(__tg_cos_, __typeof(x))
    #define sin(x)  __tg_splice(__tg_sin_, __typeof(x))
    #define tan(x)  __tg_splice(__tg_tan_, __typeof(x))
    ...etc... 

C++ Function Overloading

The C++ language provides function overloading. It also supports function templates, which provide another method for overloading functions.

    // C++ code

    extern int        foo();            // A, same as foo(void)
    extern int        foo(int x);       // B
    extern double     foo(double x);    // C

    template <class Type>               // D
    Type foo(Type *x)
    { ... }

    void bar(Dat *p)
    {
        foo();          // 1. Calls A, foo()
        foo(123);       // 2. Calls B, foo(int)
        foo('a');       // 3. Calls B, foo(int)
        foo(1.5);       // 4. Calls C, foo(double)
        foo(2.8f);      // 5. Calls C, foo(double)
        foo(p);         // 6. Calls D, foo<Dat>(Dat*)
    } 

Overloaded functions are distinguished by their signatures, which is essentially their prototypes. A function's return type is not part of its signature.

C++ employs fairly complicated rules for finding the best match for a given call expression from the set of all possible matching functions. Argument promotions and implicit type conversions are considered, as are possible template function instantiations.

Function name overloading and template function instantiation are accomplished in C++ by allowing the compiler to apply name mangling to function names to produce unique linker symbols. Such mangling typically involves combining and mapping the function's name, namespace, class prefix, template parameters, and prototype argument types into a single symbolic identifier. For this reason, C++ reserves all identifiers containing two consecutive underscores (e.g., foo__bar), so that compilers may have at least one symbolic namespace into which they can transfrom overloaded function names.

For example, a C++ compiler might mangle the names of the following overloaded functions as shown:

int foo(void)
=> _foo__i_v

int foo(int x)
=> _foo__i_i

struct Info * void foo(const struct Tag *p, int *i)
=> _foo__PS4Info_PCS3TagPi

void MyInfo::foo<int>(double x, double *y)
=> _6MyInfo_foo__Ti__dPd

True function overloading and function templates are different from function aliases. Overloaded and template function names are mapped into actual symbolic linker identifiers. In contrast, function aliasing simply replaces overloaded function names with calls to regular functions, so no name mangling is performed or necessary.


Resolved Issues

Some issues have been resolved.


Unresolved Issues

There remain a few unresolved issues.


References

  1. ISO/IEC 9899:1999 [§ 6.2.3]
    Name spaces of identifiers.

  2. ISO/IEC 9899:1999 [§ 6.2.5]
    Types.

  3. ISO/IEC 9899:1999 [§ 6.2.7]
    Compatible type and composite type.

  4. ISO/IEC 9899:1999 [§ 6.3]
    Conversions.

  5. ISO/IEC 9899:1999 [§ 6.3.1.8]
    Usual arithmetic conversions.

  6. ISO/IEC 9899:1999 [§ 6.3.2.1]
    Lvalues, arrays, and function designators.

  7. ISO/IEC 9899:1999 [§ 6.4.1]
    Keywords.

  8. ISO/IEC 9899:1999 [§ 6.5.2.2]
    Function calls.

  9. ISO/IEC 9899:1999 [§ 6.5.3.2]
    Address and indirection operators.

  10. ISO/IEC 9899:1999 [§ 6.5.4]
    Cast operators.

  11. ISO/IEC 9899:1999 [§ 6.5.9]
    Equality operators.

  12. ISO/IEC 9899:1999 [§ 6.5.16.1]
    Simple assignment.

  13. ISO/IEC 9899:1999 [§ 6.6]
    Constant expressions.

  14. ISO/IEC 9899:1999 [§ 6.7]
    Declarations.

  15. ISO/IEC 9899:1999 [§ 6.7.1]
    Storage-class specifiers.

  16. ISO/IEC 9899:1999 [§ 6.7.2.3]
    Tags (for structure, union, and enumeration types).

  17. ISO/IEC 9899:1999 [§ 6.7.4]
    Function specifiers.

  18. ISO/IEC 9899:1999 [§ 6.7.5]
    Declarators.

  19. ISO/IEC 9899:1999 [§ 6.7.5.3]
    Function declarators (including prototypes).

  20. ISO/IEC 9899:1999 [§ 6.7.5.3p7] [§ 6.7.5.3p8]
    Implicit pointer conversions of array and function parameters.

  21. ISO/IEC 9899:1999 [§ 6.7.5.3p15]
    Compatible functions.

  22. ISO/IEC 9899:1999 [§ 6.7.8]
    Initialization.

  23. ISO/IEC 9899:1999 [§ ?]
    Assignment-compatible.

  24. ISO/IEC 9899:1999 [§ 6.8]
    Statements and blocks.

  25. ISO/IEC 9899:1999 [§ 6.9p2]
    External declarations (not auto or register).

  26. ISO/IEC 9899:1999 [§ 6.9.1]
    Function definitions.

  27. ISO/IEC 9899:1999 [§ 7.22]
    Type-generic math <tgmath.h>.

  28. ISO/IEC 14882:1998 [§ 13]
    Overloading.


Acknowledgments

Most of the discussion and initial design for function aliasing began as a series of postings on the comp.std.c newsgroup.

The following people were especially helpful in providing inspiration and feedback for this proposal:


Revision History

Draft 6  (2000-12-28)
Incorporated more comments from reviewers, mostly in the "Unresolved Issues" section.
Replaced paragraph numbers with paragraph titles. Changed the keyword to _Alias.
Aliases have block scope instead of file scope.
Aliases cannot have the same name as regular functions.
Redundant identical alias definitions are allowed.
Revised the matching rules.
Added examples demonstrating how to simulate default alias parameters using inline helper functions.
Added examples demonstrating how to simulate different parameter and return type cv-qualifications using inline helper functions.

Draft 5  (2000-12-08)
Incorporated comments from a few reviewers.

Draft 4  (2000-11-25)
Rearranged paragraphs in section Semantics for better flow.
Other syntactic paradigms moved to the Other Issues section.

Draft 3  (2000-11-21)
Added Rationale paragraphs.
Disallowed aliases with empty prototypes.
Used the term signature in place of prototype.

Draft 2  (2000-11-16)
Assumed paradigm I for the function aliasing model.

Draft 1  (2000-11-10)
First draft.


Email comments to the author at david@tribble.com.
The author's home page is at http://david.tribble.com.

This page has been accessed [] times since 2000-11-10 (Draft 1).